From a3e1619635cec683eea806e18c870fd6d963b986 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Wed, 29 Jan 2025 19:02:54 +0100 Subject: [PATCH 01/51] fix: hyperlinks html entities (#9063) --- packages/excalidraw/data/url.test.tsx | 4 ++-- packages/excalidraw/data/url.ts | 4 ++-- packages/excalidraw/element/embeddable.ts | 12 ++++-------- packages/excalidraw/tests/utils.test.ts | 8 +------- packages/excalidraw/utils.ts | 17 ++++++----------- 5 files changed, 15 insertions(+), 30 deletions(-) diff --git a/packages/excalidraw/data/url.test.tsx b/packages/excalidraw/data/url.test.tsx index e0e07797d..9a40aad04 100644 --- a/packages/excalidraw/data/url.test.tsx +++ b/packages/excalidraw/data/url.test.tsx @@ -25,7 +25,7 @@ describe("normalizeLink", () => { expect(normalizeLink("file://")).toBe("file://"); expect(normalizeLink("[test](https://test)")).toBe("[test](https://test)"); expect(normalizeLink("[[test]]")).toBe("[[test]]"); - expect(normalizeLink("")).toBe("<test>"); - expect(normalizeLink("test&")).toBe("test&"); + expect(normalizeLink("")).toBe(""); + expect(normalizeLink("test&")).toBe("test&"); }); }); diff --git a/packages/excalidraw/data/url.ts b/packages/excalidraw/data/url.ts index e0c7323db..2ab553bb8 100644 --- a/packages/excalidraw/data/url.ts +++ b/packages/excalidraw/data/url.ts @@ -1,12 +1,12 @@ import { sanitizeUrl } from "@braintree/sanitize-url"; -import { sanitizeHTMLAttribute } from "../utils"; +import { escapeDoubleQuotes } from "../utils"; export const normalizeLink = (link: string) => { link = link.trim(); if (!link) { return link; } - return sanitizeUrl(sanitizeHTMLAttribute(link)); + return sanitizeUrl(escapeDoubleQuotes(link)); }; export const isLocalLink = (link: string | null) => { diff --git a/packages/excalidraw/element/embeddable.ts b/packages/excalidraw/element/embeddable.ts index 0948d4b52..b83953c2f 100644 --- a/packages/excalidraw/element/embeddable.ts +++ b/packages/excalidraw/element/embeddable.ts @@ -1,11 +1,7 @@ import { register } from "../actions/register"; import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants"; import type { ExcalidrawProps } from "../types"; -import { - getFontString, - sanitizeHTMLAttribute, - updateActiveTool, -} from "../utils"; +import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils"; import { setCursorForShape } from "../cursor"; import { newTextElement } from "./newElement"; import { wrapText } from "./textWrapping"; @@ -212,7 +208,7 @@ export const getEmbedLink = ( // Note that we don't attempt to parse the username as it can consist of // non-latin1 characters, and the username in the url can be set to anything // without affecting the embed. - const safeURL = sanitizeHTMLAttribute( + const safeURL = escapeDoubleQuotes( `https://twitter.com/x/status/${postId}`, ); @@ -231,7 +227,7 @@ export const getEmbedLink = ( if (RE_REDDIT.test(link)) { const [, page, postId, title] = link.match(RE_REDDIT)!; - const safeURL = sanitizeHTMLAttribute( + const safeURL = escapeDoubleQuotes( `https://reddit.com/r/${page}/comments/${postId}/${title}`, ); const ret: IframeDataWithSandbox = { @@ -249,7 +245,7 @@ export const getEmbedLink = ( if (RE_GH_GIST.test(link)) { const [, user, gistId] = link.match(RE_GH_GIST)!; - const safeURL = sanitizeHTMLAttribute( + const safeURL = escapeDoubleQuotes( `https://gist.github.com/${user}/${gistId}`, ); const ret: IframeDataWithSandbox = { diff --git a/packages/excalidraw/tests/utils.test.ts b/packages/excalidraw/tests/utils.test.ts index 3663973c3..34944faaa 100644 --- a/packages/excalidraw/tests/utils.test.ts +++ b/packages/excalidraw/tests/utils.test.ts @@ -1,4 +1,4 @@ -import { isTransparent, sanitizeHTMLAttribute } from "../utils"; +import { isTransparent } from "../utils"; describe("Test isTransparent", () => { it("should return true when color is rgb transparent", () => { @@ -11,9 +11,3 @@ describe("Test isTransparent", () => { expect(isTransparent("#ced4da")).toEqual(false); }); }); - -describe("sanitizeHTMLAttribute()", () => { - it("should escape HTML attribute special characters & not double escape", () => { - expect(sanitizeHTMLAttribute(`&"'><`)).toBe("&"'><"); - }); -}); diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index 1c1cdc149..e30c67ff6 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -1226,15 +1226,10 @@ export class PromisePool { } } -export const sanitizeHTMLAttribute = (html: string) => { - return ( - html - // note, if we're not doing stupid things, escaping " is enough, - // but we might end up doing stupid things - .replace(/&/g, "&") - .replace(/"/g, """) - .replace(/'/g, "'") - .replace(/>/g, ">") - .replace(/ { + return str.replace(/"/g, """); }; From a58822c1c1a1d2862ad7293ecb1d06b355604327 Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Wed, 29 Jan 2025 22:04:49 +0100 Subject: [PATCH 02/51] fix: merge server-side fonts with liberation sans (#9052) --- .../assets/LiberationSans-Regular-2048.ttf | Bin 0 -> 898548 bytes .../woff2/assets/LiberationSans-Regular.ttf | Bin 0 -> 864800 bytes scripts/woff2/woff2-esbuild-plugins.js | 40 +++++++++++++----- 3 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 scripts/woff2/assets/LiberationSans-Regular-2048.ttf create mode 100644 scripts/woff2/assets/LiberationSans-Regular.ttf diff --git a/scripts/woff2/assets/LiberationSans-Regular-2048.ttf b/scripts/woff2/assets/LiberationSans-Regular-2048.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ff514cddee1f6ee4a3b56c9d47504564ee2af7ac GIT binary patch literal 898548 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

Uc%Lt65{+5KAxNhs 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 I@JX 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∓0e>q()jJaC#N;3y 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�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

0tM>$MQE@`c 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

#+qS;;F;i^1zfMULdO(q6WvIG{FSqDu5Fs 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%0D!0PXn>dCQ1R***)1Cy8 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 { "./assets/NotoEmoji-Regular-2048.ttf", ); + const liberationPath = path.resolve( + __dirname, + "./assets/LiberationSans-Regular.ttf", + ); + + // need to use the same em size as built-in fonts, otherwise pyftmerge throws (modified manually with font forge) + const liberationPath_2048 = path.resolve( + __dirname, + "./assets/LiberationSans-Regular-2048.ttf", + ); + const xiaolaiFont = Font.create(fs.readFileSync(xiaolaiPath), { type: "ttf", }); @@ -130,6 +141,10 @@ module.exports.woff2ServerPlugin = (options = {}) => { type: "ttf", }); + const liberationFont = Font.create(fs.readFileSync(liberationPath), { + type: "ttf", + }); + const sortedFonts = Array.from(fonts.entries()).sort( ([family1], [family2]) => (family1 > family2 ? 1 : -1), ); @@ -141,13 +156,6 @@ module.exports.woff2ServerPlugin = (options = {}) => { continue; } - const fallbackFontsPaths = []; - const shouldIncludeXiaolaiFallback = family.includes("Excalifont"); - - if (shouldIncludeXiaolaiFallback) { - fallbackFontsPaths.push(xiaolaiPath); - } - const baseFont = Regular[0]; const tempPaths = Regular.map((_, index) => path.resolve(outputDir, `temp_${family}_${index}.ttf`), @@ -165,10 +173,18 @@ module.exports.woff2ServerPlugin = (options = {}) => { const mergedFontPath = path.resolve(outputDir, `${family}.ttf`); + const fallbackFontsPaths = []; + const shouldIncludeXiaolaiFallback = family.includes("Excalifont"); + + if (shouldIncludeXiaolaiFallback) { + fallbackFontsPaths.push(xiaolaiPath); + } + + // add liberation as fallback to all fonts, so that unknown characters are rendered similarly to how browser renders them (Helvetica, Arial, etc.) if (baseFont.data.head.unitsPerEm === 2048) { - fallbackFontsPaths.push(emojiPath_2048); + fallbackFontsPaths.push(emojiPath_2048, liberationPath_2048); } else { - fallbackFontsPaths.push(emojiPath); + fallbackFontsPaths.push(emojiPath, liberationPath); } // drop Vertical related metrics, otherwise it does not allow us to merge the fonts @@ -196,10 +212,12 @@ module.exports.woff2ServerPlugin = (options = {}) => { const base = baseFont.data.name[field]; const xiaolai = xiaolaiFont.data.name[field]; const emoji = emojiFont.data.name[field]; + const liberation = liberationFont.data.name[field]; + // liberation font return shouldIncludeXiaolaiFallback - ? `${base} & ${xiaolai} & ${emoji}` - : `${base} & ${emoji}`; + ? `${base} & ${xiaolai} & ${emoji} & ${liberation}` + : `${base} & ${emoji} & ${liberation}`; }; mergedFont.set({ From d29c3db7f684d16fd1d4620dbd1263f148bc33a3 Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Wed, 29 Jan 2025 22:24:26 +0100 Subject: [PATCH 03/51] fix: fonts not loading on export (again) (#9064) --- packages/excalidraw/fonts/Fonts.ts | 44 ++++++------------------------ 1 file changed, 9 insertions(+), 35 deletions(-) diff --git a/packages/excalidraw/fonts/Fonts.ts b/packages/excalidraw/fonts/Fonts.ts index 3e307e7da..d8f257c03 100644 --- a/packages/excalidraw/fonts/Fonts.ts +++ b/packages/excalidraw/fonts/Fonts.ts @@ -3,7 +3,6 @@ import { FONT_FAMILY_FALLBACKS, CJK_HAND_DRAWN_FALLBACK_FONT, WINDOWS_EMOJI_FALLBACK_FONT, - isSafari, getFontFamilyFallbacks, } from "../constants"; import { isTextElement } from "../element"; @@ -137,50 +136,28 @@ export class Fonts { /** * Load font faces for a given scene and trigger scene update. - * - * FontFaceSet loadingdone event we listen on may not always - * fire (looking at you Safari), so on init we manually load all - * fonts and rerender scene text elements once done. - * - * For Safari we make sure to check against each loaded font face - * with the unique characters per family in the scene, - * otherwise fonts might remain unloaded. */ public loadSceneFonts = async (): Promise => { const sceneFamilies = this.getSceneFamilies(); - const charsPerFamily = isSafari - ? Fonts.getCharsPerFamily(this.scene.getNonDeletedElements()) - : undefined; + const charsPerFamily = Fonts.getCharsPerFamily( + this.scene.getNonDeletedElements(), + ); return Fonts.loadFontFaces(sceneFamilies, charsPerFamily); }; /** * Load font faces for passed elements - use when the scene is unavailable (i.e. export). - * - * For Safari we make sure to check against each loaded font face, - * with the unique characters per family in the elements - * otherwise fonts might remain unloaded. */ public static loadElementsFonts = async ( elements: readonly ExcalidrawElement[], ): Promise => { const fontFamilies = Fonts.getUniqueFamilies(elements); - const charsPerFamily = isSafari - ? Fonts.getCharsPerFamily(elements) - : undefined; + const charsPerFamily = Fonts.getCharsPerFamily(elements); return Fonts.loadFontFaces(fontFamilies, charsPerFamily); }; - /** - * Load all registered font faces. - */ - public static loadAllFonts = async (): Promise => { - const allFamilies = Fonts.getAllFamilies(); - return Fonts.loadFontFaces(allFamilies); - }; - /** * Generate CSS @font-face declarations for the given elements. */ @@ -223,7 +200,7 @@ export class Fonts { private static async loadFontFaces( fontFamilies: Array, - charsPerFamily?: Record>, + charsPerFamily: Record>, ) { // add all registered font faces into the `document.fonts` (if not added already) for (const { fontFaces, metadata } of Fonts.registered.values()) { @@ -248,7 +225,7 @@ export class Fonts { private static *fontFacesLoader( fontFamilies: Array, - charsPerFamily?: Record>, + charsPerFamily: Record>, ): Generator> { for (const [index, fontFamily] of fontFamilies.entries()) { const font = getFontString({ @@ -256,12 +233,9 @@ export class Fonts { fontSize: 16, }); - // WARN: without "text" param it does not have to mean that all font faces are loaded, instead it could be just one! - // for Safari on init, we rather check with the "text" param, even though it's less efficient, as otherwise fonts might remain unloaded - const text = - isSafari && charsPerFamily - ? Fonts.getCharacters(charsPerFamily, fontFamily) - : ""; + // 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! + // instead, we are always checking chars used in the family, so that no required font faces remain unloaded + const text = Fonts.getCharacters(charsPerFamily, fontFamily); if (!window.document.fonts.check(font, text)) { yield promiseTry(async () => { From bd1590fc74c6b38df73a34e74cb0cbacccd988a0 Mon Sep 17 00:00:00 2001 From: Saikat Das Date: Thu, 30 Jan 2025 03:16:40 +0530 Subject: [PATCH 04/51] feat: implement custom Range component for opacity control (#9009) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- .../excalidraw/actions/actionProperties.tsx | 26 ++------ packages/excalidraw/components/Range.scss | 59 +++++++++++++++++ packages/excalidraw/components/Range.tsx | 65 +++++++++++++++++++ packages/excalidraw/css/theme.scss | 3 + .../excalidraw/tests/actionStyles.test.tsx | 2 +- .../excalidraw/tests/contextmenu.test.tsx | 2 +- 6 files changed, 136 insertions(+), 21 deletions(-) create mode 100644 packages/excalidraw/components/Range.scss create mode 100644 packages/excalidraw/components/Range.tsx diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 5c4d7754f..3e0768b26 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -121,6 +121,7 @@ import { import { LinearElementEditor } from "../element/linearElementEditor"; import type { LocalPoint } from "../../math"; import { pointFrom } from "../../math"; +import { Range } from "../components/Range"; const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1; @@ -630,25 +631,12 @@ export const actionChangeOpacity = register({ }; }, PanelComponent: ({ elements, appState, updateData }) => ( - + ), }); diff --git a/packages/excalidraw/components/Range.scss b/packages/excalidraw/components/Range.scss new file mode 100644 index 000000000..292b95b4b --- /dev/null +++ b/packages/excalidraw/components/Range.scss @@ -0,0 +1,59 @@ +@import "../css/variables.module.scss"; + +.excalidraw { + --Range-track-background: var(--button-bg); + --Range-track-background-active: var(--color-primary); + --Range-thumb-background: var(--color-on-surface); + --Range-legend-color: var(--text-primary-color); + + .range-wrapper { + position: relative; + padding-top: 10px; + padding-bottom: 30px; + } + + .range-input { + width: 100%; + height: 4px; + -webkit-appearance: none; + background: var(--Range-track-background); + border-radius: 2px; + outline: none; + } + + .range-input::-webkit-slider-thumb { + -webkit-appearance: none; + appearance: none; + width: 20px; + height: 20px; + background: var(--Range-thumb-background); + border-radius: 50%; + cursor: pointer; + border: none; + } + + .range-input::-moz-range-thumb { + width: 20px; + height: 20px; + background: var(--Range-thumb-background); + border-radius: 50%; + cursor: pointer; + border: none; + } + + .value-bubble { + position: absolute; + bottom: 0; + transform: translateX(-50%); + font-size: 12px; + color: var(--Range-legend-color); + } + + .zero-label { + position: absolute; + bottom: 0; + left: 4px; + font-size: 12px; + color: var(--Range-legend-color); + } +} diff --git a/packages/excalidraw/components/Range.tsx b/packages/excalidraw/components/Range.tsx new file mode 100644 index 000000000..ddc89cfa7 --- /dev/null +++ b/packages/excalidraw/components/Range.tsx @@ -0,0 +1,65 @@ +import React, { useEffect } from "react"; +import { getFormValue } from "../actions/actionProperties"; +import { t } from "../i18n"; +import "./Range.scss"; + +export type RangeProps = { + updateData: (value: number) => void; + appState: any; + elements: any; + testId?: string; +}; + +export const Range = ({ + updateData, + appState, + elements, + testId, +}: RangeProps) => { + const rangeRef = React.useRef(null); + const valueRef = React.useRef(null); + const value = getFormValue( + elements, + appState, + (element) => element.opacity, + true, + appState.currentItemOpacity, + ); + useEffect(() => { + if (rangeRef.current && valueRef.current) { + const rangeElement = rangeRef.current; + const valueElement = valueRef.current; + const inputWidth = rangeElement.offsetWidth; + const thumbWidth = 15; // 15 is the width of the thumb + const position = + (value / 100) * (inputWidth - thumbWidth) + thumbWidth / 2; + valueElement.style.left = `${position}px`; + rangeElement.style.background = `linear-gradient(to right, var(--color-primary) 0%, var(--color-primary) ${value}%, var(--button-bg) ${value}%, var(--button-bg) 100%)`; + } + }, [value]); + + return ( + + ); +}; diff --git a/packages/excalidraw/css/theme.scss b/packages/excalidraw/css/theme.scss index 69c28afda..40ecaf8ca 100644 --- a/packages/excalidraw/css/theme.scss +++ b/packages/excalidraw/css/theme.scss @@ -32,6 +32,7 @@ 0px 0px 3.1270833015441895px 0px rgba(0, 0, 0, 0.08), 0px 7px 14px 0px rgba(0, 0, 0, 0.05); + --button-bg: var(--color-surface-mid); --button-hover-bg: var(--color-surface-high); --button-active-bg: var(--color-surface-high); --button-active-border: var(--color-brand-active); @@ -171,6 +172,8 @@ --button-destructive-bg-color: #5a0000; --button-destructive-color: #{$oc-red-3}; + --button-bg: var(--color-surface-high); + --button-gray-1: #363636; --button-gray-2: #272727; --button-gray-3: #222; diff --git a/packages/excalidraw/tests/actionStyles.test.tsx b/packages/excalidraw/tests/actionStyles.test.tsx index c7e497a16..abe4a7c00 100644 --- a/packages/excalidraw/tests/actionStyles.test.tsx +++ b/packages/excalidraw/tests/actionStyles.test.tsx @@ -50,7 +50,7 @@ describe("actionStyles", () => { // Roughness fireEvent.click(screen.getByTitle("Cartoonist")); // Opacity - fireEvent.change(screen.getByLabelText("Opacity"), { + fireEvent.change(screen.getByTestId("opacity"), { target: { value: "60" }, }); diff --git a/packages/excalidraw/tests/contextmenu.test.tsx b/packages/excalidraw/tests/contextmenu.test.tsx index 42466c4f0..133c68222 100644 --- a/packages/excalidraw/tests/contextmenu.test.tsx +++ b/packages/excalidraw/tests/contextmenu.test.tsx @@ -338,7 +338,7 @@ describe("contextMenu element", () => { // Roughness fireEvent.click(screen.getByTitle("Cartoonist")); // Opacity - fireEvent.change(screen.getByLabelText("Opacity"), { + fireEvent.change(screen.getByTestId("opacity"), { target: { value: "60" }, }); From 61e0bb83d091a761d4e8305ac99c486c99ac4f2c Mon Sep 17 00:00:00 2001 From: Are Date: Thu, 30 Jan 2025 14:41:08 +0100 Subject: [PATCH 05/51] feat: improve library sidebar performance (#9060) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- .../excalidraw/components/LibraryMenu.tsx | 64 +++++++++++++------ packages/excalidraw/types.ts | 2 + 2 files changed, 46 insertions(+), 20 deletions(-) diff --git a/packages/excalidraw/components/LibraryMenu.tsx b/packages/excalidraw/components/LibraryMenu.tsx index 4b4cccbae..4b76dfc4a 100644 --- a/packages/excalidraw/components/LibraryMenu.tsx +++ b/packages/excalidraw/components/LibraryMenu.tsx @@ -1,4 +1,10 @@ -import React, { useState, useCallback, useMemo, useRef } from "react"; +import React, { + useState, + useCallback, + useMemo, + useRef, + useEffect, +} from "react"; import type Library from "../data/library"; import { distributeLibraryItemsOnSquareGrid, @@ -150,27 +156,40 @@ const usePendingElementsMemo = ( appState: UIAppState, elements: readonly NonDeletedExcalidrawElement[], ) => { - const create = () => - getSelectedElements(elements, appState, { - includeBoundTextElement: true, - includeElementsInFrames: true, - }); - const val = useRef(create()); + const create = useCallback( + (appState: UIAppState, elements: readonly NonDeletedExcalidrawElement[]) => + getSelectedElements(elements, appState, { + includeBoundTextElement: true, + includeElementsInFrames: true, + }), + [], + ); + + const val = useRef(create(appState, elements)); const prevAppState = useRef(appState); const prevElements = useRef(elements); - if ( - !isShallowEqual( - appState.selectedElementIds, - prevAppState.current.selectedElementIds, - ) || - !isShallowEqual(elements, prevElements.current) - ) { - val.current = create(); - prevAppState.current = appState; - prevElements.current = elements; - } - return val.current; + const update = useCallback(() => { + if ( + !isShallowEqual( + appState.selectedElementIds, + prevAppState.current.selectedElementIds, + ) || + !isShallowEqual(elements, prevElements.current) + ) { + val.current = create(appState, elements); + prevAppState.current = appState; + prevElements.current = elements; + } + }, [create, appState, elements]); + + return useMemo( + () => ({ + update, + value: val.current, + }), + [update, val], + ); }; /** @@ -181,6 +200,7 @@ export const LibraryMenu = () => { const { library, id, onInsertElements } = useApp(); const appProps = useAppProps(); const appState = useUIAppState(); + const app = useApp(); const setAppState = useExcalidrawSetAppState(); const elements = useExcalidrawElements(); const [selectedItems, setSelectedItems] = useState([]); @@ -203,9 +223,13 @@ export const LibraryMenu = () => { }); }, [setAppState]); + useEffect(() => { + return app.onPointerUpEmitter.on(() => pendingElements.update()); + }, [app, pendingElements]); + return ( Date: Thu, 30 Jan 2025 19:11:41 +0530 Subject: [PATCH 06/51] Fix: issue #8818 Xiaolai font has been set as a fallback for Excalifont (#9055) Co-authored-by: David Luzar <5153846+dwelle@users.noreply.github.com> --- .../excalidraw/components/welcome-screen/WelcomeScreen.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss b/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss index 8472b19fe..dc8826a66 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.scss @@ -1,6 +1,6 @@ .excalidraw { .excalifont { - font-family: "Excalifont"; + font-family: "Excalifont", "Xiaolai"; } // WelcomeSreen common From 6cdb683410626a16ef08b16b1a773ccfb4cec53e Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Fri, 31 Jan 2025 12:33:54 +0100 Subject: [PATCH 07/51] fix: button bg CSS variable leaking into other styles (#9075) --- packages/excalidraw/css/styles.scss | 8 +++++++- packages/excalidraw/css/theme.scss | 3 --- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/packages/excalidraw/css/styles.scss b/packages/excalidraw/css/styles.scss index 673106700..6f1d9cd48 100644 --- a/packages/excalidraw/css/styles.scss +++ b/packages/excalidraw/css/styles.scss @@ -649,15 +649,21 @@ body.excalidraw-cursor-resize * { @include filledButtonOnCanvas; } + .App-mobile-menu, .App-menu__left { --button-border: transparent; --button-bg: var(--color-surface-mid); + } - @at-root .excalidraw.theme--dark#{&} { + @at-root .excalidraw.theme--dark#{&} { + .App-mobile-menu, + .App-menu__left { --button-hover-bg: #363541; --button-bg: var(--color-surface-high); } + } + .App-menu__left { .buttonList { padding: 0.25rem 0; } diff --git a/packages/excalidraw/css/theme.scss b/packages/excalidraw/css/theme.scss index 40ecaf8ca..69c28afda 100644 --- a/packages/excalidraw/css/theme.scss +++ b/packages/excalidraw/css/theme.scss @@ -32,7 +32,6 @@ 0px 0px 3.1270833015441895px 0px rgba(0, 0, 0, 0.08), 0px 7px 14px 0px rgba(0, 0, 0, 0.05); - --button-bg: var(--color-surface-mid); --button-hover-bg: var(--color-surface-high); --button-active-bg: var(--color-surface-high); --button-active-border: var(--color-brand-active); @@ -172,8 +171,6 @@ --button-destructive-bg-color: #5a0000; --button-destructive-color: #{$oc-red-3}; - --button-bg: var(--color-surface-high); - --button-gray-1: #363636; --button-gray-2: #272727; --button-gray-3: #222; From 9b6edc767a2e66cfaf6fc83f099e31f347c9178a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Fri, 31 Jan 2025 14:19:07 +0100 Subject: [PATCH 08/51] fix: Elbow arrow orthogonality (#9073) --- packages/excalidraw/element/elbowArrow.ts | 25 ++++++++++++++- packages/excalidraw/element/flowchart.ts | 37 +++++++++++++++++------ 2 files changed, 52 insertions(+), 10 deletions(-) diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index c55d652c9..921e73518 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -244,6 +244,12 @@ const handleSegmentRenormalization = ( ); } + import.meta.env.DEV && + invariant( + validateElbowPoints(nextPoints), + "Invalid elbow points with fixed segments", + ); + return normalizeArrowElementUpdate( nextPoints, filteredNextFixedSegments, @@ -912,7 +918,11 @@ export const updateElbowArrowPoints = ( // 0. During all element replacement in the scene, we just need to renormalize // the arrow // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed - if (elementsMap.size === 0 && updates.points) { + if ( + elementsMap.size === 0 && + updates.points && + validateElbowPoints(updates.points) + ) { return normalizeArrowElementUpdate( updates.points.map((p) => pointFrom(arrow.x + p[0], arrow.y + p[1]), @@ -2123,3 +2133,16 @@ const getHoveredElements = ( const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => a[0] === b[0] && a[1] === b[1]; + +const validateElbowPoints =

( + points: readonly P[], + tolerance: number = DEDUP_TRESHOLD, +) => + points + .slice(1) + .map( + (p, i) => + Math.abs(p[0] - points[i][0]) < tolerance || + Math.abs(p[1] - points[i][1]) < tolerance, + ) + .every(Boolean); diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index fad72560b..d2b220c45 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -10,13 +10,15 @@ import { import { bindLinearElement } from "./binding"; import { LinearElementEditor } from "./linearElementEditor"; import { newArrowElement, newElement } from "./newElement"; -import type { - ElementsMap, - ExcalidrawBindableElement, - ExcalidrawElement, - ExcalidrawFlowchartNodeElement, - NonDeletedSceneElementsMap, - OrderedExcalidrawElement, +import type { SceneElementsMap } from "./types"; +import { + type ElementsMap, + type ExcalidrawBindableElement, + type ExcalidrawElement, + type ExcalidrawFlowchartNodeElement, + type NonDeletedSceneElementsMap, + type Ordered, + type OrderedExcalidrawElement, } from "./types"; import { KEYS } from "../keys"; import type { AppState, PendingExcalidrawElements } from "../types"; @@ -28,9 +30,10 @@ import { isFrameElement, isFlowchartNodeElement, } from "./typeChecks"; -import { invariant } from "../utils"; +import { invariant, toBrandedType } from "../utils"; import { pointFrom, type LocalPoint } from "../../math"; import { aabbForElement } from "../shapes"; +import { updateElbowArrowPoints } from "./elbowArrow"; type LinkDirection = "up" | "right" | "down" | "left"; @@ -467,7 +470,23 @@ const createBindingArrow = ( }, ]); - return bindingArrow; + const update = updateElbowArrowPoints( + bindingArrow, + toBrandedType( + new Map([ + ...elementsMap.entries(), + [startBindingElement.id, startBindingElement], + [endBindingElement.id, endBindingElement], + [bindingArrow.id, bindingArrow], + ] as [string, Ordered][]), + ), + { points: bindingArrow.points }, + ); + + return { + ...bindingArrow, + ...update, + }; }; export class FlowChartNavigator { From 511433988c9ed80acbbd1ad8c2a90df701fae9ae Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Fri, 31 Jan 2025 16:52:50 +0100 Subject: [PATCH 09/51] feat: tweak slider colors to be more muted (#9076) --- packages/excalidraw/components/Range.scss | 23 ++++++++++------------- packages/excalidraw/components/Range.tsx | 2 +- packages/excalidraw/css/theme.scss | 5 +++++ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/excalidraw/components/Range.scss b/packages/excalidraw/components/Range.scss index 292b95b4b..01cb91689 100644 --- a/packages/excalidraw/components/Range.scss +++ b/packages/excalidraw/components/Range.scss @@ -1,10 +1,7 @@ @import "../css/variables.module.scss"; .excalidraw { - --Range-track-background: var(--button-bg); - --Range-track-background-active: var(--color-primary); - --Range-thumb-background: var(--color-on-surface); - --Range-legend-color: var(--text-primary-color); + --slider-thumb-size: 16px; .range-wrapper { position: relative; @@ -16,7 +13,7 @@ width: 100%; height: 4px; -webkit-appearance: none; - background: var(--Range-track-background); + background: var(--color-slider-track); border-radius: 2px; outline: none; } @@ -24,18 +21,18 @@ .range-input::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; - width: 20px; - height: 20px; - background: var(--Range-thumb-background); + width: var(--slider-thumb-size); + height: var(--slider-thumb-size); + background: var(--color-slider-thumb); border-radius: 50%; cursor: pointer; border: none; } .range-input::-moz-range-thumb { - width: 20px; - height: 20px; - background: var(--Range-thumb-background); + width: var(--slider-thumb-size); + height: var(--slider-thumb-size); + background: var(--color-slider-thumb); border-radius: 50%; cursor: pointer; border: none; @@ -46,7 +43,7 @@ bottom: 0; transform: translateX(-50%); font-size: 12px; - color: var(--Range-legend-color); + color: var(--text-primary-color); } .zero-label { @@ -54,6 +51,6 @@ bottom: 0; left: 4px; font-size: 12px; - color: var(--Range-legend-color); + color: var(--text-primary-color); } } diff --git a/packages/excalidraw/components/Range.tsx b/packages/excalidraw/components/Range.tsx index ddc89cfa7..cd1869cc0 100644 --- a/packages/excalidraw/components/Range.tsx +++ b/packages/excalidraw/components/Range.tsx @@ -34,7 +34,7 @@ export const Range = ({ const position = (value / 100) * (inputWidth - thumbWidth) + thumbWidth / 2; valueElement.style.left = `${position}px`; - rangeElement.style.background = `linear-gradient(to right, var(--color-primary) 0%, var(--color-primary) ${value}%, var(--button-bg) ${value}%, var(--button-bg) 100%)`; + rangeElement.style.background = `linear-gradient(to right, var(--color-slider-track) 0%, var(--color-slider-track) ${value}%, var(--button-bg) ${value}%, var(--button-bg) 100%)`; } }, [value]); diff --git a/packages/excalidraw/css/theme.scss b/packages/excalidraw/css/theme.scss index 69c28afda..a531d5bb7 100644 --- a/packages/excalidraw/css/theme.scss +++ b/packages/excalidraw/css/theme.scss @@ -53,6 +53,9 @@ --scrollbar-thumb: var(--button-gray-2); --scrollbar-thumb-hover: var(--button-gray-3); + --color-slider-track: hsl(240, 100%, 90%); + --color-slider-thumb: var(--color-gray-80); + --modal-shadow: 0px 100px 80px rgba(0, 0, 0, 0.07), 0px 41.7776px 33.4221px rgba(0, 0, 0, 0.0503198), 0px 22.3363px 17.869px rgba(0, 0, 0, 0.0417275), @@ -207,6 +210,8 @@ --scrollbar-thumb: #{$oc-gray-8}; --scrollbar-thumb-hover: #{$oc-gray-7}; + --color-slider-track: hsl(244, 23%, 39%); + // will be inverted to a lighter color. --color-selection: #3530c4; From 86c67bd37fe182f70ad994dd7acb6ee2dc128c39 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sat, 1 Feb 2025 12:27:41 +0100 Subject: [PATCH 10/51] fix: library item checkbox style regression (#9080) --- packages/excalidraw/components/IconPicker.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index 830712bbf..1a96a175d 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -5,7 +5,7 @@ import { getLanguage, t } from "../i18n"; import clsx from "clsx"; import Collapsible from "./Stats/Collapsible"; import { atom, useAtom } from "../editor-jotai"; -import { useDevice } from ".."; +import { useDevice } from "./App"; import "./IconPicker.scss"; From 302664e500c7f2ee44a1f107d8f4680c0254305b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Sat, 1 Feb 2025 19:21:03 +0100 Subject: [PATCH 11/51] fix: Elbow arrow z-index binding (#9067) --- .../excalidraw/actions/actionProperties.tsx | 4 ++ packages/excalidraw/components/App.tsx | 24 +++++-- packages/excalidraw/element/binding.ts | 72 ++++++++++++++++++- packages/excalidraw/element/elbowArrow.ts | 42 ++++++++++- .../excalidraw/element/linearElementEditor.ts | 3 + packages/excalidraw/element/mutateElement.ts | 9 ++- packages/excalidraw/scene/comparisons.ts | 33 +++++---- packages/excalidraw/utils.ts | 9 ++- 8 files changed, 165 insertions(+), 31 deletions(-) diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 3e0768b26..660d7e679 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1605,6 +1605,8 @@ export const actionChangeArrowType = register({ elements, elementsMap, appState.zoom, + false, + true, ); const endHoveredElement = !newElement.endBinding && @@ -1613,6 +1615,8 @@ export const actionChangeArrowType = register({ elements, elementsMap, appState.zoom, + false, + true, ); const startElement = startHoveredElement ? startHoveredElement diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index f16f88657..dc81f9181 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -5770,7 +5770,10 @@ class App extends React.Component { }); } if (editingLinearElement?.lastUncommittedPoint != null) { - this.maybeSuggestBindingAtCursor(scenePointer); + this.maybeSuggestBindingAtCursor( + scenePointer, + editingLinearElement.elbowed, + ); } else { // causes stack overflow if not sync flushSync(() => { @@ -5790,7 +5793,7 @@ class App extends React.Component { this.state.startBoundElement, ); } else { - this.maybeSuggestBindingAtCursor(scenePointer); + this.maybeSuggestBindingAtCursor(scenePointer, false); } } @@ -7728,6 +7731,7 @@ class App extends React.Component { this.scene.getNonDeletedElementsMap(), this.state.zoom, isElbowArrow(element), + isElbowArrow(element), ); this.scene.insertElement(element); @@ -10005,15 +10009,20 @@ class App extends React.Component { } }; - private maybeSuggestBindingAtCursor = (pointerCoords: { - x: number; - y: number; - }): void => { + private maybeSuggestBindingAtCursor = ( + pointerCoords: { + x: number; + y: number; + }, + considerAll: boolean, + ): void => { const hoveredBindableElement = getHoveredElementForBinding( pointerCoords, this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), this.state.zoom, + false, + considerAll, ); this.setState({ suggestedBindings: @@ -10043,7 +10052,8 @@ class App extends React.Component { this.scene.getNonDeletedElements(), this.scene.getNonDeletedElementsMap(), this.state.zoom, - isArrowElement(linearElement) && isElbowArrow(linearElement), + isElbowArrow(linearElement), + isElbowArrow(linearElement), ); if ( hoveredBindableElement != null && diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 615a484a4..5b45d982b 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -49,7 +49,11 @@ import type { ElementUpdate } from "./mutateElement"; import { mutateElement } from "./mutateElement"; import type Scene from "../scene/Scene"; import { LinearElementEditor } from "./linearElementEditor"; -import { arrayToMap, tupleToCoors } from "../utils"; +import { + arrayToMap, + isBindingFallthroughEnabled, + tupleToCoors, +} from "../utils"; import { KEYS } from "../keys"; import { getBoundTextElement, handleBindTextResize } from "./textElement"; import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; @@ -75,6 +79,7 @@ import { clamp, } from "../../math"; import { segmentIntersectRectangleElement } from "../../utils/geometry/shape"; +import { getElementsAtPosition } from "../scene/comparisons"; export type SuggestedBinding = | NonDeleted @@ -425,7 +430,8 @@ export const maybeBindLinearElement = ( elements, elementsMap, appState.zoom, - isElbowArrow(linearElement) && isElbowArrow(linearElement), + isElbowArrow(linearElement), + isElbowArrow(linearElement), ); if (hoveredElement !== null) { @@ -558,7 +564,64 @@ export const getHoveredElementForBinding = ( elementsMap: NonDeletedSceneElementsMap, zoom?: AppState["zoom"], fullShape?: boolean, + considerAllElements?: boolean, ): NonDeleted | null => { + if (considerAllElements) { + let cullRest = false; + const candidateElements = getElementsAtPosition( + elements, + (element) => + isBindableElement(element, false) && + bindingBorderTest( + element, + pointerCoords, + elementsMap, + zoom, + (fullShape || + !isBindingFallthroughEnabled( + element as ExcalidrawBindableElement, + )) && + // disable fullshape snapping for frame elements so we + // can bind to frame children + !isFrameLikeElement(element), + ), + ).filter((element) => { + if (cullRest) { + return false; + } + + if (!isBindingFallthroughEnabled(element as ExcalidrawBindableElement)) { + cullRest = true; + } + + return true; + }) as NonDeleted[] | null; + + // Return early if there are no candidates or just one candidate + if (!candidateElements || candidateElements.length === 0) { + return null; + } + + if (candidateElements.length === 1) { + return candidateElements[0] as NonDeleted; + } + + // Prefer the shape with the border being tested (if any) + const borderTestElements = candidateElements.filter((element) => + bindingBorderTest(element, pointerCoords, elementsMap, zoom, false), + ); + if (borderTestElements.length === 1) { + return borderTestElements[0]; + } + + // Prefer smaller shapes + return candidateElements + .sort( + (a, b) => b.width ** 2 + b.height ** 2 - (a.width ** 2 + a.height ** 2), + ) + .pop() as NonDeleted; + } + const hoveredElement = getElementAtPosition( elements, (element) => @@ -570,7 +633,8 @@ export const getHoveredElementForBinding = ( zoom, // disable fullshape snapping for frame elements so we // can bind to frame children - fullShape && !isFrameLikeElement(element), + (fullShape || !isBindingFallthroughEnabled(element)) && + !isFrameLikeElement(element), ), ); @@ -1220,6 +1284,8 @@ const getElligibleElementForBindingElement = ( elements, elementsMap, zoom, + isElbowArrow(linearElement), + isElbowArrow(linearElement), ); }; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 921e73518..498e59d71 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -20,11 +20,11 @@ import { bindPointToSnapToElementOutline, distanceToBindableElement, avoidRectangularCorner, - getHoveredElementForBinding, FIXED_BINDING_DISTANCE, getHeadingForElbowArrowSnap, getGlobalFixedPointForBindableElement, snapToMid, + getHoveredElementForBinding, } from "./binding"; import type { Bounds } from "./bounds"; import type { Heading } from "./heading"; @@ -872,6 +872,8 @@ export const updateElbowArrowPoints = ( updates: { points?: readonly LocalPoint[]; fixedSegments?: FixedSegment[] | null; + startBinding?: FixedPointBinding | null; + endBinding?: FixedPointBinding | null; }, options?: { isDragging?: boolean; @@ -953,17 +955,48 @@ export const updateElbowArrowPoints = ( hoveredStartElement, hoveredEndElement, ...rest - } = getElbowArrowData(arrow, elementsMap, updatedPoints, options); + } = getElbowArrowData( + { + x: arrow.x, + y: arrow.y, + startBinding: + typeof updates.startBinding !== "undefined" + ? updates.startBinding + : arrow.startBinding, + endBinding: + typeof updates.endBinding !== "undefined" + ? updates.endBinding + : arrow.endBinding, + startArrowhead: arrow.startArrowhead, + endArrowhead: arrow.endArrowhead, + }, + elementsMap, + updatedPoints, + options, + ); const fixedSegments = updates.fixedSegments ?? arrow.fixedSegments ?? []; //// // 1. Renormalize the arrow //// - if (!updates.points && !updates.fixedSegments) { + if ( + !updates.points && + !updates.fixedSegments && + !updates.startBinding && + !updates.endBinding + ) { return handleSegmentRenormalization(arrow, elementsMap); } + // Short circuit on no-op to avoid huge performance hit + if ( + updates.startBinding === arrow.startBinding && + updates.endBinding === arrow.endBinding + ) { + return {}; + } + //// // 2. Just normal elbow arrow things //// @@ -1010,6 +1043,7 @@ export const updateElbowArrowPoints = ( //// // 5. Handle resize + //// if (updates.points && updates.fixedSegments) { return updates; } @@ -2120,6 +2154,7 @@ const getHoveredElements = ( nonDeletedSceneElementsMap, zoom, true, + true, ), getHoveredElementForBinding( tupleToCoors(origEndGlobalPoint), @@ -2127,6 +2162,7 @@ const getHoveredElements = ( nonDeletedSceneElementsMap, zoom, true, + true, ), ]; }; diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index 99b369a76..380313067 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -444,6 +444,8 @@ export class LinearElementEditor { elements, elementsMap, appState.zoom, + isElbowArrow(element), + isElbowArrow(element), ) : null; @@ -796,6 +798,7 @@ export class LinearElementEditor { elements, elementsMap, app.state.zoom, + linearElementEditor.elbowed, ), }; diff --git a/packages/excalidraw/element/mutateElement.ts b/packages/excalidraw/element/mutateElement.ts index d5fcc1ff3..2f2a5d47f 100644 --- a/packages/excalidraw/element/mutateElement.ts +++ b/packages/excalidraw/element/mutateElement.ts @@ -33,13 +33,16 @@ export const mutateElement = >( // casting to any because can't use `in` operator // (see https://github.com/microsoft/TypeScript/issues/21732) - const { points, fixedSegments, fileId } = updates as any; + const { points, fixedSegments, fileId, startBinding, endBinding } = + updates as any; if ( isElbowArrow(element) && (Object.keys(updates).length === 0 || // normalization case typeof points !== "undefined" || // repositioning - typeof fixedSegments !== "undefined") // segment fixing + typeof fixedSegments !== "undefined" || // segment fixing + typeof startBinding !== "undefined" || + typeof endBinding !== "undefined") // manual binding to element ) { const elementsMap = toBrandedType( Scene.getScene(element)?.getNonDeletedElementsMap() ?? new Map(), @@ -58,6 +61,8 @@ export const mutateElement = >( { fixedSegments, points, + startBinding, + endBinding, }, { isDragging: options?.isDragging, diff --git a/packages/excalidraw/scene/comparisons.ts b/packages/excalidraw/scene/comparisons.ts index 629fb371e..47561fdf9 100644 --- a/packages/excalidraw/scene/comparisons.ts +++ b/packages/excalidraw/scene/comparisons.ts @@ -75,20 +75,23 @@ export const getElementsAtPosition = ( isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean, ) => { const iframeLikes: ExcalidrawIframeElement[] = []; - // The parameter elements comes ordered from lower z-index to higher. - // We want to preserve that order on the returned array. - // Exception being embeddables which should be on top of everything else in - // terms of hit testing. - const elsAtPos = elements.filter((element) => { - const hit = !element.isDeleted && isAtPositionFn(element); - if (hit) { - if (isIframeElement(element)) { - iframeLikes.push(element); - return false; - } - return true; + const elementsAtPosition: NonDeletedExcalidrawElement[] = []; + // We need to to hit testing from front (end of the array) to back (beginning of the array) + // because array is ordered from lower z-index to highest and we want element z-index + // with higher z-index + for (let index = elements.length - 1; index >= 0; --index) { + const element = elements[index]; + if (element.isDeleted) { + continue; } - return false; - }); - return elsAtPos.concat(iframeLikes); + if (isIframeElement(element)) { + iframeLikes.push(element); + continue; + } + if (isAtPositionFn(element)) { + elementsAtPosition.push(element); + } + } + + return elementsAtPosition.concat(iframeLikes); }; diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index e30c67ff6..e4431ddd1 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -9,7 +9,11 @@ import { isDarwin, WINDOWS_EMOJI_FALLBACK_FONT, } from "./constants"; -import type { FontFamilyValues, FontString } from "./element/types"; +import type { + ExcalidrawBindableElement, + FontFamilyValues, + FontString, +} from "./element/types"; import type { ActiveTool, AppState, @@ -543,6 +547,9 @@ export const isTransparent = (color: string) => { ); }; +export const isBindingFallthroughEnabled = (el: ExcalidrawBindableElement) => + el.fillStyle !== "solid" || isTransparent(el.backgroundColor); + export type ResolvablePromise = Promise & { resolve: [T] extends [undefined] ? (value?: MaybePromise>) => void From 424e94a403b0c819c3624afb8aad4ae18e32e1dc Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Tue, 4 Feb 2025 19:23:47 +0100 Subject: [PATCH 12/51] fix: duplicating/removing frame while children selected (#9079) --- .../actions/actionDeleteSelected.test.tsx | 211 + .../actions/actionDeleteSelected.tsx | 50 +- .../actions/actionDuplicateSelection.test.tsx | 530 +++ .../actions/actionDuplicateSelection.tsx | 291 +- packages/excalidraw/constants.ts | 3 + packages/excalidraw/element/newElement.ts | 44 +- packages/excalidraw/element/sortElements.ts | 5 +- packages/excalidraw/frame.test.tsx | 11 +- packages/excalidraw/package.json | 1 + .../__snapshots__/contextmenu.test.tsx.snap | 8 +- .../tests/__snapshots__/history.test.tsx.snap | 3654 ++++++++--------- .../tests/__snapshots__/move.test.tsx.snap | 2 +- .../regressionTests.test.tsx.snap | 14 +- packages/excalidraw/tests/helpers/api.ts | 99 +- packages/excalidraw/tests/history.test.tsx | 19 +- packages/excalidraw/tests/library.test.tsx | 51 +- packages/excalidraw/tests/test-utils.ts | 151 + packages/excalidraw/tests/zindex.test.tsx | 70 +- packages/excalidraw/utility-types.ts | 3 + packages/excalidraw/utils.ts | 3 + yarn.lock | 5 + 21 files changed, 3160 insertions(+), 2065 deletions(-) create mode 100644 packages/excalidraw/actions/actionDeleteSelected.test.tsx create mode 100644 packages/excalidraw/actions/actionDuplicateSelection.test.tsx diff --git a/packages/excalidraw/actions/actionDeleteSelected.test.tsx b/packages/excalidraw/actions/actionDeleteSelected.test.tsx new file mode 100644 index 000000000..d48646fac --- /dev/null +++ b/packages/excalidraw/actions/actionDeleteSelected.test.tsx @@ -0,0 +1,211 @@ +import React from "react"; +import { Excalidraw, mutateElement } from "../index"; +import { act, assertElements, render } from "../tests/test-utils"; +import { API } from "../tests/helpers/api"; +import { actionDeleteSelected } from "./actionDeleteSelected"; + +const { h } = window; + +describe("deleting selected elements when frame selected should keep children + select them", () => { + beforeEach(async () => { + await render(); + }); + + it("frame only", async () => { + const f1 = API.createElement({ + type: "frame", + }); + + const r1 = API.createElement({ + type: "rectangle", + frameId: f1.id, + }); + + API.setElements([f1, r1]); + + API.setSelectedElements([f1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: r1.id, isDeleted: false, selected: true }, + ]); + }); + + it("frame + text container (text's frameId set)", async () => { + const f1 = API.createElement({ + type: "frame", + }); + + const r1 = API.createElement({ + type: "rectangle", + frameId: f1.id, + }); + + const t1 = API.createElement({ + type: "text", + width: 200, + height: 100, + fontSize: 20, + containerId: r1.id, + frameId: f1.id, + }); + + mutateElement(r1, { + boundElements: [{ type: "text", id: t1.id }], + }); + + API.setElements([f1, r1, t1]); + + API.setSelectedElements([f1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: r1.id, isDeleted: false, selected: true }, + { id: t1.id, isDeleted: false }, + ]); + }); + + it("frame + text container (text's frameId not set)", async () => { + const f1 = API.createElement({ + type: "frame", + }); + + const r1 = API.createElement({ + type: "rectangle", + frameId: f1.id, + }); + + const t1 = API.createElement({ + type: "text", + width: 200, + height: 100, + fontSize: 20, + containerId: r1.id, + frameId: null, + }); + + mutateElement(r1, { + boundElements: [{ type: "text", id: t1.id }], + }); + + API.setElements([f1, r1, t1]); + + API.setSelectedElements([f1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: r1.id, isDeleted: false, selected: true }, + { id: t1.id, isDeleted: false }, + ]); + }); + + it("frame + text container (text selected too)", async () => { + const f1 = API.createElement({ + type: "frame", + }); + + const r1 = API.createElement({ + type: "rectangle", + frameId: f1.id, + }); + + const t1 = API.createElement({ + type: "text", + width: 200, + height: 100, + fontSize: 20, + containerId: r1.id, + frameId: null, + }); + + mutateElement(r1, { + boundElements: [{ type: "text", id: t1.id }], + }); + + API.setElements([f1, r1, t1]); + + API.setSelectedElements([f1, t1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: r1.id, isDeleted: false, selected: true }, + { id: t1.id, isDeleted: false }, + ]); + }); + + it("frame + labeled arrow", async () => { + const f1 = API.createElement({ + type: "frame", + }); + + const a1 = API.createElement({ + type: "arrow", + frameId: f1.id, + }); + + const t1 = API.createElement({ + type: "text", + width: 200, + height: 100, + fontSize: 20, + containerId: a1.id, + frameId: null, + }); + + mutateElement(a1, { + boundElements: [{ type: "text", id: t1.id }], + }); + + API.setElements([f1, a1, t1]); + + API.setSelectedElements([f1, t1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: a1.id, isDeleted: false, selected: true }, + { id: t1.id, isDeleted: false }, + ]); + }); + + it("frame + children selected", async () => { + const f1 = API.createElement({ + type: "frame", + }); + const r1 = API.createElement({ + type: "rectangle", + frameId: f1.id, + }); + API.setElements([f1, r1]); + + API.setSelectedElements([f1, r1]); + + act(() => { + h.app.actionManager.executeAction(actionDeleteSelected); + }); + + assertElements(h.elements, [ + { id: f1.id, isDeleted: true }, + { id: r1.id, isDeleted: false, selected: true }, + ]); + }); +}); diff --git a/packages/excalidraw/actions/actionDeleteSelected.tsx b/packages/excalidraw/actions/actionDeleteSelected.tsx index 882c8b3f3..c66b2c024 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.tsx @@ -18,6 +18,8 @@ import { import { updateActiveTool } from "../utils"; import { TrashIcon } from "../components/icons"; import { StoreAction } from "../store"; +import { getContainerElement } from "../element/textElement"; +import { getFrameChildren } from "../frame"; const deleteSelectedElements = ( elements: readonly ExcalidrawElement[], @@ -33,10 +35,50 @@ const deleteSelectedElements = ( const selectedElementIds: Record = {}; + const elementsMap = app.scene.getNonDeletedElementsMap(); + + const processedElements = new Set(); + + for (const frameId of framesToBeDeleted) { + const frameChildren = getFrameChildren(elements, frameId); + for (const el of frameChildren) { + if (processedElements.has(el.id)) { + continue; + } + + if (isBoundToContainer(el)) { + const containerElement = getContainerElement(el, elementsMap); + if (containerElement) { + selectedElementIds[containerElement.id] = true; + } + } else { + selectedElementIds[el.id] = true; + } + processedElements.add(el.id); + } + } + let shouldSelectEditingGroup = true; const nextElements = elements.map((el) => { if (appState.selectedElementIds[el.id]) { + const boundElement = isBoundToContainer(el) + ? getContainerElement(el, elementsMap) + : null; + + if (el.frameId && framesToBeDeleted.has(el.frameId)) { + shouldSelectEditingGroup = false; + selectedElementIds[el.id] = true; + return el; + } + + if ( + boundElement?.frameId && + framesToBeDeleted.has(boundElement?.frameId) + ) { + return el; + } + if (el.boundElements) { el.boundElements.forEach((candidate) => { const bound = app.scene.getNonDeletedElementsMap().get(candidate.id); @@ -59,7 +101,9 @@ const deleteSelectedElements = ( // if deleting a frame, remove the children from it and select them if (el.frameId && framesToBeDeleted.has(el.frameId)) { shouldSelectEditingGroup = false; - selectedElementIds[el.id] = true; + if (!isBoundToContainer(el)) { + selectedElementIds[el.id] = true; + } return newElementWith(el, { frameId: null }); } @@ -224,11 +268,13 @@ export const actionDeleteSelected = register({ storeAction: StoreAction.CAPTURE, }; } + let { elements: nextElements, appState: nextAppState } = deleteSelectedElements(elements, appState, app); + fixBindingsAfterDeletion( nextElements, - elements.filter(({ id }) => appState.selectedElementIds[id]), + nextElements.filter((el) => el.isDeleted), ); nextAppState = handleGroupEditingState(nextAppState, nextElements); diff --git a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx new file mode 100644 index 000000000..dc471df37 --- /dev/null +++ b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx @@ -0,0 +1,530 @@ +import { Excalidraw } from "../index"; +import { + act, + assertElements, + getCloneByOrigId, + render, +} from "../tests/test-utils"; +import { API } from "../tests/helpers/api"; +import { actionDuplicateSelection } from "./actionDuplicateSelection"; +import React from "react"; +import { ORIG_ID } from "../constants"; + +const { h } = window; + +describe("actionDuplicateSelection", () => { + beforeEach(async () => { + await render(); + }); + + describe("duplicating frames", () => { + it("frame selected only", async () => { + const frame = API.createElement({ + type: "frame", + }); + + const rectangle = API.createElement({ + type: "rectangle", + frameId: frame.id, + }); + + API.setElements([frame, rectangle]); + API.setSelectedElements([frame]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: getCloneByOrigId(frame.id)?.id }, + { [ORIG_ID]: frame.id, selected: true }, + ]); + }); + + it("frame selected only (with text container)", async () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, rectangle, text]); + API.setSelectedElements([frame]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: getCloneByOrigId(frame.id)?.id }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id)?.id, + frameId: getCloneByOrigId(frame.id)?.id, + }, + { [ORIG_ID]: frame.id, selected: true }, + ]); + }); + + it("frame + text container selected (order A)", async () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, rectangle, text]); + API.setSelectedElements([frame, rectangle]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id, frameId: frame.id }, + { + [ORIG_ID]: rectangle.id, + frameId: getCloneByOrigId(frame.id)?.id, + }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id)?.id, + frameId: getCloneByOrigId(frame.id)?.id, + }, + { + [ORIG_ID]: frame.id, + selected: true, + }, + ]); + }); + + it("frame + text container selected (order B)", async () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([text, rectangle, frame]); + API.setSelectedElements([rectangle, frame]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id, frameId: frame.id }, + { id: frame.id }, + { + type: "rectangle", + [ORIG_ID]: `${rectangle.id}`, + }, + { + [ORIG_ID]: `${text.id}`, + type: "text", + containerId: getCloneByOrigId(rectangle.id)?.id, + frameId: getCloneByOrigId(frame.id)?.id, + }, + { [ORIG_ID]: `${frame.id}`, type: "frame", selected: true }, + ]); + }); + }); + + describe("duplicating frame children", () => { + it("frame child selected", () => { + const frame = API.createElement({ + type: "frame", + }); + + const rectangle = API.createElement({ + type: "rectangle", + frameId: frame.id, + }); + + API.setElements([frame, rectangle]); + API.setSelectedElements([rectangle]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: frame.id, selected: true }, + ]); + }); + + it("frame text container selected (rectangle selected)", () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, rectangle, text]); + API.setSelectedElements([rectangle]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: frame.id, selected: true }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id).id, + frameId: frame.id, + }, + ]); + }); + + it("frame bound text selected (container not selected)", () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, rectangle, text]); + API.setSelectedElements([text]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: frame.id, selected: true }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id).id, + frameId: frame.id, + }, + ]); + }); + + it("frame text container selected (text not exists)", () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, rectangle]); + API.setSelectedElements([rectangle]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { [ORIG_ID]: rectangle.id, frameId: frame.id, selected: true }, + ]); + }); + + // shouldn't happen + it("frame bound text selected (container not exists)", () => { + const frame = API.createElement({ + type: "frame", + }); + + const [, text] = API.createTextContainer({ frameId: frame.id }); + + API.setElements([frame, text]); + API.setSelectedElements([text]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: text.id, frameId: frame.id }, + { [ORIG_ID]: text.id, frameId: frame.id }, + ]); + }); + + it("frame bound container selected (text has no frameId)", () => { + const frame = API.createElement({ + type: "frame", + }); + + const [rectangle, text] = API.createTextContainer({ + frameId: frame.id, + label: { frameId: null }, + }); + + API.setElements([frame, rectangle, text]); + API.setSelectedElements([rectangle]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: frame.id }, + { id: rectangle.id, frameId: frame.id }, + { id: text.id, containerId: rectangle.id }, + { [ORIG_ID]: rectangle.id, frameId: frame.id, selected: true }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id).id, + }, + ]); + }); + }); + + describe("duplicating multiple frames", () => { + it("multiple frames selected (no children)", () => { + const frame1 = API.createElement({ + type: "frame", + }); + + const rect1 = API.createElement({ + type: "rectangle", + frameId: frame1.id, + }); + + const frame2 = API.createElement({ + type: "frame", + }); + + const rect2 = API.createElement({ + type: "rectangle", + frameId: frame2.id, + }); + + const ellipse = API.createElement({ + type: "ellipse", + }); + + API.setElements([rect1, frame1, ellipse, rect2, frame2]); + API.setSelectedElements([frame1, frame2]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rect1.id, frameId: frame1.id }, + { id: frame1.id }, + { [ORIG_ID]: rect1.id, frameId: getCloneByOrigId(frame1.id)?.id }, + { [ORIG_ID]: frame1.id, selected: true }, + { id: ellipse.id }, + { id: rect2.id, frameId: frame2.id }, + { id: frame2.id }, + { [ORIG_ID]: rect2.id, frameId: getCloneByOrigId(frame2.id)?.id }, + { [ORIG_ID]: frame2.id, selected: true }, + ]); + }); + + it("multiple frames selected (no children) + unrelated element", () => { + const frame1 = API.createElement({ + type: "frame", + }); + + const rect1 = API.createElement({ + type: "rectangle", + frameId: frame1.id, + }); + + const frame2 = API.createElement({ + type: "frame", + }); + + const rect2 = API.createElement({ + type: "rectangle", + frameId: frame2.id, + }); + + const ellipse = API.createElement({ + type: "ellipse", + }); + + API.setElements([rect1, frame1, ellipse, rect2, frame2]); + API.setSelectedElements([frame1, ellipse, frame2]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rect1.id, frameId: frame1.id }, + { id: frame1.id }, + { [ORIG_ID]: rect1.id, frameId: getCloneByOrigId(frame1.id)?.id }, + { [ORIG_ID]: frame1.id, selected: true }, + { id: ellipse.id }, + { [ORIG_ID]: ellipse.id, selected: true }, + { id: rect2.id, frameId: frame2.id }, + { id: frame2.id }, + { [ORIG_ID]: rect2.id, frameId: getCloneByOrigId(frame2.id)?.id }, + { [ORIG_ID]: frame2.id, selected: true }, + ]); + }); + }); + + describe("duplicating containers/bound elements", () => { + it("labeled arrow (arrow selected)", () => { + const [arrow, text] = API.createLabeledArrow(); + + API.setElements([arrow, text]); + API.setSelectedElements([arrow]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: arrow.id }, + { id: text.id, containerId: arrow.id }, + { [ORIG_ID]: arrow.id, selected: true }, + { [ORIG_ID]: text.id, containerId: getCloneByOrigId(arrow.id)?.id }, + ]); + }); + + // shouldn't happen + it("labeled arrow (text selected)", () => { + const [arrow, text] = API.createLabeledArrow(); + + API.setElements([arrow, text]); + API.setSelectedElements([text]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: arrow.id }, + { id: text.id, containerId: arrow.id }, + { [ORIG_ID]: arrow.id, selected: true }, + { [ORIG_ID]: text.id, containerId: getCloneByOrigId(arrow.id)?.id }, + ]); + }); + }); + + describe("duplicating groups", () => { + it("duplicate group containing frame (children don't have groupIds set)", () => { + const frame = API.createElement({ + type: "frame", + groupIds: ["A"], + }); + + const [rectangle, text] = API.createTextContainer({ + frameId: frame.id, + }); + + const ellipse = API.createElement({ + type: "ellipse", + groupIds: ["A"], + }); + + API.setElements([rectangle, text, frame, ellipse]); + API.setSelectedElements([frame, ellipse]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle.id, frameId: frame.id }, + { id: text.id, frameId: frame.id }, + { id: frame.id }, + { id: ellipse.id }, + { [ORIG_ID]: rectangle.id, frameId: getCloneByOrigId(frame.id)?.id }, + { [ORIG_ID]: text.id, frameId: getCloneByOrigId(frame.id)?.id }, + { [ORIG_ID]: frame.id, selected: true }, + { [ORIG_ID]: ellipse.id, selected: true }, + ]); + }); + + it("duplicate group containing frame (children have groupIds)", () => { + const frame = API.createElement({ + type: "frame", + groupIds: ["A"], + }); + + const [rectangle, text] = API.createTextContainer({ + frameId: frame.id, + groupIds: ["A"], + }); + + const ellipse = API.createElement({ + type: "ellipse", + groupIds: ["A"], + }); + + API.setElements([rectangle, text, frame, ellipse]); + API.setSelectedElements([frame, ellipse]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle.id, frameId: frame.id }, + { id: text.id, frameId: frame.id }, + { id: frame.id }, + { id: ellipse.id }, + { + [ORIG_ID]: rectangle.id, + frameId: getCloneByOrigId(frame.id)?.id, + // FIXME shouldn't be selected (in selectGroupsForSelectedElements) + selected: true, + }, + { + [ORIG_ID]: text.id, + frameId: getCloneByOrigId(frame.id)?.id, + // FIXME shouldn't be selected (in selectGroupsForSelectedElements) + selected: true, + }, + { [ORIG_ID]: frame.id, selected: true }, + { [ORIG_ID]: ellipse.id, selected: true }, + ]); + }); + + it("duplicating element nested in group", () => { + const ellipse = API.createElement({ + type: "ellipse", + groupIds: ["B"], + }); + const rect1 = API.createElement({ + type: "rectangle", + groupIds: ["A", "B"], + }); + const rect2 = API.createElement({ + type: "rectangle", + groupIds: ["A", "B"], + }); + + API.setElements([ellipse, rect1, rect2]); + API.setSelectedElements([ellipse], "B"); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: ellipse.id }, + { [ORIG_ID]: ellipse.id, groupIds: ["B"], selected: true }, + { id: rect1.id, groupIds: ["A", "B"] }, + { id: rect2.id, groupIds: ["A", "B"] }, + ]); + }); + }); +}); diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index d19bfa59d..735c5cf23 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -5,7 +5,13 @@ import { duplicateElement, getNonDeletedElements } from "../element"; import { isSomeElementSelected } from "../scene"; import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; -import { arrayToMap, getShortcutKey } from "../utils"; +import { + arrayToMap, + castArray, + findLastIndex, + getShortcutKey, + invariant, +} from "../utils"; import { LinearElementEditor } from "../element/linearElementEditor"; import { selectGroupsForSelectedElements, @@ -19,8 +25,13 @@ import { DEFAULT_GRID_SIZE } from "../constants"; import { bindTextToShapeAfterDuplication, getBoundTextElement, + getContainerElement, } from "../element/textElement"; -import { isBoundToContainer, isFrameLikeElement } from "../element/typeChecks"; +import { + hasBoundTextElement, + isBoundToContainer, + isFrameLikeElement, +} from "../element/typeChecks"; import { normalizeElementOrder } from "../element/sortElements"; import { DuplicateIcon } from "../components/icons"; import { @@ -31,7 +42,6 @@ import { excludeElementsInFramesFromSelection, getSelectedElements, } from "../scene/selection"; -import { syncMovedIndices } from "../fractionalIndex"; import { StoreAction } from "../store"; export const actionDuplicateSelection = register({ @@ -85,34 +95,66 @@ const duplicateElements = ( ): Partial => { // --------------------------------------------------------------------------- - // step (1) - - const sortedElements = normalizeElementOrder(elements); const groupIdMap = new Map(); const newElements: ExcalidrawElement[] = []; const oldElements: ExcalidrawElement[] = []; const oldIdToDuplicatedId = new Map(); const duplicatedElementsMap = new Map(); - const duplicateAndOffsetElement = (element: ExcalidrawElement) => { - const newElement = duplicateElement( - appState.editingGroupId, - groupIdMap, - element, - { - x: element.x + DEFAULT_GRID_SIZE / 2, - y: element.y + DEFAULT_GRID_SIZE / 2, + const elementsMap = arrayToMap(elements); + + const duplicateAndOffsetElement = < + T extends ExcalidrawElement | ExcalidrawElement[], + >( + element: T, + ): T extends ExcalidrawElement[] + ? ExcalidrawElement[] + : ExcalidrawElement | null => { + const elements = castArray(element); + + const _newElements = elements.reduce( + (acc: ExcalidrawElement[], element) => { + if (processedIds.has(element.id)) { + return acc; + } + + processedIds.set(element.id, true); + + const newElement = duplicateElement( + appState.editingGroupId, + groupIdMap, + element, + { + x: element.x + DEFAULT_GRID_SIZE / 2, + y: element.y + DEFAULT_GRID_SIZE / 2, + }, + ); + + processedIds.set(newElement.id, true); + + duplicatedElementsMap.set(newElement.id, newElement); + oldIdToDuplicatedId.set(element.id, newElement.id); + + oldElements.push(element); + newElements.push(newElement); + + acc.push(newElement); + return acc; }, + [], ); - duplicatedElementsMap.set(newElement.id, newElement); - oldIdToDuplicatedId.set(element.id, newElement.id); - oldElements.push(element); - newElements.push(newElement); - return newElement; + + return ( + Array.isArray(element) ? _newElements : _newElements[0] || null + ) as T extends ExcalidrawElement[] + ? ExcalidrawElement[] + : ExcalidrawElement | null; }; + elements = normalizeElementOrder(elements); + const idsOfElementsToDuplicate = arrayToMap( - getSelectedElements(sortedElements, appState, { + getSelectedElements(elements, appState, { includeBoundTextElement: true, includeElementsInFrames: true, }), @@ -130,122 +172,133 @@ const duplicateElements = ( // loop over them. const processedIds = new Map(); - const markAsProcessed = (elements: ExcalidrawElement[]) => { - for (const element of elements) { - processedIds.set(element.id, true); + const elementsWithClones: ExcalidrawElement[] = elements.slice(); + + const insertAfterIndex = ( + index: number, + elements: ExcalidrawElement | null | ExcalidrawElement[], + ) => { + invariant(index !== -1, "targetIndex === -1 "); + + if (!Array.isArray(elements) && !elements) { + return; } - return elements; + + elementsWithClones.splice(index + 1, 0, ...castArray(elements)); }; - const elementsWithClones: ExcalidrawElement[] = []; + const frameIdsToDuplicate = new Set( + elements + .filter( + (el) => idsOfElementsToDuplicate.has(el.id) && isFrameLikeElement(el), + ) + .map((el) => el.id), + ); - let index = -1; - - while (++index < sortedElements.length) { - const element = sortedElements[index]; - - if (processedIds.get(element.id)) { + for (const element of elements) { + if (processedIds.has(element.id)) { continue; } - const boundTextElement = getBoundTextElement(element, arrayToMap(elements)); - const isElementAFrameLike = isFrameLikeElement(element); + if (!idsOfElementsToDuplicate.has(element.id)) { + continue; + } - if (idsOfElementsToDuplicate.get(element.id)) { - // if a group or a container/bound-text or frame, duplicate atomically - if (element.groupIds.length || boundTextElement || isElementAFrameLike) { - const groupId = getSelectedGroupForElement(appState, element); - if (groupId) { - // TODO: - // remove `.flatMap...` - // if the elements in a frame are grouped when the frame is grouped - const groupElements = getElementsInGroup( - sortedElements, - groupId, - ).flatMap((element) => - isFrameLikeElement(element) - ? [...getFrameChildren(elements, element.id), element] - : [element], - ); + // groups + // ------------------------------------------------------------------------- - elementsWithClones.push( - ...markAsProcessed([ - ...groupElements, - ...groupElements.map((element) => - duplicateAndOffsetElement(element), - ), - ]), - ); - continue; - } - if (boundTextElement) { - elementsWithClones.push( - ...markAsProcessed([ - element, - boundTextElement, - duplicateAndOffsetElement(element), - duplicateAndOffsetElement(boundTextElement), - ]), - ); - continue; - } - if (isElementAFrameLike) { - const elementsInFrame = getFrameChildren(sortedElements, element.id); + const groupId = getSelectedGroupForElement(appState, element); + if (groupId) { + const groupElements = getElementsInGroup(elements, groupId).flatMap( + (element) => + isFrameLikeElement(element) + ? [...getFrameChildren(elements, element.id), element] + : [element], + ); - elementsWithClones.push( - ...markAsProcessed([ - ...elementsInFrame, - element, - ...elementsInFrame.map((e) => duplicateAndOffsetElement(e)), - duplicateAndOffsetElement(element), - ]), - ); + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return el.groupIds?.includes(groupId); + }); - continue; - } - } - // since elements in frames have a lower z-index than the frame itself, - // they will be looped first and if their frames are selected as well, - // they will have been copied along with the frame atomically in the - // above branch, so we must skip those elements here - // - // now, for elements do not belong any frames or elements whose frames - // are selected (or elements that are left out from the above - // steps for whatever reason) we (should at least) duplicate them here - if (!element.frameId || !idsOfElementsToDuplicate.has(element.frameId)) { - elementsWithClones.push( - ...markAsProcessed([element, duplicateAndOffsetElement(element)]), + insertAfterIndex(targetIndex, duplicateAndOffsetElement(groupElements)); + continue; + } + + // frame duplication + // ------------------------------------------------------------------------- + + if (element.frameId && frameIdsToDuplicate.has(element.frameId)) { + continue; + } + + if (isFrameLikeElement(element)) { + const frameId = element.id; + + const frameChildren = getFrameChildren(elements, frameId); + + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return el.frameId === frameId || el.id === frameId; + }); + + insertAfterIndex( + targetIndex, + duplicateAndOffsetElement([...frameChildren, element]), + ); + continue; + } + + // text container + // ------------------------------------------------------------------------- + + if (hasBoundTextElement(element)) { + const boundTextElement = getBoundTextElement(element, elementsMap); + + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return ( + el.id === element.id || + ("containerId" in el && el.containerId === element.id) ); + }); + + if (boundTextElement) { + insertAfterIndex( + targetIndex, + duplicateAndOffsetElement([element, boundTextElement]), + ); + } else { + insertAfterIndex(targetIndex, duplicateAndOffsetElement(element)); } - } else { - elementsWithClones.push(...markAsProcessed([element])); + + continue; } - } - // step (2) + if (isBoundToContainer(element)) { + const container = getContainerElement(element, elementsMap); - // second pass to remove duplicates. We loop from the end as it's likelier - // that the last elements are in the correct order (contiguous or otherwise). - // Thus we need to reverse as the last step (3). + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return el.id === element.id || el.id === container?.id; + }); - const finalElementsReversed: ExcalidrawElement[] = []; + if (container) { + insertAfterIndex( + targetIndex, + duplicateAndOffsetElement([container, element]), + ); + } else { + insertAfterIndex(targetIndex, duplicateAndOffsetElement(element)); + } - const finalElementIds = new Map(); - index = elementsWithClones.length; - - while (--index >= 0) { - const element = elementsWithClones[index]; - if (!finalElementIds.get(element.id)) { - finalElementIds.set(element.id, true); - finalElementsReversed.push(element); + continue; } - } - // step (3) - const finalElements = syncMovedIndices( - finalElementsReversed.reverse(), - arrayToMap(newElements), - ); + // default duplication (regular elements) + // ------------------------------------------------------------------------- + + insertAfterIndex( + findLastIndex(elementsWithClones, (el) => el.id === element.id), + duplicateAndOffsetElement(element), + ); + } // --------------------------------------------------------------------------- @@ -260,7 +313,7 @@ const duplicateElements = ( oldIdToDuplicatedId, ); bindElementsToFramesAfterDuplication( - finalElements, + elementsWithClones, oldElements, oldIdToDuplicatedId, ); @@ -269,7 +322,7 @@ const duplicateElements = ( excludeElementsInFramesFromSelection(newElements); return { - elements: finalElements, + elements: elementsWithClones, appState: { ...appState, ...selectGroupsForSelectedElements( @@ -285,7 +338,7 @@ const duplicateElements = ( {}, ), }, - getNonDeletedElements(finalElements), + getNonDeletedElements(elementsWithClones), appState, null, ), diff --git a/packages/excalidraw/constants.ts b/packages/excalidraw/constants.ts index b8f7e1b83..cb32190b2 100644 --- a/packages/excalidraw/constants.ts +++ b/packages/excalidraw/constants.ts @@ -458,3 +458,6 @@ export const ARROW_TYPE: { [T in AppState["currentItemArrowType"]]: T } = { export const DEFAULT_REDUCED_GLOBAL_ALPHA = 0.3; export const ELEMENT_LINK_KEY = "element"; + +/** used in tests */ +export const ORIG_ID = Symbol.for("__test__originalId__"); diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index a79f077aa..58b5ec43f 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -45,6 +45,7 @@ import { DEFAULT_FONT_SIZE, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, + ORIG_ID, VERTICAL_ALIGN, } from "../constants"; import type { MarkOptional, Merge, Mutable } from "../utility-types"; @@ -592,26 +593,18 @@ export const deepCopyElement = ( return _deepCopyElement(val); }; +const __test__defineOrigId = (clonedObj: object, origId: string) => { + Object.defineProperty(clonedObj, ORIG_ID, { + value: origId, + writable: false, + enumerable: false, + }); +}; + /** - * utility wrapper to generate new id. In test env it reuses the old + postfix - * for test assertions. + * utility wrapper to generate new id. */ -export const regenerateId = ( - /** supply null if no previous id exists */ - previousId: string | null, -) => { - if (isTestEnv() && previousId) { - let nextId = `${previousId}_copy`; - // `window.h` may not be defined in some unit tests - if ( - window.h?.app - ?.getSceneElementsIncludingDeleted() - .find((el: ExcalidrawElement) => el.id === nextId) - ) { - nextId += "_copy"; - } - return nextId; - } +const regenerateId = () => { return randomId(); }; @@ -637,7 +630,11 @@ export const duplicateElement = ( ): Readonly => { let copy = deepCopyElement(element); - copy.id = regenerateId(copy.id); + if (isTestEnv()) { + __test__defineOrigId(copy, element.id); + } + + copy.id = regenerateId(); copy.boundElements = null; copy.updated = getUpdatedTimestamp(); copy.seed = randomInteger(); @@ -646,7 +643,7 @@ export const duplicateElement = ( editingGroupId, (groupId) => { if (!groupIdMapForOperation.has(groupId)) { - groupIdMapForOperation.set(groupId, regenerateId(groupId)); + groupIdMapForOperation.set(groupId, regenerateId()); } return groupIdMapForOperation.get(groupId)!; }, @@ -692,7 +689,7 @@ export const duplicateElements = ( // if we haven't migrated the element id, but an old element with the same // id exists, generate a new id for it and return it if (origElementsMap.has(id)) { - const newId = regenerateId(id); + const newId = regenerateId(); elementNewIdsMap.set(id, newId); return newId; } @@ -706,6 +703,9 @@ export const duplicateElements = ( const clonedElement: Mutable = _deepCopyElement(element); clonedElement.id = maybeGetNewId(element.id)!; + if (isTestEnv()) { + __test__defineOrigId(clonedElement, element.id); + } if (opts?.randomizeSeed) { clonedElement.seed = randomInteger(); @@ -715,7 +715,7 @@ export const duplicateElements = ( if (clonedElement.groupIds) { clonedElement.groupIds = clonedElement.groupIds.map((groupId) => { if (!groupNewIdsMap.has(groupId)) { - groupNewIdsMap.set(groupId, regenerateId(groupId)); + groupNewIdsMap.set(groupId, regenerateId()); } return groupNewIdsMap.get(groupId)!; }); diff --git a/packages/excalidraw/element/sortElements.ts b/packages/excalidraw/element/sortElements.ts index bb758370a..3078a6827 100644 --- a/packages/excalidraw/element/sortElements.ts +++ b/packages/excalidraw/element/sortElements.ts @@ -116,8 +116,5 @@ const normalizeBoundElementsOrder = ( export const normalizeElementOrder = ( elements: readonly ExcalidrawElement[], ) => { - // console.time(); - const ret = normalizeBoundElementsOrder(normalizeGroupElementOrder(elements)); - // console.timeEnd(); - return ret; + return normalizeBoundElementsOrder(normalizeGroupElementOrder(elements)); }; diff --git a/packages/excalidraw/frame.test.tsx b/packages/excalidraw/frame.test.tsx index 010ed9343..6a5045b2c 100644 --- a/packages/excalidraw/frame.test.tsx +++ b/packages/excalidraw/frame.test.tsx @@ -1,9 +1,8 @@ -import React from "react"; import type { ExcalidrawElement } from "./element/types"; import { convertToExcalidrawElements, Excalidraw } from "./index"; import { API } from "./tests/helpers/api"; import { Keyboard, Pointer } from "./tests/helpers/ui"; -import { render } from "./tests/test-utils"; +import { getCloneByOrigId, render } from "./tests/test-utils"; const { h } = window; const mouse = new Pointer("mouse"); @@ -413,10 +412,10 @@ describe("adding elements to frames", () => { dragElementIntoFrame(frame, rect2); - const rect2_copy = { ...rect2, id: `${rect2.id}_copy` }; - selectElementAndDuplicate(rect2); + const rect2_copy = getCloneByOrigId(rect2.id); + expect(rect2_copy.frameId).toBe(frame.id); expect(rect2.frameId).toBe(frame.id); expectEqualIds([rect2_copy, rect2, frame]); @@ -427,11 +426,11 @@ describe("adding elements to frames", () => { dragElementIntoFrame(frame, rect2); - const rect2_copy = { ...rect2, id: `${rect2.id}_copy` }; - // move the rect2 outside the frame selectElementAndDuplicate(rect2, [-1000, -1000]); + const rect2_copy = getCloneByOrigId(rect2.id); + expect(rect2_copy.frameId).toBe(frame.id); expect(rect2.frameId).toBe(null); expectEqualIds([rect2_copy, frame, rect2]); diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json index fdbda46b8..b1f3e691b 100644 --- a/packages/excalidraw/package.json +++ b/packages/excalidraw/package.json @@ -103,6 +103,7 @@ "@types/pako": "1.0.3", "@types/pica": "5.1.3", "@types/resize-observer-browser": "0.1.7", + "ansicolor": "2.0.3", "autoprefixer": "10.4.7", "babel-loader": "8.2.5", "babel-plugin-transform-class-properties": "6.24.1", diff --git a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap index 36666faec..f77eb8ddb 100644 --- a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap @@ -2517,7 +2517,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates "scrolledOutside": false, "searchMatches": [], "selectedElementIds": { - "id0_copy": true, + "id1": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -2590,7 +2590,7 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates "frameId": null, "groupIds": [], "height": 20, - "id": "id0_copy", + "id": "id1", "index": "a1", "isDeleted": false, "link": null, @@ -2680,7 +2680,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id0_copy": true, + "id1": true, }, }, "inserted": { @@ -2693,7 +2693,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id0_copy" => Delta { + "id1" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 58bc9303e..9e353c06f 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -78,14 +78,14 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id166": true, + "id172": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id166": true, + "id172": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -123,7 +123,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id164", + "id": "id170", "index": "a0", "isDeleted": false, "link": null, @@ -155,7 +155,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id165", + "id": "id171", "index": "a1", "isDeleted": false, "link": null, @@ -186,7 +186,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id169", + "elementId": "id175", "fixedPoint": [ "0.50000", 1, @@ -198,7 +198,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 99, - "id": "id166", + "id": "id172", "index": "a2", "isDeleted": false, "lastCommittedPoint": null, @@ -239,7 +239,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id166", + "id": "id172", "type": "arrow", }, ], @@ -248,7 +248,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 50, - "id": "id169", + "id": "id175", "index": "a3", "isDeleted": false, "link": null, @@ -290,10 +290,10 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id166" => Delta { + "id172" => Delta { "deleted": { "endBinding": { - "elementId": "id165", + "elementId": "id171", "fixedPoint": null, "focus": "0.00990", "gap": 1, @@ -310,7 +310,7 @@ History { ], ], "startBinding": { - "elementId": "id164", + "elementId": "id170", "fixedPoint": null, "focus": "0.02970", "gap": 1, @@ -318,7 +318,7 @@ History { }, "inserted": { "endBinding": { - "elementId": "id165", + "elementId": "id171", "fixedPoint": null, "focus": "-0.02000", "gap": 1, @@ -335,7 +335,7 @@ History { ], ], "startBinding": { - "elementId": "id164", + "elementId": "id170", "fixedPoint": null, "focus": "0.02000", "gap": 1, @@ -356,36 +356,36 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id164" => Delta { + "id170" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id166", + "id": "id172", "type": "arrow", }, ], }, }, - "id165" => Delta { + "id171" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id166", + "id": "id172", "type": "arrow", }, ], }, }, - "id166" => Delta { + "id172" => Delta { "deleted": { "endBinding": { - "elementId": "id169", + "elementId": "id175", "fixedPoint": [ "0.50000", 1, @@ -409,7 +409,7 @@ History { }, "inserted": { "endBinding": { - "elementId": "id165", + "elementId": "id171", "fixedPoint": null, "focus": "0.00990", "gap": 1, @@ -426,7 +426,7 @@ History { ], ], "startBinding": { - "elementId": "id164", + "elementId": "id170", "fixedPoint": null, "focus": "0.02970", "gap": 1, @@ -434,11 +434,11 @@ History { "y": "0.99245", }, }, - "id169" => Delta { + "id175" => Delta { "deleted": { "boundElements": [ { - "id": "id166", + "id": "id172", "type": "arrow", }, ], @@ -462,7 +462,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id164" => Delta { + "id170" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -493,7 +493,7 @@ History { "isDeleted": true, }, }, - "id165" => Delta { + "id171" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -533,9 +533,9 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id166": true, + "id172": true, }, - "selectedLinearElementId": "id166", + "selectedLinearElementId": "id172", }, "inserted": { "selectedElementIds": {}, @@ -546,7 +546,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id166" => Delta { + "id172" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -683,14 +683,14 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id161": true, + "id167": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id161": true, + "id167": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -728,7 +728,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id159", + "id": "id165", "index": "a0", "isDeleted": false, "link": null, @@ -760,7 +760,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id160", + "id": "id166", "index": "a1", "isDeleted": false, "link": null, @@ -795,7 +795,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 0, - "id": "id161", + "id": "id167", "index": "a2", "isDeleted": false, "lastCommittedPoint": null, @@ -850,7 +850,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id161" => Delta { + "id167" => Delta { "deleted": { "points": [ [ @@ -890,33 +890,33 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id159" => Delta { + "id165" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id161", + "id": "id167", "type": "arrow", }, ], }, }, - "id160" => Delta { + "id166" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id161", + "id": "id167", "type": "arrow", }, ], }, }, - "id161" => Delta { + "id167" => Delta { "deleted": { "endBinding": null, "points": [ @@ -933,7 +933,7 @@ History { }, "inserted": { "endBinding": { - "elementId": "id160", + "elementId": "id166", "fixedPoint": null, "focus": 0, "gap": 1, @@ -949,7 +949,7 @@ History { ], ], "startBinding": { - "elementId": "id159", + "elementId": "id165", "fixedPoint": null, "focus": 0, "gap": 1, @@ -971,7 +971,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id159" => Delta { + "id165" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1002,7 +1002,7 @@ History { "isDeleted": true, }, }, - "id160" => Delta { + "id166" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1042,9 +1042,9 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id161": true, + "id167": true, }, - "selectedLinearElementId": "id161", + "selectedLinearElementId": "id167", }, "inserted": { "selectedElementIds": {}, @@ -1055,7 +1055,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id161" => Delta { + "id167" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1235,7 +1235,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "elbowed": false, "endArrowhead": null, "endBinding": { - "elementId": "id171", + "elementId": "id177", "fixedPoint": [ "0.50000", 1, @@ -1247,7 +1247,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": "2.61991", - "id": "id172", + "id": "id178", "index": "Zz", "isDeleted": false, "lastCommittedPoint": null, @@ -1270,7 +1270,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "startArrowhead": null, "startBinding": { - "elementId": "id170", + "elementId": "id176", "fixedPoint": [ 1, "0.50000", @@ -1296,7 +1296,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id172", + "id": "id178", "type": "arrow", }, ], @@ -1305,7 +1305,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id170", + "id": "id176", "index": "a0", "isDeleted": false, "link": null, @@ -1333,7 +1333,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id172", + "id": "id178", "type": "arrow", }, ], @@ -1342,7 +1342,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id171", + "id": "id177", "index": "a1", "isDeleted": false, "link": null, @@ -1384,7 +1384,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id170" => Delta { + "id176" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1415,7 +1415,7 @@ History { "isDeleted": true, }, }, - "id171" => Delta { + "id177" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1448,10 +1448,10 @@ History { }, }, "updated": Map { - "id172" => Delta { + "id178" => Delta { "deleted": { "endBinding": { - "elementId": "id171", + "elementId": "id177", "fixedPoint": [ "0.50000", 1, @@ -1460,7 +1460,7 @@ History { "gap": 1, }, "startBinding": { - "elementId": "id170", + "elementId": "id176", "fixedPoint": [ 1, "0.50000", @@ -1606,7 +1606,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "elbowed": false, "endArrowhead": null, "endBinding": { - "elementId": "id174", + "elementId": "id180", "fixedPoint": [ 1, "0.50000", @@ -1618,7 +1618,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": "2.61991", - "id": "id175", + "id": "id181", "index": "a0", "isDeleted": false, "lastCommittedPoint": null, @@ -1641,7 +1641,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "startArrowhead": null, "startBinding": { - "elementId": "id173", + "elementId": "id179", "fixedPoint": [ "0.50000", 1, @@ -1667,7 +1667,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id175", + "id": "id181", "type": "arrow", }, ], @@ -1676,7 +1676,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id173", + "id": "id179", "index": "a0V", "isDeleted": false, "link": null, @@ -1704,7 +1704,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id175", + "id": "id181", "type": "arrow", }, ], @@ -1713,7 +1713,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id174", + "id": "id180", "index": "a1", "isDeleted": false, "link": null, @@ -1755,7 +1755,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id175" => Delta { + "id181" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -1764,7 +1764,7 @@ History { "elbowed": false, "endArrowhead": null, "endBinding": { - "elementId": "id174", + "elementId": "id180", "fixedPoint": [ 1, "0.50000", @@ -1798,7 +1798,7 @@ History { }, "startArrowhead": null, "startBinding": { - "elementId": "id173", + "elementId": "id179", "fixedPoint": [ "0.50000", 1, @@ -1820,11 +1820,11 @@ History { }, }, "updated": Map { - "id173" => Delta { + "id179" => Delta { "deleted": { "boundElements": [ { - "id": "id175", + "id": "id181", "type": "arrow", }, ], @@ -1833,11 +1833,11 @@ History { "boundElements": [], }, }, - "id174" => Delta { + "id180" => Delta { "deleted": { "boundElements": [ { - "id": "id175", + "id": "id181", "type": "arrow", }, ], @@ -1979,7 +1979,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id176", + "id": "id182", "index": "a0", "isDeleted": false, "link": null, @@ -2011,7 +2011,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id177", + "id": "id183", "index": "a1", "isDeleted": false, "link": null, @@ -2053,7 +2053,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id176" => Delta { + "id182" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -2084,7 +2084,7 @@ History { "isDeleted": true, }, }, - "id177" => Delta { + "id183" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -2210,7 +2210,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id180": true, + "id186": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -2244,7 +2244,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id180", + "id": "id186", "type": "arrow", }, ], @@ -2253,7 +2253,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id178", + "id": "id184", "index": "a0", "isDeleted": false, "link": null, @@ -2281,7 +2281,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "backgroundColor": "transparent", "boundElements": [ { - "id": "id180", + "id": "id186", "type": "arrow", }, ], @@ -2290,7 +2290,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": 100, - "id": "id179", + "id": "id185", "index": "a1", "isDeleted": false, "link": null, @@ -2321,7 +2321,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id179", + "elementId": "id185", "fixedPoint": null, "focus": 0, "gap": 1, @@ -2330,7 +2330,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "frameId": null, "groupIds": [], "height": "408.19672", - "id": "id180", + "id": "id186", "index": "a2", "isDeleted": false, "lastCommittedPoint": null, @@ -2353,7 +2353,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl }, "startArrowhead": null, "startBinding": { - "elementId": "id178", + "elementId": "id184", "fixedPoint": null, "focus": 0, "gap": 1, @@ -2390,7 +2390,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id178" => Delta { + "id184" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -2421,7 +2421,7 @@ History { "isDeleted": true, }, }, - "id179" => Delta { + "id185" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -2461,9 +2461,9 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id180": true, + "id186": true, }, - "selectedLinearElementId": "id180", + "selectedLinearElementId": "id186", }, "inserted": { "selectedElementIds": {}, @@ -2474,7 +2474,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id180" => Delta { + "id186" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -2483,7 +2483,7 @@ History { "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id179", + "elementId": "id185", "fixedPoint": null, "focus": 0, "gap": 1, @@ -2514,7 +2514,7 @@ History { }, "startArrowhead": null, "startBinding": { - "elementId": "id178", + "elementId": "id184", "fixedPoint": null, "focus": 0, "gap": 1, @@ -2533,11 +2533,11 @@ History { }, }, "updated": Map { - "id178" => Delta { + "id184" => Delta { "deleted": { "boundElements": [ { - "id": "id180", + "id": "id186", "type": "arrow", }, ], @@ -2546,11 +2546,11 @@ History { "boundElements": [], }, }, - "id179" => Delta { + "id185" => Delta { "deleted": { "boundElements": [ { - "id": "id180", + "id": "id186", "type": "arrow", }, ], @@ -2688,7 +2688,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id147", + "id": "id153", "type": "text", }, ], @@ -2697,7 +2697,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id145", + "id": "id151", "index": "a0", "isDeleted": false, "link": null, @@ -2733,7 +2733,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id146", + "id": "id152", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -2766,7 +2766,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id145", + "containerId": "id151", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -2774,7 +2774,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id147", + "id": "id153", "index": "a2", "isDeleted": false, "lineHeight": "1.25000", @@ -2821,7 +2821,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id145" => Delta { + "id151" => Delta { "deleted": { "isDeleted": false, }, @@ -2852,7 +2852,7 @@ History { "y": 10, }, }, - "id146" => Delta { + "id152" => Delta { "deleted": { "containerId": null, }, @@ -2990,7 +2990,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id150", + "id": "id156", "type": "text", }, ], @@ -2999,7 +2999,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id148", + "id": "id154", "index": "Zz", "isDeleted": false, "link": null, @@ -3027,7 +3027,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id148", + "containerId": "id154", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -3035,7 +3035,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id149", + "id": "id155", "index": "a0", "isDeleted": true, "lineHeight": "1.25000", @@ -3068,7 +3068,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id148", + "containerId": "id154", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -3076,7 +3076,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id150", + "id": "id156", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -3121,9 +3121,9 @@ History { }, "elementsChange": ElementsChange { "added": Map { - "id149" => Delta { + "id155" => Delta { "deleted": { - "containerId": "id148", + "containerId": "id154", "isDeleted": true, }, "inserted": { @@ -3134,14 +3134,14 @@ History { }, "removed": Map {}, "updated": Map { - "id148" => Delta { + "id154" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id149", + "id": "id155", "type": "text", }, ], @@ -3277,7 +3277,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id137", + "id": "id143", "type": "text", }, ], @@ -3286,7 +3286,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id135", + "id": "id141", "index": "a0", "isDeleted": false, "link": null, @@ -3314,7 +3314,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id135", + "containerId": "id141", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -3322,7 +3322,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id137", + "id": "id143", "index": "a0V", "isDeleted": false, "lineHeight": "1.25000", @@ -3363,7 +3363,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id136", + "id": "id142", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -3410,11 +3410,11 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id135" => Delta { + "id141" => Delta { "deleted": { "boundElements": [ { - "id": "id137", + "id": "id143", "type": "text", }, ], @@ -3422,23 +3422,23 @@ History { "inserted": { "boundElements": [ { - "id": "id136", + "id": "id142", "type": "text", }, ], }, }, - "id136" => Delta { + "id142" => Delta { "deleted": { "containerId": null, }, "inserted": { - "containerId": "id135", + "containerId": "id141", }, }, - "id137" => Delta { + "id143" => Delta { "deleted": { - "containerId": "id135", + "containerId": "id141", }, "inserted": { "containerId": null, @@ -3578,7 +3578,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id138", + "id": "id144", "index": "a0", "isDeleted": false, "link": null, @@ -3606,7 +3606,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id139", + "id": "id145", "type": "text", }, ], @@ -3615,7 +3615,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 60, - "id": "id140", + "id": "id146", "index": "a0V", "isDeleted": false, "link": null, @@ -3643,7 +3643,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id140", + "containerId": "id146", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -3651,7 +3651,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 50, - "id": "id139", + "id": "id145", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -3699,32 +3699,32 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id138" => Delta { + "id144" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id139", + "id": "id145", "type": "text", }, ], }, }, - "id139" => Delta { + "id145" => Delta { "deleted": { - "containerId": "id140", + "containerId": "id146", }, "inserted": { - "containerId": "id138", + "containerId": "id144", }, }, - "id140" => Delta { + "id146" => Delta { "deleted": { "boundElements": [ { - "id": "id139", + "id": "id145", "type": "text", }, ], @@ -3867,7 +3867,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id133", + "id": "id139", "index": "a0", "isDeleted": false, "link": null, @@ -3903,7 +3903,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id134", + "id": "id140", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -3950,25 +3950,25 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id133" => Delta { + "id139" => Delta { "deleted": { "boundElements": [], }, "inserted": { "boundElements": [ { - "id": "id134", + "id": "id140", "type": "text", }, ], }, }, - "id134" => Delta { + "id140" => Delta { "deleted": { "containerId": null, }, "inserted": { - "containerId": "id133", + "containerId": "id139", }, }, }, @@ -4101,7 +4101,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id142", + "id": "id148", "type": "text", }, ], @@ -4110,7 +4110,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id141", + "id": "id147", "index": "a0", "isDeleted": false, "link": null, @@ -4138,7 +4138,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id141", + "containerId": "id147", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -4146,7 +4146,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id142", + "id": "id148", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -4193,7 +4193,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id141" => Delta { + "id147" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -4226,9 +4226,9 @@ History { }, }, "updated": Map { - "id142" => Delta { + "id148" => Delta { "deleted": { - "containerId": "id141", + "containerId": "id147", }, "inserted": { "containerId": null, @@ -4363,7 +4363,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id144", + "id": "id150", "type": "text", }, ], @@ -4372,7 +4372,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id143", + "id": "id149", "index": "Zz", "isDeleted": false, "link": null, @@ -4400,7 +4400,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id143", + "containerId": "id149", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -4408,7 +4408,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id144", + "id": "id150", "index": "a0", "isDeleted": false, "lineHeight": "1.25000", @@ -4455,13 +4455,13 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id144" => Delta { + "id150" => Delta { "deleted": { "angle": 0, "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id143", + "containerId": "id149", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -4497,11 +4497,11 @@ History { }, }, "updated": Map { - "id143" => Delta { + "id149" => Delta { "deleted": { "boundElements": [ { - "id": "id144", + "id": "id150", "type": "text", }, ], @@ -4639,7 +4639,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id158", + "id": "id164", "type": "text", }, ], @@ -4648,7 +4648,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id157", + "id": "id163", "index": "Zz", "isDeleted": false, "link": null, @@ -4676,7 +4676,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id157", + "containerId": "id163", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -4684,7 +4684,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id158", + "id": "id164", "index": "a0", "isDeleted": false, "lineHeight": "1.25000", @@ -4731,7 +4731,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id158" => Delta { + "id164" => Delta { "deleted": { "angle": 0, "x": 15, @@ -4873,7 +4873,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id156", + "id": "id162", "type": "text", }, ], @@ -4882,7 +4882,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id155", + "id": "id161", "index": "a0", "isDeleted": false, "link": null, @@ -4910,7 +4910,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id155", + "containerId": "id161", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -4918,7 +4918,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 25, - "id": "id156", + "id": "id162", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -4966,7 +4966,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id155" => Delta { + "id161" => Delta { "deleted": { "angle": 90, "x": 200, @@ -5111,7 +5111,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id151", + "id": "id157", "index": "a0", "isDeleted": false, "link": null, @@ -5139,7 +5139,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id151", + "containerId": "id157", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -5147,7 +5147,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id152", + "id": "id158", "index": "a1", "isDeleted": true, "lineHeight": "1.25000", @@ -5194,7 +5194,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id151" => Delta { + "id157" => Delta { "deleted": { "boundElements": [], "isDeleted": false, @@ -5202,7 +5202,7 @@ History { "inserted": { "boundElements": [ { - "id": "id152", + "id": "id158", "type": "text", }, ], @@ -5339,7 +5339,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "backgroundColor": "transparent", "boundElements": [ { - "id": "id154", + "id": "id160", "type": "text", }, ], @@ -5348,7 +5348,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id153", + "id": "id159", "index": "Zz", "isDeleted": true, "link": null, @@ -5384,7 +5384,7 @@ exports[`history > multiplayer undo/redo > conflicts in bound text elements and "frameId": null, "groupIds": [], "height": 100, - "id": "id154", + "id": "id160", "index": "a0", "isDeleted": false, "lineHeight": "1.25000", @@ -5431,13 +5431,13 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id154" => Delta { + "id160" => Delta { "deleted": { "containerId": null, "isDeleted": false, }, "inserted": { - "containerId": "id153", + "containerId": "id159", "isDeleted": true, }, }, @@ -5575,7 +5575,7 @@ exports[`history > multiplayer undo/redo > conflicts in frames and their childre "frameId": null, "groupIds": [], "height": 100, - "id": "id182", + "id": "id188", "index": "Zz", "isDeleted": false, "link": null, @@ -5607,7 +5607,7 @@ exports[`history > multiplayer undo/redo > conflicts in frames and their childre "frameId": null, "groupIds": [], "height": 500, - "id": "id181", + "id": "id187", "index": "a0", "isDeleted": true, "link": null, @@ -5650,7 +5650,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id182" => Delta { + "id188" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -5696,9 +5696,9 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id182" => Delta { + "id188" => Delta { "deleted": { - "frameId": "id181", + "frameId": "id187", }, "inserted": { "frameId": null, @@ -5793,7 +5793,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id110": true, + "id116": true, }, "resizingElement": null, "scrollX": 0, @@ -5838,7 +5838,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "A", ], "height": 100, - "id": "id109", + "id": "id115", "index": "a0", "isDeleted": false, "link": null, @@ -5872,7 +5872,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "A", ], "height": 100, - "id": "id110", + "id": "id116", "index": "a1", "isDeleted": true, "link": null, @@ -5909,8 +5909,8 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id109": true, - "id110": true, + "id115": true, + "id116": true, }, "selectedGroupIds": { "A": true, @@ -5926,7 +5926,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id109" => Delta { + "id115" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -5959,7 +5959,7 @@ History { "isDeleted": true, }, }, - "id110" => Delta { + "id116" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6006,7 +6006,7 @@ History { "inserted": { "editingGroupId": null, "selectedElementIds": { - "id109": true, + "id115": true, }, "selectedGroupIds": { "A": true, @@ -6030,7 +6030,7 @@ History { "inserted": { "editingGroupId": "A", "selectedElementIds": { - "id110": true, + "id116": true, }, }, }, @@ -6127,7 +6127,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id97": true, + "id103": true, }, "resizingElement": null, "scrollX": 0, @@ -6170,7 +6170,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 10, - "id": "id95", + "id": "id101", "index": "a0", "isDeleted": false, "link": null, @@ -6202,7 +6202,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 10, - "id": "id96", + "id": "id102", "index": "a1", "isDeleted": true, "link": null, @@ -6234,7 +6234,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 10, - "id": "id97", + "id": "id103", "index": "a2", "isDeleted": true, "link": null, @@ -6271,7 +6271,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id95": true, + "id101": true, }, }, "inserted": { @@ -6282,7 +6282,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id95" => Delta { + "id101" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6322,12 +6322,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id96": true, + "id102": true, }, }, "inserted": { "selectedElementIds": { - "id95": true, + "id101": true, }, }, }, @@ -6336,7 +6336,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id96" => Delta { + "id102" => Delta { "deleted": { "angle": 0, "backgroundColor": "#ffc9c9", @@ -6381,7 +6381,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id96" => Delta { + "id102" => Delta { "deleted": { "backgroundColor": "#ffc9c9", }, @@ -6397,12 +6397,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id97": true, + "id103": true, }, }, "inserted": { "selectedElementIds": { - "id96": true, + "id102": true, }, }, }, @@ -6411,7 +6411,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id97" => Delta { + "id103" => Delta { "deleted": { "angle": 0, "backgroundColor": "#ffc9c9", @@ -6456,7 +6456,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id97" => Delta { + "id103" => Delta { "deleted": { "x": 50, "y": 50, @@ -6555,15 +6555,15 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id100": true, + "id106": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id100": true, - "id101": true, + "id106": true, + "id107": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -6601,7 +6601,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id99", + "id": "id105", "index": "a0", "isDeleted": false, "link": null, @@ -6633,7 +6633,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id100", + "id": "id106", "index": "a1", "isDeleted": false, "link": null, @@ -6665,7 +6665,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id101", + "id": "id107", "index": "a2", "isDeleted": false, "link": null, @@ -6702,7 +6702,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id99": true, + "id105": true, }, }, "inserted": { @@ -6713,7 +6713,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id99" => Delta { + "id105" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6744,7 +6744,7 @@ History { "isDeleted": true, }, }, - "id100" => Delta { + "id106" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6775,7 +6775,7 @@ History { "isDeleted": true, }, }, - "id101" => Delta { + "id107" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -6815,12 +6815,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id100": true, + "id106": true, }, }, "inserted": { "selectedElementIds": { - "id99": true, + "id105": true, }, }, }, @@ -6836,7 +6836,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id101": true, + "id107": true, }, }, "inserted": { @@ -6944,10 +6944,10 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id105": true, - "id106": true, - "id107": true, - "id108": true, + "id111": true, + "id112": true, + "id113": true, + "id114": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": { @@ -6990,7 +6990,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "A", ], "height": 100, - "id": "id105", + "id": "id111", "index": "a0", "isDeleted": false, "link": null, @@ -7024,7 +7024,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "A", ], "height": 100, - "id": "id106", + "id": "id112", "index": "a1", "isDeleted": false, "link": null, @@ -7058,7 +7058,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "B", ], "height": 100, - "id": "id107", + "id": "id113", "index": "a2", "isDeleted": false, "link": null, @@ -7092,7 +7092,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "B", ], "height": 100, - "id": "id108", + "id": "id114", "index": "a3", "isDeleted": false, "link": null, @@ -7129,8 +7129,8 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id105": true, - "id106": true, + "id111": true, + "id112": true, }, "selectedGroupIds": { "A": true, @@ -7153,8 +7153,8 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id107": true, - "id108": true, + "id113": true, + "id114": true, }, "selectedGroupIds": { "B": true, @@ -7263,7 +7263,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id113": true, + "id119": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -7304,7 +7304,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 10, - "id": "id113", + "id": "id119", "index": "a0", "isDeleted": true, "lastCommittedPoint": [ @@ -7357,7 +7357,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id113": true, + "id119": true, }, }, "inserted": { @@ -7368,7 +7368,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id113" => Delta { + "id119" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -7426,7 +7426,7 @@ History { "appStateChange": AppStateChange { "delta": Delta { "deleted": { - "selectedLinearElementId": "id113", + "selectedLinearElementId": "id119", }, "inserted": { "selectedLinearElementId": null, @@ -7443,7 +7443,7 @@ History { "appStateChange": AppStateChange { "delta": Delta { "deleted": { - "editingLinearElementId": "id113", + "editingLinearElementId": "id119", }, "inserted": { "editingLinearElementId": null, @@ -7463,7 +7463,7 @@ History { "editingLinearElementId": null, }, "inserted": { - "editingLinearElementId": "id113", + "editingLinearElementId": "id119", }, }, }, @@ -7600,7 +7600,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 10, - "id": "id94", + "id": "id100", "index": "a0", "isDeleted": true, "link": null, @@ -7637,7 +7637,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id94": true, + "id100": true, }, }, "inserted": { @@ -7649,7 +7649,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id94" => Delta { + "id100" => Delta { "deleted": { "angle": 0, "backgroundColor": "#ffec99", @@ -7694,7 +7694,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id94" => Delta { + "id100" => Delta { "deleted": { "backgroundColor": "#ffec99", }, @@ -7832,7 +7832,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id119", + "id": "id125", "index": "a1", "isDeleted": true, "link": null, @@ -7864,7 +7864,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id120", + "id": "id126", "index": "a3V", "isDeleted": true, "link": null, @@ -7896,7 +7896,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id118", + "id": "id124", "index": "a4", "isDeleted": true, "link": null, @@ -7938,7 +7938,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id119" => Delta { + "id125" => Delta { "deleted": { "index": "a1", }, @@ -7957,14 +7957,14 @@ History { }, "inserted": { "selectedElementIds": { - "id119": true, + "id125": true, }, }, }, }, "elementsChange": ElementsChange { "added": Map { - "id118" => Delta { + "id124" => Delta { "deleted": { "isDeleted": true, }, @@ -7995,7 +7995,7 @@ History { "y": 10, }, }, - "id119" => Delta { + "id125" => Delta { "deleted": { "isDeleted": true, }, @@ -8026,7 +8026,7 @@ History { "y": 20, }, }, - "id120" => Delta { + "id126" => Delta { "deleted": { "isDeleted": true, }, @@ -8190,7 +8190,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id114", + "id": "id120", "index": "Zx", "isDeleted": true, "link": null, @@ -8222,7 +8222,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id116", + "id": "id122", "index": "Zy", "isDeleted": true, "link": null, @@ -8254,7 +8254,7 @@ exports[`history > multiplayer undo/redo > should iterate through the history wh "frameId": null, "groupIds": [], "height": 100, - "id": "id115", + "id": "id121", "index": "a1", "isDeleted": true, "link": null, @@ -8296,7 +8296,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id115" => Delta { + "id121" => Delta { "deleted": { "index": "a1", }, @@ -8315,14 +8315,14 @@ History { }, "inserted": { "selectedElementIds": { - "id115": true, + "id121": true, }, }, }, }, "elementsChange": ElementsChange { "added": Map { - "id114" => Delta { + "id120" => Delta { "deleted": { "isDeleted": true, }, @@ -8353,7 +8353,7 @@ History { "y": 10, }, }, - "id115" => Delta { + "id121" => Delta { "deleted": { "isDeleted": true, }, @@ -8384,7 +8384,7 @@ History { "y": 20, }, }, - "id116" => Delta { + "id122" => Delta { "deleted": { "isDeleted": true, }, @@ -8507,16 +8507,16 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id127": true, - "id128": true, + "id133": true, + "id134": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id127": true, - "id128": true, + "id133": true, + "id134": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -8554,7 +8554,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 10, - "id": "id127", + "id": "id133", "index": "a0", "isDeleted": false, "link": null, @@ -8586,7 +8586,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 10, - "id": "id128", + "id": "id134", "index": "a1", "isDeleted": false, "link": null, @@ -8618,7 +8618,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 100, - "id": "id132", + "id": "id138", "index": "a2", "isDeleted": false, "link": null, @@ -8655,7 +8655,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id127": true, + "id133": true, }, }, "inserted": { @@ -8666,7 +8666,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id127" => Delta { + "id133" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -8706,12 +8706,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id128": true, + "id134": true, }, }, "inserted": { "selectedElementIds": { - "id127": true, + "id133": true, }, }, }, @@ -8719,7 +8719,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id128" => Delta { + "id134" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -8759,12 +8759,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id127": true, + "id133": true, }, }, "inserted": { "selectedElementIds": { - "id128": true, + "id134": true, }, }, }, @@ -8780,7 +8780,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id128": true, + "id134": true, }, }, "inserted": { @@ -8805,7 +8805,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id127" => Delta { + "id133" => Delta { "deleted": { "x": 90, "y": 90, @@ -8815,7 +8815,7 @@ History { "y": 10, }, }, - "id128" => Delta { + "id134" => Delta { "deleted": { "x": 110, "y": 110, @@ -8955,7 +8955,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 50, - "id": "id122", + "id": "id128", "index": "a0", "isDeleted": false, "lastCommittedPoint": [ @@ -9014,7 +9014,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 100, - "id": "id123", + "id": "id129", "index": "a1", "isDeleted": false, "link": null, @@ -9056,7 +9056,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id122" => Delta { + "id128" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -9209,7 +9209,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id124": true, + "id130": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -9247,7 +9247,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 90, - "id": "id124", + "id": "id130", "index": "a0", "isDeleted": false, "link": null, @@ -9279,7 +9279,7 @@ exports[`history > multiplayer undo/redo > should not let remote changes to inte "frameId": null, "groupIds": [], "height": 100, - "id": "id126", + "id": "id132", "index": "a1", "isDeleted": false, "link": null, @@ -9316,7 +9316,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id124": true, + "id130": true, }, }, "inserted": { @@ -9327,7 +9327,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id124" => Delta { + "id130" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -9373,7 +9373,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id124" => Delta { + "id130" => Delta { "deleted": { "height": 90, "width": 90, @@ -9477,7 +9477,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id81": true, + "id87": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -9515,7 +9515,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "frameId": null, "groupIds": [], "height": 10, - "id": "id81", + "id": "id87", "index": "a0", "isDeleted": false, "link": null, @@ -9547,7 +9547,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "frameId": null, "groupIds": [], "height": 100, - "id": "id82", + "id": "id88", "index": "a1", "isDeleted": false, "link": null, @@ -9589,7 +9589,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id81" => Delta { + "id87" => Delta { "deleted": { "backgroundColor": "transparent", }, @@ -9607,7 +9607,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id81": true, + "id87": true, }, }, "inserted": { @@ -9618,7 +9618,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id81" => Delta { + "id87" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -9744,7 +9744,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id83": true, + "id89": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -9782,7 +9782,7 @@ exports[`history > multiplayer undo/redo > should not override remote changes on "frameId": null, "groupIds": [], "height": 10, - "id": "id83", + "id": "id89", "index": "a0", "isDeleted": false, "link": null, @@ -9819,7 +9819,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id83": true, + "id89": true, }, }, "inserted": { @@ -9830,7 +9830,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id83" => Delta { + "id89" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -9876,7 +9876,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id83" => Delta { + "id89" => Delta { "deleted": { "backgroundColor": "#ffc9c9", }, @@ -10020,7 +10020,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups "B", ], "height": 100, - "id": "id88", + "id": "id94", "index": "a0", "isDeleted": false, "link": null, @@ -10055,7 +10055,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups "B", ], "height": 100, - "id": "id89", + "id": "id95", "index": "a1", "isDeleted": false, "link": null, @@ -10089,7 +10089,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups "B", ], "height": 100, - "id": "id90", + "id": "id96", "index": "a2", "isDeleted": false, "link": null, @@ -10123,7 +10123,7 @@ exports[`history > multiplayer undo/redo > should override remotely added groups "B", ], "height": 100, - "id": "id91", + "id": "id97", "index": "a3", "isDeleted": false, "link": null, @@ -10166,7 +10166,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id88" => Delta { + "id94" => Delta { "deleted": { "groupIds": [ "A", @@ -10177,7 +10177,7 @@ History { "groupIds": [], }, }, - "id89" => Delta { + "id95" => Delta { "deleted": { "groupIds": [ "A", @@ -10282,7 +10282,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id92": true, + "id98": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -10323,7 +10323,7 @@ exports[`history > multiplayer undo/redo > should override remotely added points "frameId": null, "groupIds": [], "height": 30, - "id": "id92", + "id": "id98", "index": "a0", "isDeleted": false, "lastCommittedPoint": [ @@ -10388,7 +10388,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id92": true, + "id98": true, }, }, "inserted": { @@ -10399,7 +10399,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id92" => Delta { + "id98" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -10464,7 +10464,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id92" => Delta { + "id98" => Delta { "deleted": { "height": 30, "lastCommittedPoint": [ @@ -10521,7 +10521,7 @@ History { "appStateChange": AppStateChange { "delta": Delta { "deleted": { - "selectedLinearElementId": "id92", + "selectedLinearElementId": "id98", }, "inserted": { "selectedLinearElementId": null, @@ -10661,7 +10661,7 @@ exports[`history > multiplayer undo/redo > should redistribute deltas when eleme "frameId": null, "groupIds": [], "height": 10, - "id": "id93", + "id": "id99", "index": "a0", "isDeleted": false, "link": null, @@ -10698,7 +10698,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id93": true, + "id99": true, }, }, "inserted": { @@ -10709,7 +10709,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id93" => Delta { + "id99" => Delta { "deleted": { "angle": 0, "backgroundColor": "#ffec99", @@ -10752,7 +10752,7 @@ History { }, "inserted": { "selectedElementIds": { - "id93": true, + "id99": true, }, }, }, @@ -10761,7 +10761,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id93" => Delta { + "id99" => Delta { "deleted": { "isDeleted": false, }, @@ -11315,7 +11315,7 @@ exports[`history > multiplayer undo/redo > should update history entries after r "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id84": true, + "id90": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -11353,7 +11353,7 @@ exports[`history > multiplayer undo/redo > should update history entries after r "frameId": null, "groupIds": [], "height": 10, - "id": "id84", + "id": "id90", "index": "a0", "isDeleted": false, "link": null, @@ -11395,7 +11395,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id84" => Delta { + "id90" => Delta { "deleted": { "backgroundColor": "#d0bfff", }, @@ -11417,7 +11417,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id84" => Delta { + "id90" => Delta { "deleted": { "backgroundColor": "transparent", }, @@ -11435,7 +11435,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id84": true, + "id90": true, }, }, "inserted": { @@ -11446,7 +11446,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id84" => Delta { + "id90" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -11640,7 +11640,7 @@ exports[`history > singleplayer undo/redo > remounting undo/redo buttons should "frameId": null, "groupIds": [], "height": 10, - "id": "id80", + "id": "id86", "index": "a1", "isDeleted": true, "link": null, @@ -11679,14 +11679,14 @@ History { }, "inserted": { "selectedElementIds": { - "id80": true, + "id86": true, }, }, }, }, "elementsChange": ElementsChange { "added": Map { - "id80" => Delta { + "id86" => Delta { "deleted": { "isDeleted": true, }, @@ -12712,7 +12712,7 @@ exports[`history > singleplayer undo/redo > should disable undo/redo buttons whe "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id78": true, + "id84": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -12782,7 +12782,7 @@ exports[`history > singleplayer undo/redo > should disable undo/redo buttons whe "frameId": null, "groupIds": [], "height": 10, - "id": "id78", + "id": "id84", "index": "a1", "isDeleted": false, "link": null, @@ -12819,7 +12819,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id78": true, + "id84": true, }, }, "inserted": { @@ -12830,7 +12830,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id78" => Delta { + "id84" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -14881,1328 +14881,6 @@ exports[`history > singleplayer undo/redo > should support appstate name or view exports[`history > singleplayer undo/redo > should support appstate name or viewBackgroundColor change > [end of test] number of renders 1`] = `8`; exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] appState 1`] = ` -{ - "activeEmbeddable": null, - "activeTool": { - "customType": null, - "lastActiveTool": null, - "locked": false, - "type": "selection", - }, - "collaborators": Map {}, - "contextMenu": null, - "croppingElementId": null, - "currentChartType": "bar", - "currentHoveredFontFamily": null, - "currentItemArrowType": "round", - "currentItemBackgroundColor": "transparent", - "currentItemEndArrowhead": "arrow", - "currentItemFillStyle": "solid", - "currentItemFontFamily": 5, - "currentItemFontSize": 20, - "currentItemOpacity": 100, - "currentItemRoughness": 1, - "currentItemRoundness": "round", - "currentItemStartArrowhead": null, - "currentItemStrokeColor": "#1e1e1e", - "currentItemStrokeStyle": "solid", - "currentItemStrokeWidth": 2, - "currentItemTextAlign": "left", - "cursorButton": "up", - "defaultSidebarDockedPreference": false, - "editingFrame": null, - "editingGroupId": null, - "editingLinearElement": null, - "editingTextElement": null, - "elementsToHighlight": null, - "errorMessage": null, - "exportBackground": true, - "exportEmbedScene": false, - "exportScale": 1, - "exportWithDarkMode": false, - "fileHandle": null, - "followedBy": Set {}, - "frameRendering": { - "clip": true, - "enabled": true, - "name": true, - "outline": true, - }, - "frameToHighlight": null, - "gridModeEnabled": false, - "gridSize": 20, - "gridStep": 5, - "height": 0, - "hoveredElementIds": {}, - "isBindingEnabled": true, - "isCropping": false, - "isLoading": false, - "isResizing": false, - "isRotating": false, - "lastPointerDownWith": "mouse", - "multiElement": null, - "newElement": null, - "objectsSnapModeEnabled": false, - "offsetLeft": 0, - "offsetTop": 0, - "openDialog": null, - "openMenu": null, - "openPopup": null, - "openSidebar": null, - "originSnapOffset": null, - "pasteDialog": { - "data": null, - "shown": false, - }, - "penDetected": false, - "penMode": false, - "pendingImageElementId": null, - "previousSelectedElementIds": { - "id50": true, - }, - "resizingElement": null, - "scrollX": 0, - "scrollY": 0, - "searchMatches": [], - "selectedElementIds": { - "id55": true, - }, - "selectedElementsAreBeingDragged": false, - "selectedGroupIds": {}, - "selectionElement": null, - "shouldCacheIgnoreZoom": false, - "showHyperlinkPopup": false, - "showWelcomeScreen": true, - "snapLines": [], - "startBoundElement": null, - "stats": { - "open": false, - "panels": 3, - }, - "suggestedBindings": [], - "theme": "light", - "toast": null, - "userToFollow": null, - "viewBackgroundColor": "#ffffff", - "viewModeEnabled": false, - "width": 0, - "zenModeEnabled": false, - "zoom": { - "value": 1, - }, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 0 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id51", - "type": "text", - }, - { - "id": "id55", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "id": "id50", - "index": "a0", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 8, - "width": 100, - "x": -100, - "y": -50, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 1 1`] = ` -{ - "angle": 0, - "autoResize": true, - "backgroundColor": "transparent", - "boundElements": null, - "containerId": "id50", - "customData": undefined, - "fillStyle": "solid", - "fontFamily": 5, - "fontSize": 20, - "frameId": null, - "groupIds": [], - "height": 25, - "id": "id51", - "index": "a1", - "isDeleted": false, - "lineHeight": "1.25000", - "link": null, - "locked": false, - "opacity": 100, - "originalText": "ola", - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "text": "ola", - "textAlign": "center", - "type": "text", - "updated": 1, - "version": 6, - "verticalAlign": "middle", - "width": 30, - "x": -65, - "y": "-12.50000", -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 2 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id55", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "id": "id52", - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 7, - "width": 100, - "x": 100, - "y": -50, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 3 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id52", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 0, - "id": "id55", - "index": "a3", - "isDeleted": false, - "lastCommittedPoint": null, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - "98.00000", - 0, - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": { - "elementId": "id50", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "updated": 1, - "version": 10, - "width": "98.00000", - "x": 1, - "y": 0, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] history 1`] = ` -History { - "onHistoryChangedEmitter": Emitter { - "subscribers": [ - [Function], - [Function], - ], - }, - "redoStack": [ - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id55": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id55" => Delta { - "deleted": { - "isDeleted": false, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - }, - "inserted": { - "isDeleted": true, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - }, - }, - }, - "updated": Map { - "id50" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id55", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - "id52" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id55", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - }, - }, - }, - ], - "undoStack": [ - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id50" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a0", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "width": 100, - "x": -100, - "y": -50, - }, - "inserted": { - "isDeleted": true, - }, - }, - "id51" => Delta { - "deleted": { - "angle": 0, - "autoResize": true, - "backgroundColor": "transparent", - "boundElements": null, - "containerId": null, - "customData": undefined, - "fillStyle": "solid", - "fontFamily": 5, - "fontSize": 20, - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a1", - "isDeleted": false, - "lineHeight": "1.25000", - "link": null, - "locked": false, - "opacity": 100, - "originalText": "ola", - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "text": "ola", - "textAlign": "left", - "type": "text", - "verticalAlign": "top", - "width": 100, - "x": -200, - "y": -200, - }, - "inserted": { - "isDeleted": true, - }, - }, - "id52" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "width": 100, - "x": 100, - "y": -50, - }, - "inserted": { - "isDeleted": true, - }, - }, - }, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id50": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id51": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": {}, - }, - "inserted": { - "selectedElementIds": { - "id51": true, - }, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map { - "id50" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id51", - "type": "text", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - "id51" => Delta { - "deleted": { - "containerId": "id50", - "height": 25, - "textAlign": "center", - "verticalAlign": "middle", - "width": 30, - "x": -65, - "y": "-12.50000", - }, - "inserted": { - "containerId": null, - "height": 100, - "textAlign": "left", - "verticalAlign": "top", - "width": 100, - "x": -200, - "y": -200, - }, - }, - }, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id55": true, - }, - "selectedLinearElementId": "id55", - }, - "inserted": { - "selectedElementIds": { - "id50": true, - }, - "selectedLinearElementId": null, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id55" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id52", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 0, - "index": "a3", - "isDeleted": false, - "lastCommittedPoint": null, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": { - "elementId": "id50", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "width": 100, - "x": 0, - "y": 0, - }, - "inserted": { - "isDeleted": true, - }, - }, - }, - "updated": Map { - "id50" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id55", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - "id52" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id55", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - }, - }, - }, - ], -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of elements 1`] = `4`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of renders 1`] = `12`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] appState 1`] = ` -{ - "activeEmbeddable": null, - "activeTool": { - "customType": null, - "lastActiveTool": null, - "locked": false, - "type": "selection", - }, - "collaborators": Map {}, - "contextMenu": null, - "croppingElementId": null, - "currentChartType": "bar", - "currentHoveredFontFamily": null, - "currentItemArrowType": "round", - "currentItemBackgroundColor": "transparent", - "currentItemEndArrowhead": "arrow", - "currentItemFillStyle": "solid", - "currentItemFontFamily": 5, - "currentItemFontSize": 20, - "currentItemOpacity": 100, - "currentItemRoughness": 1, - "currentItemRoundness": "round", - "currentItemStartArrowhead": null, - "currentItemStrokeColor": "#1e1e1e", - "currentItemStrokeStyle": "solid", - "currentItemStrokeWidth": 2, - "currentItemTextAlign": "left", - "cursorButton": "up", - "defaultSidebarDockedPreference": false, - "editingFrame": null, - "editingGroupId": null, - "editingLinearElement": null, - "editingTextElement": null, - "elementsToHighlight": null, - "errorMessage": null, - "exportBackground": true, - "exportEmbedScene": false, - "exportScale": 1, - "exportWithDarkMode": false, - "fileHandle": null, - "followedBy": Set {}, - "frameRendering": { - "clip": true, - "enabled": true, - "name": true, - "outline": true, - }, - "frameToHighlight": null, - "gridModeEnabled": false, - "gridSize": 20, - "gridStep": 5, - "height": 0, - "hoveredElementIds": {}, - "isBindingEnabled": true, - "isCropping": false, - "isLoading": false, - "isResizing": false, - "isRotating": false, - "lastPointerDownWith": "mouse", - "multiElement": null, - "newElement": null, - "objectsSnapModeEnabled": false, - "offsetLeft": 0, - "offsetTop": 0, - "openDialog": null, - "openMenu": null, - "openPopup": null, - "openSidebar": null, - "originSnapOffset": null, - "pasteDialog": { - "data": null, - "shown": false, - }, - "penDetected": false, - "penMode": false, - "pendingImageElementId": null, - "previousSelectedElementIds": { - "id44": true, - }, - "resizingElement": null, - "scrollX": 0, - "scrollY": 0, - "searchMatches": [], - "selectedElementIds": { - "id49": true, - }, - "selectedElementsAreBeingDragged": false, - "selectedGroupIds": {}, - "selectionElement": null, - "shouldCacheIgnoreZoom": false, - "showHyperlinkPopup": false, - "showWelcomeScreen": true, - "snapLines": [], - "startBoundElement": null, - "stats": { - "open": false, - "panels": 3, - }, - "suggestedBindings": [], - "theme": "light", - "toast": null, - "userToFollow": null, - "viewBackgroundColor": "#ffffff", - "viewModeEnabled": false, - "width": 0, - "zenModeEnabled": false, - "zoom": { - "value": 1, - }, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 0 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id45", - "type": "text", - }, - { - "id": "id49", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "id": "id44", - "index": "a0", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 8, - "width": 100, - "x": -100, - "y": -50, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 1 1`] = ` -{ - "angle": 0, - "autoResize": true, - "backgroundColor": "transparent", - "boundElements": null, - "containerId": "id44", - "customData": undefined, - "fillStyle": "solid", - "fontFamily": 5, - "fontSize": 20, - "frameId": null, - "groupIds": [], - "height": 25, - "id": "id45", - "index": "a1", - "isDeleted": false, - "lineHeight": "1.25000", - "link": null, - "locked": false, - "opacity": 100, - "originalText": "ola", - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "text": "ola", - "textAlign": "center", - "type": "text", - "updated": 1, - "version": 8, - "verticalAlign": "middle", - "width": 30, - "x": -65, - "y": "-12.50000", -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 2 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": [ - { - "id": "id49", - "type": "arrow", - }, - ], - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "id": "id46", - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "updated": 1, - "version": 7, - "width": 100, - "x": 100, - "y": -50, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 3 1`] = ` -{ - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id46", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 0, - "id": "id49", - "index": "a3", - "isDeleted": false, - "lastCommittedPoint": null, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - "98.00000", - 0, - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": { - "elementId": "id44", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "updated": 1, - "version": 10, - "width": "98.00000", - "x": 1, - "y": 0, -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] history 1`] = ` -History { - "onHistoryChangedEmitter": Emitter { - "subscribers": [ - [Function], - [Function], - ], - }, - "redoStack": [], - "undoStack": [ - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": {}, - "inserted": {}, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id44" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a0", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "width": 100, - "x": -100, - "y": -50, - }, - "inserted": { - "isDeleted": true, - }, - }, - "id45" => Delta { - "deleted": { - "angle": 0, - "autoResize": true, - "backgroundColor": "transparent", - "boundElements": null, - "containerId": null, - "customData": undefined, - "fillStyle": "solid", - "fontFamily": 5, - "fontSize": 20, - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a1", - "isDeleted": false, - "lineHeight": "1.25000", - "link": null, - "locked": false, - "opacity": 100, - "originalText": "ola", - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "text": "ola", - "textAlign": "left", - "type": "text", - "verticalAlign": "top", - "width": 100, - "x": -200, - "y": -200, - }, - "inserted": { - "isDeleted": true, - }, - }, - "id46" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 100, - "index": "a2", - "isDeleted": false, - "link": null, - "locked": false, - "opacity": 100, - "roughness": 1, - "roundness": { - "type": 3, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "rectangle", - "width": 100, - "x": 100, - "y": -50, - }, - "inserted": { - "isDeleted": true, - }, - }, - }, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id44": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id45": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map {}, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": {}, - }, - "inserted": { - "selectedElementIds": { - "id45": true, - }, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map {}, - "updated": Map { - "id44" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id45", - "type": "text", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - "id45" => Delta { - "deleted": { - "containerId": "id44", - "height": 25, - "textAlign": "center", - "verticalAlign": "middle", - "width": 30, - "x": -65, - "y": "-12.50000", - }, - "inserted": { - "containerId": null, - "height": 100, - "textAlign": "left", - "verticalAlign": "top", - "width": 100, - "x": -200, - "y": -200, - }, - }, - }, - }, - }, - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id49": true, - }, - "selectedLinearElementId": "id49", - }, - "inserted": { - "selectedElementIds": { - "id44": true, - }, - "selectedLinearElementId": null, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id49" => Delta { - "deleted": { - "angle": 0, - "backgroundColor": "transparent", - "boundElements": null, - "customData": undefined, - "elbowed": false, - "endArrowhead": "arrow", - "endBinding": { - "elementId": "id46", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "fillStyle": "solid", - "frameId": null, - "groupIds": [], - "height": 0, - "index": "a3", - "isDeleted": false, - "lastCommittedPoint": null, - "link": null, - "locked": false, - "opacity": 100, - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "roughness": 1, - "roundness": { - "type": 2, - }, - "startArrowhead": null, - "startBinding": { - "elementId": "id44", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - "strokeColor": "#1e1e1e", - "strokeStyle": "solid", - "strokeWidth": 2, - "type": "arrow", - "width": 100, - "x": 0, - "y": 0, - }, - "inserted": { - "isDeleted": true, - }, - }, - }, - "updated": Map { - "id44" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id49", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - "id46" => Delta { - "deleted": { - "boundElements": [ - { - "id": "id49", - "type": "arrow", - }, - ], - }, - "inserted": { - "boundElements": [], - }, - }, - }, - }, - }, - ], -} -`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of elements 1`] = `4`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of renders 1`] = `12`; - -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] appState 1`] = ` { "activeEmbeddable": null, "activeTool": { @@ -16315,7 +14993,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 0 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 0 1`] = ` { "angle": 0, "backgroundColor": "transparent", @@ -16349,14 +15027,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 12, + "version": 8, "width": 100, "x": -100, "y": -50, } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 1 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 1 1`] = ` { "angle": 0, "autoResize": true, @@ -16389,7 +15067,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 12, + "version": 6, "verticalAlign": "middle", "width": 30, "x": -65, @@ -16397,7 +15075,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 2 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 2 1`] = ` { "angle": 0, "backgroundColor": "transparent", @@ -16427,14 +15105,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 9, + "version": 7, "width": 100, "x": 100, "y": -50, } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 3 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] element 3 1`] = ` { "angle": 0, "backgroundColor": "transparent", @@ -16492,7 +15170,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] history 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] history 1`] = ` History { "onHistoryChangedEmitter": Emitter { "subscribers": [ @@ -16500,7 +15178,83 @@ History { [Function], ], }, - "redoStack": [], + "redoStack": [ + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id61": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id61" => Delta { + "deleted": { + "isDeleted": false, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + }, + "inserted": { + "isDeleted": true, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + }, + }, + }, + "updated": Map { + "id56" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id61", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + "id58" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id61", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + }, + }, + }, + ], "undoStack": [ HistoryEntry { "appStateChange": AppStateChange { @@ -16821,11 +15575,11 @@ History { } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of elements 1`] = `4`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of elements 1`] = `4`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of renders 1`] = `20`; +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on deletion and rebind on undo > [end of test] number of renders 1`] = `12`; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] appState 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] appState 1`] = ` { "activeEmbeddable": null, "activeTool": { @@ -16902,13 +15656,15 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "penDetected": false, "penMode": false, "pendingImageElementId": null, - "previousSelectedElementIds": {}, + "previousSelectedElementIds": { + "id50": true, + }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id62": true, + "id55": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -16936,19 +15692,642 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 0 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 0 1`] = ` { "angle": 0, "backgroundColor": "transparent", "boundElements": [ { - "id": "id67", + "id": "id51", + "type": "text", + }, + { + "id": "id55", "type": "arrow", }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id50", + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 8, + "width": 100, + "x": -100, + "y": -50, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 1 1`] = ` +{ + "angle": 0, + "autoResize": true, + "backgroundColor": "transparent", + "boundElements": null, + "containerId": "id50", + "customData": undefined, + "fillStyle": "solid", + "fontFamily": 5, + "fontSize": 20, + "frameId": null, + "groupIds": [], + "height": 25, + "id": "id51", + "index": "a1", + "isDeleted": false, + "lineHeight": "1.25000", + "link": null, + "locked": false, + "opacity": 100, + "originalText": "ola", + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "text": "ola", + "textAlign": "center", + "type": "text", + "updated": 1, + "version": 8, + "verticalAlign": "middle", + "width": 30, + "x": -65, + "y": "-12.50000", +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 2 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id55", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id52", + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 7, + "width": 100, + "x": 100, + "y": -50, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] element 3 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id52", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 0, + "id": "id55", + "index": "a3", + "isDeleted": false, + "lastCommittedPoint": null, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + "98.00000", + 0, + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id50", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "updated": 1, + "version": 10, + "width": "98.00000", + "x": 1, + "y": 0, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] history 1`] = ` +History { + "onHistoryChangedEmitter": Emitter { + "subscribers": [ + [Function], + [Function], + ], + }, + "redoStack": [], + "undoStack": [ + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id50" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "width": 100, + "x": -100, + "y": -50, + }, + "inserted": { + "isDeleted": true, + }, + }, + "id51" => Delta { + "deleted": { + "angle": 0, + "autoResize": true, + "backgroundColor": "transparent", + "boundElements": null, + "containerId": null, + "customData": undefined, + "fillStyle": "solid", + "fontFamily": 5, + "fontSize": 20, + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a1", + "isDeleted": false, + "lineHeight": "1.25000", + "link": null, + "locked": false, + "opacity": 100, + "originalText": "ola", + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "text": "ola", + "textAlign": "left", + "type": "text", + "verticalAlign": "top", + "width": 100, + "x": -200, + "y": -200, + }, + "inserted": { + "isDeleted": true, + }, + }, + "id52" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "width": 100, + "x": 100, + "y": -50, + }, + "inserted": { + "isDeleted": true, + }, + }, + }, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id50": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id51": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": {}, + }, + "inserted": { + "selectedElementIds": { + "id51": true, + }, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map { + "id50" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id51", + "type": "text", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + "id51" => Delta { + "deleted": { + "containerId": "id50", + "height": 25, + "textAlign": "center", + "verticalAlign": "middle", + "width": 30, + "x": -65, + "y": "-12.50000", + }, + "inserted": { + "containerId": null, + "height": 100, + "textAlign": "left", + "verticalAlign": "top", + "width": 100, + "x": -200, + "y": -200, + }, + }, + }, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id55": true, + }, + "selectedLinearElementId": "id55", + }, + "inserted": { + "selectedElementIds": { + "id50": true, + }, + "selectedLinearElementId": null, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id55" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id52", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 0, + "index": "a3", + "isDeleted": false, + "lastCommittedPoint": null, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id50", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "width": 100, + "x": 0, + "y": 0, + }, + "inserted": { + "isDeleted": true, + }, + }, + }, + "updated": Map { + "id50" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id55", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + "id52" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id55", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + }, + }, + }, + ], +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of elements 1`] = `4`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind arrow from non deleted bindable elements on undo and rebind on redo > [end of test] number of renders 1`] = `12`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] appState 1`] = ` +{ + "activeEmbeddable": null, + "activeTool": { + "customType": null, + "lastActiveTool": null, + "locked": false, + "type": "selection", + }, + "collaborators": Map {}, + "contextMenu": null, + "croppingElementId": null, + "currentChartType": "bar", + "currentHoveredFontFamily": null, + "currentItemArrowType": "round", + "currentItemBackgroundColor": "transparent", + "currentItemEndArrowhead": "arrow", + "currentItemFillStyle": "solid", + "currentItemFontFamily": 5, + "currentItemFontSize": 20, + "currentItemOpacity": 100, + "currentItemRoughness": 1, + "currentItemRoundness": "round", + "currentItemStartArrowhead": null, + "currentItemStrokeColor": "#1e1e1e", + "currentItemStrokeStyle": "solid", + "currentItemStrokeWidth": 2, + "currentItemTextAlign": "left", + "cursorButton": "up", + "defaultSidebarDockedPreference": false, + "editingFrame": null, + "editingGroupId": null, + "editingLinearElement": null, + "editingTextElement": null, + "elementsToHighlight": null, + "errorMessage": null, + "exportBackground": true, + "exportEmbedScene": false, + "exportScale": 1, + "exportWithDarkMode": false, + "fileHandle": null, + "followedBy": Set {}, + "frameRendering": { + "clip": true, + "enabled": true, + "name": true, + "outline": true, + }, + "frameToHighlight": null, + "gridModeEnabled": false, + "gridSize": 20, + "gridStep": 5, + "height": 0, + "hoveredElementIds": {}, + "isBindingEnabled": true, + "isCropping": false, + "isLoading": false, + "isResizing": false, + "isRotating": false, + "lastPointerDownWith": "mouse", + "multiElement": null, + "newElement": null, + "objectsSnapModeEnabled": false, + "offsetLeft": 0, + "offsetTop": 0, + "openDialog": null, + "openMenu": null, + "openPopup": null, + "openSidebar": null, + "originSnapOffset": null, + "pasteDialog": { + "data": null, + "shown": false, + }, + "penDetected": false, + "penMode": false, + "pendingImageElementId": null, + "previousSelectedElementIds": { + "id62": true, + }, + "resizingElement": null, + "scrollX": 0, + "scrollY": 0, + "searchMatches": [], + "selectedElementIds": { + "id67": true, + }, + "selectedElementsAreBeingDragged": false, + "selectedGroupIds": {}, + "selectionElement": null, + "shouldCacheIgnoreZoom": false, + "showHyperlinkPopup": false, + "showWelcomeScreen": true, + "snapLines": [], + "startBoundElement": null, + "stats": { + "open": false, + "panels": 3, + }, + "suggestedBindings": [], + "theme": "light", + "toast": null, + "userToFollow": null, + "viewBackgroundColor": "#ffffff", + "viewModeEnabled": false, + "width": 0, + "zenModeEnabled": false, + "zoom": { + "value": 1, + }, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 0 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ { "id": "id63", "type": "text", }, + { + "id": "id67", + "type": "arrow", + }, ], "customData": undefined, "fillStyle": "solid", @@ -16970,14 +16349,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 8, + "version": 12, "width": 100, "x": -100, "y": -50, } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 1 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 1 1`] = ` { "angle": 0, "autoResize": true, @@ -17010,7 +16389,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "textAlign": "center", "type": "text", "updated": 1, - "version": 8, + "version": 12, "verticalAlign": "middle", "width": 30, "x": -65, @@ -17018,7 +16397,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 2 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 2 1`] = ` { "angle": 0, "backgroundColor": "transparent", @@ -17048,14 +16427,14 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, + "version": 9, "width": 100, "x": 100, "y": -50, } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 3 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] element 3 1`] = ` { "angle": 0, "backgroundColor": "transparent", @@ -17113,7 +16492,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding } `; -exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] history 1`] = ` +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] history 1`] = ` History { "onHistoryChangedEmitter": Emitter { "subscribers": [ @@ -17121,78 +16500,7 @@ History { [Function], ], }, - "redoStack": [ - HistoryEntry { - "appStateChange": AppStateChange { - "delta": Delta { - "deleted": { - "selectedElementIds": { - "id62": true, - }, - }, - "inserted": { - "selectedElementIds": {}, - }, - }, - }, - "elementsChange": ElementsChange { - "added": Map {}, - "removed": Map { - "id62" => Delta { - "deleted": { - "isDeleted": false, - }, - "inserted": { - "isDeleted": true, - }, - }, - "id63" => Delta { - "deleted": { - "isDeleted": false, - }, - "inserted": { - "isDeleted": true, - }, - }, - }, - "updated": Map { - "id67" => Delta { - "deleted": { - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "startBinding": { - "elementId": "id62", - "fixedPoint": null, - "focus": 0, - "gap": 1, - }, - }, - "inserted": { - "points": [ - [ - 0, - 0, - ], - [ - 100, - 0, - ], - ], - "startBinding": null, - }, - }, - }, - }, - }, - ], + "redoStack": [], "undoStack": [ HistoryEntry { "appStateChange": AppStateChange { @@ -17509,20 +16817,712 @@ History { }, }, }, + ], +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of elements 1`] = `4`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind everything from non deleted elements when iterating through the whole undo stack and vice versa rebind everything on redo > [end of test] number of renders 1`] = `20`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] appState 1`] = ` +{ + "activeEmbeddable": null, + "activeTool": { + "customType": null, + "lastActiveTool": null, + "locked": false, + "type": "selection", + }, + "collaborators": Map {}, + "contextMenu": null, + "croppingElementId": null, + "currentChartType": "bar", + "currentHoveredFontFamily": null, + "currentItemArrowType": "round", + "currentItemBackgroundColor": "transparent", + "currentItemEndArrowhead": "arrow", + "currentItemFillStyle": "solid", + "currentItemFontFamily": 5, + "currentItemFontSize": 20, + "currentItemOpacity": 100, + "currentItemRoughness": 1, + "currentItemRoundness": "round", + "currentItemStartArrowhead": null, + "currentItemStrokeColor": "#1e1e1e", + "currentItemStrokeStyle": "solid", + "currentItemStrokeWidth": 2, + "currentItemTextAlign": "left", + "cursorButton": "up", + "defaultSidebarDockedPreference": false, + "editingFrame": null, + "editingGroupId": null, + "editingLinearElement": null, + "editingTextElement": null, + "elementsToHighlight": null, + "errorMessage": null, + "exportBackground": true, + "exportEmbedScene": false, + "exportScale": 1, + "exportWithDarkMode": false, + "fileHandle": null, + "followedBy": Set {}, + "frameRendering": { + "clip": true, + "enabled": true, + "name": true, + "outline": true, + }, + "frameToHighlight": null, + "gridModeEnabled": false, + "gridSize": 20, + "gridStep": 5, + "height": 0, + "hoveredElementIds": {}, + "isBindingEnabled": true, + "isCropping": false, + "isLoading": false, + "isResizing": false, + "isRotating": false, + "lastPointerDownWith": "mouse", + "multiElement": null, + "newElement": null, + "objectsSnapModeEnabled": false, + "offsetLeft": 0, + "offsetTop": 0, + "openDialog": null, + "openMenu": null, + "openPopup": null, + "openSidebar": null, + "originSnapOffset": null, + "pasteDialog": { + "data": null, + "shown": false, + }, + "penDetected": false, + "penMode": false, + "pendingImageElementId": null, + "previousSelectedElementIds": {}, + "resizingElement": null, + "scrollX": 0, + "scrollY": 0, + "searchMatches": [], + "selectedElementIds": { + "id68": true, + }, + "selectedElementsAreBeingDragged": false, + "selectedGroupIds": {}, + "selectionElement": null, + "shouldCacheIgnoreZoom": false, + "showHyperlinkPopup": false, + "showWelcomeScreen": true, + "snapLines": [], + "startBoundElement": null, + "stats": { + "open": false, + "panels": 3, + }, + "suggestedBindings": [], + "theme": "light", + "toast": null, + "userToFollow": null, + "viewBackgroundColor": "#ffffff", + "viewModeEnabled": false, + "width": 0, + "zenModeEnabled": false, + "zoom": { + "value": 1, + }, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 0 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id73", + "type": "arrow", + }, + { + "id": "id69", + "type": "text", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id68", + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 8, + "width": 100, + "x": -100, + "y": -50, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 1 1`] = ` +{ + "angle": 0, + "autoResize": true, + "backgroundColor": "transparent", + "boundElements": null, + "containerId": "id68", + "customData": undefined, + "fillStyle": "solid", + "fontFamily": 5, + "fontSize": 20, + "frameId": null, + "groupIds": [], + "height": 25, + "id": "id69", + "index": "a1", + "isDeleted": false, + "lineHeight": "1.25000", + "link": null, + "locked": false, + "opacity": 100, + "originalText": "ola", + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "text": "ola", + "textAlign": "center", + "type": "text", + "updated": 1, + "version": 8, + "verticalAlign": "middle", + "width": 30, + "x": -65, + "y": "-12.50000", +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 2 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": [ + { + "id": "id73", + "type": "arrow", + }, + ], + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "id": "id70", + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "updated": 1, + "version": 5, + "width": 100, + "x": 100, + "y": -50, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] element 3 1`] = ` +{ + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id70", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 0, + "id": "id73", + "index": "a3", + "isDeleted": false, + "lastCommittedPoint": null, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + "98.00000", + 0, + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id68", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "updated": 1, + "version": 10, + "width": "98.00000", + "x": 1, + "y": 0, +} +`; + +exports[`history > singleplayer undo/redo > should support bidirectional bindings > should unbind rectangle from arrow on deletion and rebind on undo > [end of test] history 1`] = ` +History { + "onHistoryChangedEmitter": Emitter { + "subscribers": [ + [Function], + [Function], + ], + }, + "redoStack": [ HistoryEntry { "appStateChange": AppStateChange { "delta": Delta { "deleted": { "selectedElementIds": { - "id62": true, + "id68": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id68" => Delta { + "deleted": { + "isDeleted": false, + }, + "inserted": { + "isDeleted": true, + }, + }, + "id69" => Delta { + "deleted": { + "isDeleted": false, + }, + "inserted": { + "isDeleted": true, + }, + }, + }, + "updated": Map { + "id73" => Delta { + "deleted": { + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "startBinding": { + "elementId": "id68", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + }, + "inserted": { + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "startBinding": null, + }, + }, + }, + }, + }, + ], + "undoStack": [ + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": {}, + "inserted": {}, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id68" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a0", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "width": 100, + "x": -100, + "y": -50, + }, + "inserted": { + "isDeleted": true, + }, + }, + "id69" => Delta { + "deleted": { + "angle": 0, + "autoResize": true, + "backgroundColor": "transparent", + "boundElements": null, + "containerId": null, + "customData": undefined, + "fillStyle": "solid", + "fontFamily": 5, + "fontSize": 20, + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a1", + "isDeleted": false, + "lineHeight": "1.25000", + "link": null, + "locked": false, + "opacity": 100, + "originalText": "ola", + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "text": "ola", + "textAlign": "left", + "type": "text", + "verticalAlign": "top", + "width": 100, + "x": -200, + "y": -200, + }, + "inserted": { + "isDeleted": true, + }, + }, + "id70" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 100, + "index": "a2", + "isDeleted": false, + "link": null, + "locked": false, + "opacity": 100, + "roughness": 1, + "roundness": { + "type": 3, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "rectangle", + "width": 100, + "x": 100, + "y": -50, + }, + "inserted": { + "isDeleted": true, + }, + }, + }, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id68": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id69": true, + }, + }, + "inserted": { + "selectedElementIds": {}, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map {}, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": {}, + }, + "inserted": { + "selectedElementIds": { + "id69": true, + }, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map {}, + "updated": Map { + "id68" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id69", + "type": "text", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + "id69" => Delta { + "deleted": { + "containerId": "id68", + "height": 25, + "textAlign": "center", + "verticalAlign": "middle", + "width": 30, + "x": -65, + "y": "-12.50000", + }, + "inserted": { + "containerId": null, + "height": 100, + "textAlign": "left", + "verticalAlign": "top", + "width": 100, + "x": -200, + "y": -200, + }, + }, + }, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id73": true, + }, + "selectedLinearElementId": "id73", + }, + "inserted": { + "selectedElementIds": { + "id68": true, + }, + "selectedLinearElementId": null, + }, + }, + }, + "elementsChange": ElementsChange { + "added": Map {}, + "removed": Map { + "id73" => Delta { + "deleted": { + "angle": 0, + "backgroundColor": "transparent", + "boundElements": null, + "customData": undefined, + "elbowed": false, + "endArrowhead": "arrow", + "endBinding": { + "elementId": "id70", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "fillStyle": "solid", + "frameId": null, + "groupIds": [], + "height": 0, + "index": "a3", + "isDeleted": false, + "lastCommittedPoint": null, + "link": null, + "locked": false, + "opacity": 100, + "points": [ + [ + 0, + 0, + ], + [ + 100, + 0, + ], + ], + "roughness": 1, + "roundness": { + "type": 2, + }, + "startArrowhead": null, + "startBinding": { + "elementId": "id68", + "fixedPoint": null, + "focus": 0, + "gap": 1, + }, + "strokeColor": "#1e1e1e", + "strokeStyle": "solid", + "strokeWidth": 2, + "type": "arrow", + "width": 100, + "x": 0, + "y": 0, + }, + "inserted": { + "isDeleted": true, + }, + }, + }, + "updated": Map { + "id68" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id73", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + "id70" => Delta { + "deleted": { + "boundElements": [ + { + "id": "id73", + "type": "arrow", + }, + ], + }, + "inserted": { + "boundElements": [], + }, + }, + }, + }, + }, + HistoryEntry { + "appStateChange": AppStateChange { + "delta": Delta { + "deleted": { + "selectedElementIds": { + "id68": true, }, "selectedLinearElementId": null, }, "inserted": { "selectedElementIds": { - "id67": true, + "id73": true, }, - "selectedLinearElementId": "id67", + "selectedLinearElementId": "id73", }, }, }, @@ -17618,15 +17618,15 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id69": true, + "id75": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id69": true, - "id71": true, + "id75": true, + "id77": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -17660,11 +17660,11 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "backgroundColor": "transparent", "boundElements": [ { - "id": "id74", + "id": "id80", "type": "arrow", }, { - "id": "id70", + "id": "id76", "type": "text", }, ], @@ -17673,7 +17673,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "frameId": null, "groupIds": [], "height": 100, - "id": "id69", + "id": "id75", "index": "a0", "isDeleted": false, "link": null, @@ -17701,7 +17701,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "autoResize": true, "backgroundColor": "transparent", "boundElements": null, - "containerId": "id69", + "containerId": "id75", "customData": undefined, "fillStyle": "solid", "fontFamily": 5, @@ -17709,7 +17709,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "frameId": null, "groupIds": [], "height": 25, - "id": "id70", + "id": "id76", "index": "a1", "isDeleted": false, "lineHeight": "1.25000", @@ -17742,7 +17742,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "backgroundColor": "transparent", "boundElements": [ { - "id": "id74", + "id": "id80", "type": "arrow", }, ], @@ -17751,7 +17751,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "frameId": null, "groupIds": [], "height": 100, - "id": "id71", + "id": "id77", "index": "a2", "isDeleted": false, "link": null, @@ -17782,7 +17782,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id71", + "elementId": "id77", "fixedPoint": null, "focus": 0, "gap": 1, @@ -17791,7 +17791,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "frameId": null, "groupIds": [], "height": 0, - "id": "id74", + "id": "id80", "index": "a3", "isDeleted": false, "lastCommittedPoint": null, @@ -17814,7 +17814,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding }, "startArrowhead": null, "startBinding": { - "elementId": "id69", + "elementId": "id75", "fixedPoint": null, "focus": 0, "gap": 1, @@ -17845,8 +17845,8 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id69": true, - "id71": true, + "id75": true, + "id77": true, }, }, "inserted": { @@ -17857,7 +17857,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id69" => Delta { + "id75" => Delta { "deleted": { "isDeleted": false, }, @@ -17865,7 +17865,7 @@ History { "isDeleted": true, }, }, - "id70" => Delta { + "id76" => Delta { "deleted": { "isDeleted": false, }, @@ -17873,7 +17873,7 @@ History { "isDeleted": true, }, }, - "id71" => Delta { + "id77" => Delta { "deleted": { "isDeleted": false, }, @@ -17883,10 +17883,10 @@ History { }, }, "updated": Map { - "id74" => Delta { + "id80" => Delta { "deleted": { "endBinding": { - "elementId": "id71", + "elementId": "id77", "fixedPoint": null, "focus": 0, "gap": 1, @@ -17902,7 +17902,7 @@ History { ], ], "startBinding": { - "elementId": "id69", + "elementId": "id75", "fixedPoint": null, "focus": 0, "gap": 1, @@ -17938,7 +17938,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id69" => Delta { + "id75" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -17969,7 +17969,7 @@ History { "isDeleted": true, }, }, - "id70" => Delta { + "id76" => Delta { "deleted": { "angle": 0, "autoResize": true, @@ -18009,7 +18009,7 @@ History { "isDeleted": true, }, }, - "id71" => Delta { + "id77" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -18049,7 +18049,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id69": true, + "id75": true, }, }, "inserted": { @@ -18068,7 +18068,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id70": true, + "id76": true, }, }, "inserted": { @@ -18090,7 +18090,7 @@ History { }, "inserted": { "selectedElementIds": { - "id70": true, + "id76": true, }, }, }, @@ -18099,11 +18099,11 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id69" => Delta { + "id75" => Delta { "deleted": { "boundElements": [ { - "id": "id70", + "id": "id76", "type": "text", }, ], @@ -18112,9 +18112,9 @@ History { "boundElements": [], }, }, - "id70" => Delta { + "id76" => Delta { "deleted": { - "containerId": "id69", + "containerId": "id75", "height": 25, "textAlign": "center", "verticalAlign": "middle", @@ -18140,13 +18140,13 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id74": true, + "id80": true, }, - "selectedLinearElementId": "id74", + "selectedLinearElementId": "id80", }, "inserted": { "selectedElementIds": { - "id69": true, + "id75": true, }, "selectedLinearElementId": null, }, @@ -18155,7 +18155,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id74" => Delta { + "id80" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -18164,7 +18164,7 @@ History { "elbowed": false, "endArrowhead": "arrow", "endBinding": { - "elementId": "id71", + "elementId": "id77", "fixedPoint": null, "focus": 0, "gap": 1, @@ -18195,7 +18195,7 @@ History { }, "startArrowhead": null, "startBinding": { - "elementId": "id69", + "elementId": "id75", "fixedPoint": null, "focus": 0, "gap": 1, @@ -18214,11 +18214,11 @@ History { }, }, "updated": Map { - "id69" => Delta { + "id75" => Delta { "deleted": { "boundElements": [ { - "id": "id74", + "id": "id80", "type": "arrow", }, ], @@ -18227,11 +18227,11 @@ History { "boundElements": [], }, }, - "id71" => Delta { + "id77" => Delta { "deleted": { "boundElements": [ { - "id": "id74", + "id": "id80", "type": "arrow", }, ], @@ -18248,15 +18248,15 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id69": true, + "id75": true, }, "selectedLinearElementId": null, }, "inserted": { "selectedElementIds": { - "id74": true, + "id80": true, }, - "selectedLinearElementId": "id74", + "selectedLinearElementId": "id80", }, }, }, @@ -18271,7 +18271,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id71": true, + "id77": true, }, }, "inserted": { @@ -18371,15 +18371,15 @@ exports[`history > singleplayer undo/redo > should support changes in elements' "penMode": false, "pendingImageElementId": null, "previousSelectedElementIds": { - "id39": true, + "id45": true, }, "resizingElement": null, "scrollX": 0, "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id39": true, - "id41": true, + "id45": true, + "id47": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": {}, @@ -18417,7 +18417,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements' "frameId": null, "groupIds": [], "height": 10, - "id": "id40", + "id": "id46", "index": "a1", "isDeleted": false, "link": null, @@ -18449,7 +18449,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements' "frameId": null, "groupIds": [], "height": 10, - "id": "id39", + "id": "id45", "index": "a2", "isDeleted": false, "link": null, @@ -18481,7 +18481,7 @@ exports[`history > singleplayer undo/redo > should support changes in elements' "frameId": null, "groupIds": [], "height": 10, - "id": "id41", + "id": "id47", "index": "a3", "isDeleted": false, "link": null, @@ -18518,7 +18518,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id39": true, + "id45": true, }, }, "inserted": { @@ -18529,7 +18529,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id39" => Delta { + "id45" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -18569,12 +18569,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id40": true, + "id46": true, }, }, "inserted": { "selectedElementIds": { - "id39": true, + "id45": true, }, }, }, @@ -18582,7 +18582,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id40" => Delta { + "id46" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -18622,12 +18622,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id41": true, + "id47": true, }, }, "inserted": { "selectedElementIds": { - "id40": true, + "id46": true, }, }, }, @@ -18635,7 +18635,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id41" => Delta { + "id47" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -18681,7 +18681,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id41" => Delta { + "id47" => Delta { "deleted": { "index": "a0V", }, @@ -18697,12 +18697,12 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id39": true, + "id45": true, }, }, "inserted": { "selectedElementIds": { - "id41": true, + "id47": true, }, }, }, @@ -18718,7 +18718,7 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id41": true, + "id47": true, }, }, "inserted": { @@ -18743,7 +18743,7 @@ History { "added": Map {}, "removed": Map {}, "updated": Map { - "id39" => Delta { + "id45" => Delta { "deleted": { "index": "a2", }, @@ -18751,7 +18751,7 @@ History { "index": "Zz", }, }, - "id41" => Delta { + "id47" => Delta { "deleted": { "index": "a3", }, @@ -18855,12 +18855,12 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "scrollY": 0, "searchMatches": [], "selectedElementIds": { - "id35_copy_copy": true, - "id36_copy_copy": true, + "id42": true, + "id44": true, }, "selectedElementsAreBeingDragged": false, "selectedGroupIds": { - "A_copy": true, + "id43": true, }, "selectionElement": null, "shouldCacheIgnoreZoom": false, @@ -18963,10 +18963,10 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id43", ], "height": 100, - "id": "id35_copy_copy", + "id": "id42", "index": "a1G", "isDeleted": false, "link": null, @@ -18997,10 +18997,10 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id43", ], "height": 100, - "id": "id36_copy_copy", + "id": "id44", "index": "a1V", "isDeleted": false, "link": null, @@ -19031,10 +19031,10 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id40", ], "height": 100, - "id": "id35_copy", + "id": "id39", "index": "a2", "isDeleted": true, "link": null, @@ -19065,10 +19065,10 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id40", ], "height": 100, - "id": "id36_copy", + "id": "id41", "index": "a3", "isDeleted": true, "link": null, @@ -19196,11 +19196,11 @@ History { "delta": Delta { "deleted": { "selectedElementIds": { - "id35_copy_copy": true, - "id36_copy_copy": true, + "id42": true, + "id44": true, }, "selectedGroupIds": { - "A_copy": true, + "id43": true, }, }, "inserted": { @@ -19217,7 +19217,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id35_copy_copy" => Delta { + "id42" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -19226,7 +19226,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id43", ], "height": 100, "index": "a1G", @@ -19250,7 +19250,7 @@ History { "isDeleted": true, }, }, - "id36_copy_copy" => Delta { + "id44" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -19259,7 +19259,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [ - "A_copy", + "id43", ], "height": 100, "index": "a1V", diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 1fc6156fe..2e34ec6b2 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -10,7 +10,7 @@ exports[`duplicate element on move when ALT is clicked > rectangle 5`] = ` "frameId": null, "groupIds": [], "height": 50, - "id": "id0_copy", + "id": "id2", "index": "a0", "isDeleted": false, "link": null, diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap index 75795b251..5d48ead6c 100644 --- a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap @@ -2129,7 +2129,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id0_copy" => Delta { + "id2" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -10619,7 +10619,7 @@ History { "elementsChange": ElementsChange { "added": Map {}, "removed": Map { - "id0_copy" => Delta { + "id6" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -10628,7 +10628,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [ - "id4_copy", + "id7", ], "height": 10, "index": "a0", @@ -10652,7 +10652,7 @@ History { "isDeleted": true, }, }, - "id1_copy" => Delta { + "id8" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -10661,7 +10661,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [ - "id4_copy", + "id7", ], "height": 10, "index": "a1", @@ -10685,7 +10685,7 @@ History { "isDeleted": true, }, }, - "id2_copy" => Delta { + "id9" => Delta { "deleted": { "angle": 0, "backgroundColor": "transparent", @@ -10694,7 +10694,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [ - "id4_copy", + "id7", ], "height": 10, "index": "a2", diff --git a/packages/excalidraw/tests/helpers/api.ts b/packages/excalidraw/tests/helpers/api.ts index f0876611e..a6432666a 100644 --- a/packages/excalidraw/tests/helpers/api.ts +++ b/packages/excalidraw/tests/helpers/api.ts @@ -40,6 +40,7 @@ import { createTestHook } from "../../components/App"; import type { Action } from "../../actions/types"; import { mutateElement } from "../../element/mutateElement"; import { pointFrom, type LocalPoint, type Radians } from "../../../math"; +import { selectGroupsForSelectedElements } from "../../groups"; const readFile = util.promisify(fs.readFile); // so that window.h is available when App.tsx is not imported as well. @@ -68,13 +69,21 @@ export class API { }); }; - static setSelectedElements = (elements: ExcalidrawElement[]) => { + static setSelectedElements = (elements: ExcalidrawElement[], editingGroupId?: string | null) => { act(() => { h.setState({ - selectedElementIds: elements.reduce((acc, element) => { - acc[element.id] = true; - return acc; - }, {} as Record), + ...selectGroupsForSelectedElements( + { + editingGroupId: editingGroupId ?? null, + selectedElementIds: elements.reduce((acc, element) => { + acc[element.id] = true; + return acc; + }, {} as Record), + }, + elements, + h.state, + h.app, + ) }); }); }; @@ -158,7 +167,7 @@ export class API { isDeleted?: boolean; frameId?: ExcalidrawElement["id"] | null; index?: ExcalidrawElement["index"]; - groupIds?: string[]; + groupIds?: ExcalidrawElement["groupIds"]; // generic element props strokeColor?: ExcalidrawGenericElement["strokeColor"]; backgroundColor?: ExcalidrawGenericElement["backgroundColor"]; @@ -369,6 +378,84 @@ export class API { return element as any; }; + static createTextContainer = (opts?: { + frameId?: ExcalidrawElement["id"]; + groupIds?: ExcalidrawElement["groupIds"]; + label?: { + text?: string; + frameId?: ExcalidrawElement["id"] | null; + groupIds?: ExcalidrawElement["groupIds"]; + }; + }) => { + const rectangle = API.createElement({ + type: "rectangle", + frameId: opts?.frameId || null, + groupIds: opts?.groupIds, + }); + + const text = API.createElement({ + type: "text", + text: opts?.label?.text || "sample-text", + width: 50, + height: 20, + fontSize: 16, + containerId: rectangle.id, + frameId: + opts?.label?.frameId === undefined + ? opts?.frameId ?? null + : opts?.label?.frameId ?? null, + groupIds: opts?.label?.groupIds === undefined + ? opts?.groupIds + : opts?.label?.groupIds , + + }); + + mutateElement( + rectangle, + { + boundElements: [{ type: "text", id: text.id }], + }, + false, + ); + + return [rectangle, text]; + }; + + static createLabeledArrow = (opts?: { + frameId?: ExcalidrawElement["id"]; + label?: { + text?: string; + frameId?: ExcalidrawElement["id"] | null; + }; + }) => { + const arrow = API.createElement({ + type: "arrow", + frameId: opts?.frameId || null, + }); + + const text = API.createElement({ + type: "text", + id: "text2", + width: 50, + height: 20, + containerId: arrow.id, + frameId: + opts?.label?.frameId === undefined + ? opts?.frameId ?? null + : opts?.label?.frameId ?? null, + }); + + mutateElement( + arrow, + { + boundElements: [{ type: "text", id: text.id }], + }, + false, + ); + + return [arrow, text]; + }; + static readFile = async ( filepath: string, encoding?: T, diff --git a/packages/excalidraw/tests/history.test.tsx b/packages/excalidraw/tests/history.test.tsx index 9402095ee..5000940ca 100644 --- a/packages/excalidraw/tests/history.test.tsx +++ b/packages/excalidraw/tests/history.test.tsx @@ -7,6 +7,7 @@ import { assertSelectedElements, render, togglePopover, + getCloneByOrigId, } from "./test-utils"; import { Excalidraw } from "../index"; import { Keyboard, Pointer, UI } from "./helpers/ui"; @@ -15,7 +16,7 @@ import { getDefaultAppState } from "../appState"; import { fireEvent, queryByTestId, waitFor } from "@testing-library/react"; import { createUndoAction, createRedoAction } from "../actions/actionHistory"; import { actionToggleViewMode } from "../actions/actionToggleViewMode"; -import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; +import { EXPORT_DATA_TYPES, MIME_TYPES, ORIG_ID } from "../constants"; import type { AppState } from "../types"; import { arrayToMap } from "../utils"; import { @@ -1138,8 +1139,8 @@ describe("history", () => { expect(h.elements).toEqual([ expect.objectContaining({ id: rect1.id, isDeleted: false }), expect.objectContaining({ id: rect2.id, isDeleted: false }), - expect.objectContaining({ id: `${rect1.id}_copy`, isDeleted: true }), - expect.objectContaining({ id: `${rect2.id}_copy`, isDeleted: true }), + expect.objectContaining({ [ORIG_ID]: rect1.id, isDeleted: true }), + expect.objectContaining({ [ORIG_ID]: rect2.id, isDeleted: true }), ]); expect(h.state.editingGroupId).toBeNull(); expect(h.state.selectedGroupIds).toEqual({ A: true }); @@ -1151,8 +1152,8 @@ describe("history", () => { expect(h.elements).toEqual([ expect.objectContaining({ id: rect1.id, isDeleted: false }), expect.objectContaining({ id: rect2.id, isDeleted: false }), - expect.objectContaining({ id: `${rect1.id}_copy`, isDeleted: false }), - expect.objectContaining({ id: `${rect2.id}_copy`, isDeleted: false }), + expect.objectContaining({ [ORIG_ID]: rect1.id, isDeleted: false }), + expect.objectContaining({ [ORIG_ID]: rect2.id, isDeleted: false }), ]); expect(h.state.editingGroupId).toBeNull(); expect(h.state.selectedGroupIds).not.toEqual( @@ -1171,14 +1172,14 @@ describe("history", () => { expect.arrayContaining([ expect.objectContaining({ id: rect1.id, isDeleted: false }), expect.objectContaining({ id: rect2.id, isDeleted: false }), - expect.objectContaining({ id: `${rect1.id}_copy`, isDeleted: true }), - expect.objectContaining({ id: `${rect2.id}_copy`, isDeleted: true }), + expect.objectContaining({ [ORIG_ID]: rect1.id, isDeleted: true }), + expect.objectContaining({ [ORIG_ID]: rect2.id, isDeleted: true }), expect.objectContaining({ - id: `${rect1.id}_copy_copy`, + [ORIG_ID]: getCloneByOrigId(rect1.id)?.id, isDeleted: false, }), expect.objectContaining({ - id: `${rect2.id}_copy_copy`, + [ORIG_ID]: getCloneByOrigId(rect2.id)?.id, isDeleted: false, }), ]), diff --git a/packages/excalidraw/tests/library.test.tsx b/packages/excalidraw/tests/library.test.tsx index 51b139ce3..7b48407b7 100644 --- a/packages/excalidraw/tests/library.test.tsx +++ b/packages/excalidraw/tests/library.test.tsx @@ -1,11 +1,11 @@ import React from "react"; import { vi } from "vitest"; -import { fireEvent, render, waitFor } from "./test-utils"; +import { fireEvent, getCloneByOrigId, render, waitFor } from "./test-utils"; import { act, queryByTestId } from "@testing-library/react"; import { Excalidraw } from "../index"; import { API } from "./helpers/api"; -import { MIME_TYPES } from "../constants"; +import { MIME_TYPES, ORIG_ID } from "../constants"; import type { LibraryItem, LibraryItems } from "../types"; import { UI } from "./helpers/ui"; import { serializeLibraryAsJSON } from "../data/json"; @@ -76,7 +76,7 @@ describe("library", () => { }), ); await waitFor(() => { - expect(h.elements).toEqual([expect.objectContaining({ id: "A_copy" })]); + expect(h.elements).toEqual([expect.objectContaining({ [ORIG_ID]: "A" })]); }); }); @@ -125,23 +125,27 @@ describe("library", () => { ); await waitFor(() => { - expect(h.elements).toEqual([ - expect.objectContaining({ - id: "rectangle1_copy", - boundElements: expect.arrayContaining([ - { type: "text", id: "text1_copy" }, - { type: "arrow", id: "arrow1_copy" }, - ]), - }), - expect.objectContaining({ - id: "text1_copy", - containerId: "rectangle1_copy", - }), - expect.objectContaining({ - id: "arrow1_copy", - endBinding: expect.objectContaining({ elementId: "rectangle1_copy" }), - }), - ]); + expect(h.elements).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + [ORIG_ID]: "rectangle1", + boundElements: expect.arrayContaining([ + { type: "text", id: getCloneByOrigId("text1").id }, + { type: "arrow", id: getCloneByOrigId("arrow1").id }, + ]), + }), + expect.objectContaining({ + [ORIG_ID]: "text1", + containerId: getCloneByOrigId("rectangle1").id, + }), + expect.objectContaining({ + [ORIG_ID]: "arrow1", + endBinding: expect.objectContaining({ + elementId: getCloneByOrigId("rectangle1").id, + }), + }), + ]), + ); }); }); @@ -170,10 +174,11 @@ describe("library", () => { await waitFor(() => { expect(h.elements).toEqual([ expect.objectContaining({ - id: "elem1_copy", + [ORIG_ID]: "elem1", }), expect.objectContaining({ - id: expect.not.stringMatching(/^(elem1_copy|elem1)$/), + id: expect.not.stringMatching(/^elem1$/), + [ORIG_ID]: expect.not.stringMatching(/^\w+$/), }), ]); }); @@ -189,7 +194,7 @@ describe("library", () => { }), ); await waitFor(() => { - expect(h.elements).toEqual([expect.objectContaining({ id: "A_copy" })]); + expect(h.elements).toEqual([expect.objectContaining({ [ORIG_ID]: "A" })]); }); expect(h.state.activeTool.type).toBe("selection"); }); diff --git a/packages/excalidraw/tests/test-utils.ts b/packages/excalidraw/tests/test-utils.ts index 4c0eacee6..1c775c221 100644 --- a/packages/excalidraw/tests/test-utils.ts +++ b/packages/excalidraw/tests/test-utils.ts @@ -11,6 +11,10 @@ import { getSelectedElements } from "../scene/selection"; import type { ExcalidrawElement } from "../element/types"; import { UI } from "./helpers/ui"; import { diffStringsUnified } from "jest-diff"; +import ansi from "ansicolor"; +import { ORIG_ID } from "../constants"; +import { arrayToMap } from "../utils"; +import type { AllPossibleKeys } from "../utility-types"; const customQueries = { ...queries, @@ -295,3 +299,150 @@ expect.addSnapshotSerializer({ ); }, }); + +export const getCloneByOrigId = ( + origId: ExcalidrawElement["id"], + returnNullIfNotExists: T = false as T, +): T extends true ? ExcalidrawElement | null : ExcalidrawElement => { + const clonedElement = window.h.elements?.find( + (el) => (el as any)[ORIG_ID] === origId, + ); + if (clonedElement) { + return clonedElement; + } + if (returnNullIfNotExists !== true) { + throw new Error(`cloned element not found for origId: ${origId}`); + } + return null as T extends true ? ExcalidrawElement | null : ExcalidrawElement; +}; + +/** + * Assertion helper that strips the actual elements of extra attributes + * so that diffs are easier to read in case of failure. + * + * Asserts element order as well, and selected element ids + * (when `selected: true` set for given element). + * + * If testing cloned elements, you can use { `[ORIG_ID]: origElement.id } + * If you need to refer to cloned element properties, you can use + * `getCloneByOrigId()`, e.g.: `{ frameId: getCloneByOrigId(origFrame.id)?.id }` + */ +export const assertElements = >( + actualElements: readonly ExcalidrawElement[], + /** array order matters */ + expectedElements: (Partial> & { + /** meta, will be stripped for element attribute checks */ + selected?: true; + } & ( + | { + id: ExcalidrawElement["id"]; + } + | { [ORIG_ID]?: string } + ))[], +) => { + const h = window.h; + + const expectedElementsWithIds: (typeof expectedElements[number] & { + id: ExcalidrawElement["id"]; + })[] = expectedElements.map((el) => { + if ("id" in el) { + return el; + } + const actualElement = actualElements.find( + (act) => (act as any)[ORIG_ID] === el[ORIG_ID], + ); + if (actualElement) { + return { ...el, id: actualElement.id }; + } + return { + ...el, + id: "UNKNOWN_ID", + }; + }); + + const map_expectedElements = arrayToMap(expectedElementsWithIds); + + const selectedElementIds = expectedElementsWithIds.reduce( + (acc: Record, el) => { + if (el.selected) { + acc[el.id] = true; + } + return acc; + }, + {}, + ); + + const mappedActualElements = actualElements.map((el) => { + const expectedElement = map_expectedElements.get(el.id); + if (expectedElement) { + const pickedAttrs: Record = {}; + + for (const key of Object.keys(expectedElement)) { + if (key === "selected") { + delete expectedElement.selected; + continue; + } + pickedAttrs[key] = (el as any)[key]; + } + + if (ORIG_ID in expectedElement) { + // @ts-ignore + pickedAttrs[ORIG_ID] = (el as any)[ORIG_ID]; + } + + return pickedAttrs; + } + return el; + }); + + try { + // testing order separately for even easier diffs + expect(actualElements.map((x) => x.id)).toEqual( + expectedElementsWithIds.map((x) => x.id), + ); + } catch (err: any) { + let errStr = "\n\nmismatched element order\n\n"; + + errStr += `actual: ${ansi.lightGray( + `[${err.actual + .map((id: string, index: number) => { + const act = actualElements[index]; + + return `${ + id === err.expected[index] ? ansi.green(id) : ansi.red(id) + } (${act.type.slice(0, 4)}${ + ORIG_ID in act ? ` ↳ ${(act as any)[ORIG_ID]}` : "" + })`; + }) + .join(", ")}]`, + )}\n${ansi.lightGray( + `expected: [${err.expected + .map((exp: string, index: number) => { + const expEl = actualElements.find((el) => el.id === exp); + const origEl = + expEl && + actualElements.find((el) => el.id === (expEl as any)[ORIG_ID]); + return expEl + ? `${ + exp === err.actual[index] + ? ansi.green(expEl.id) + : ansi.red(expEl.id) + } (${expEl.type.slice(0, 4)}${origEl ? ` ↳ ${origEl.id}` : ""})` + : exp; + }) + .join(", ")}]\n`, + )}`; + + const error = new Error(errStr); + const stack = err.stack.split("\n"); + stack.splice(1, 1); + error.stack = stack.join("\n"); + throw error; + } + + expect(mappedActualElements).toEqual( + expect.arrayContaining(expectedElementsWithIds), + ); + + expect(h.state.selectedElementIds).toEqual(selectedElementIds); +}; diff --git a/packages/excalidraw/tests/zindex.test.tsx b/packages/excalidraw/tests/zindex.test.tsx index 66599ac86..732644eb3 100644 --- a/packages/excalidraw/tests/zindex.test.tsx +++ b/packages/excalidraw/tests/zindex.test.tsx @@ -1,6 +1,6 @@ import React from "react"; import ReactDOM from "react-dom"; -import { act, render } from "./test-utils"; +import { act, getCloneByOrigId, render } from "./test-utils"; import { Excalidraw } from "../index"; import { reseed } from "../random"; import { @@ -916,9 +916,9 @@ describe("z-index manipulation", () => { API.executeAction(actionDuplicateSelection); expect(h.elements).toMatchObject([ { id: "A" }, - { id: "A_copy" }, + { id: getCloneByOrigId("A").id }, { id: "B" }, - { id: "B_copy" }, + { id: getCloneByOrigId("B").id }, ]); populateElements([ @@ -930,12 +930,12 @@ describe("z-index manipulation", () => { { id: "A" }, { id: "B" }, { - id: "A_copy", + id: getCloneByOrigId("A").id, groupIds: [expect.stringMatching(/.{3,}/)], }, { - id: "B_copy", + id: getCloneByOrigId("B").id, groupIds: [expect.stringMatching(/.{3,}/)], }, @@ -951,12 +951,12 @@ describe("z-index manipulation", () => { { id: "A" }, { id: "B" }, { - id: "A_copy", + id: getCloneByOrigId("A").id, groupIds: [expect.stringMatching(/.{3,}/)], }, { - id: "B_copy", + id: getCloneByOrigId("B").id, groupIds: [expect.stringMatching(/.{3,}/)], }, @@ -972,10 +972,10 @@ describe("z-index manipulation", () => { expect(h.elements.map((element) => element.id)).toEqual([ "A", "B", - "A_copy", - "B_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, "C", - "C_copy", + getCloneByOrigId("C").id, ]); populateElements([ @@ -988,12 +988,12 @@ describe("z-index manipulation", () => { expect(h.elements.map((element) => element.id)).toEqual([ "A", "B", - "A_copy", - "B_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, "C", "D", - "C_copy", - "D_copy", + getCloneByOrigId("C").id, + getCloneByOrigId("D").id, ]); populateElements( @@ -1010,10 +1010,10 @@ describe("z-index manipulation", () => { expect(h.elements.map((element) => element.id)).toEqual([ "A", "B", - "A_copy", - "B_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, "C", - "C_copy", + getCloneByOrigId("C").id, ]); populateElements( @@ -1031,9 +1031,9 @@ describe("z-index manipulation", () => { "A", "B", "C", - "A_copy", - "B_copy", - "C_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, + getCloneByOrigId("C").id, ]); populateElements( @@ -1054,15 +1054,15 @@ describe("z-index manipulation", () => { "A", "B", "C", - "A_copy", - "B_copy", - "C_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, + getCloneByOrigId("C").id, "D", "E", "F", - "D_copy", - "E_copy", - "F_copy", + getCloneByOrigId("D").id, + getCloneByOrigId("E").id, + getCloneByOrigId("F").id, ]); populateElements( @@ -1076,7 +1076,7 @@ describe("z-index manipulation", () => { API.executeAction(actionDuplicateSelection); expect(h.elements.map((element) => element.id)).toEqual([ "A", - "A_copy", + getCloneByOrigId("A").id, "B", "C", ]); @@ -1093,7 +1093,7 @@ describe("z-index manipulation", () => { expect(h.elements.map((element) => element.id)).toEqual([ "A", "B", - "B_copy", + getCloneByOrigId("B").id, "C", ]); @@ -1108,9 +1108,9 @@ describe("z-index manipulation", () => { API.executeAction(actionDuplicateSelection); expect(h.elements.map((element) => element.id)).toEqual([ "A", - "A_copy", + getCloneByOrigId("A").id, "B", - "B_copy", + getCloneByOrigId("B").id, "C", ]); }); @@ -1125,8 +1125,8 @@ describe("z-index manipulation", () => { expect(h.elements.map((element) => element.id)).toEqual([ "A", "C", - "A_copy", - "C_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("C").id, "B", ]); }); @@ -1144,9 +1144,9 @@ describe("z-index manipulation", () => { "A", "B", "C", - "A_copy", - "B_copy", - "C_copy", + getCloneByOrigId("A").id, + getCloneByOrigId("B").id, + getCloneByOrigId("C").id, "D", ]); }); diff --git a/packages/excalidraw/utility-types.ts b/packages/excalidraw/utility-types.ts index f7872393e..d4804d195 100644 --- a/packages/excalidraw/utility-types.ts +++ b/packages/excalidraw/utility-types.ts @@ -65,3 +65,6 @@ export type MakeBrand = { /** Maybe just promise or already fulfilled one! */ export type MaybePromise = T | Promise; + +// get union of all keys from the union of types +export type AllPossibleKeys = T extends any ? keyof T : never; diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index e4431ddd1..6a682e9cf 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -1240,3 +1240,6 @@ export class PromisePool { export const escapeDoubleQuotes = (str: string) => { return str.replace(/"/g, """); }; + +export const castArray = (value: T | T[]): T[] => + Array.isArray(value) ? value : [value]; diff --git a/yarn.lock b/yarn.lock index 79ad50f23..a71ad5738 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3916,6 +3916,11 @@ ansi-styles@^6.0.0, ansi-styles@^6.1.0: resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== +ansicolor@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/ansicolor/-/ansicolor-2.0.3.tgz#ec4448ae5baf8c2d62bf2dad52eac06ba0b5ea21" + integrity sha512-pzusTqk9VHrjgMCcTPDTTvfJfx6Q3+L5tQ6yKC8Diexmoit4YROTFIkxFvRTNL9y5s0Q8HrSrgerCD5bIC+Kiw== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" From 4f6437250603028b7fb8d137cf2aae27c354bd52 Mon Sep 17 00:00:00 2001 From: tothatt81 <39777981+tothatt81@users.noreply.github.com> Date: Tue, 4 Feb 2025 22:05:56 +0100 Subject: [PATCH 13/51] perf: Improved pointer events related performance when the sidebar is docked with a large library open (#9086) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- packages/excalidraw/components/App.tsx | 25 +- .../excalidraw/components/LibraryMenu.tsx | 336 ++++++++++-------- setupTests.ts | 3 + 3 files changed, 212 insertions(+), 152 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index dc81f9181..9699c8a8a 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -1522,13 +1522,17 @@ class App extends React.Component { const allElementsMap = this.scene.getNonDeletedElementsMap(); const shouldBlockPointerEvents = - this.state.selectionElement || - this.state.newElement || - this.state.selectedElementsAreBeingDragged || - this.state.resizingElement || - (this.state.activeTool.type === "laser" && - // technically we can just test on this once we make it more safe - this.state.cursorButton === "down"); + // default back to `--ui-pointerEvents` flow if setPointerCapture + // not supported + "setPointerCapture" in HTMLElement.prototype + ? false + : this.state.selectionElement || + this.state.newElement || + this.state.selectedElementsAreBeingDragged || + this.state.resizingElement || + (this.state.activeTool.type === "laser" && + // technically we can just test on this once we make it more safe + this.state.cursorButton === "down"); const firstSelectedElement = selectedElements[0]; @@ -6295,6 +6299,13 @@ class App extends React.Component { private handleCanvasPointerDown = ( event: React.PointerEvent, ) => { + const target = event.target as HTMLElement; + // capture subsequent pointer events to the canvas + // this makes other elements non-interactive until pointer up + if (target.setPointerCapture) { + target.setPointerCapture(event.pointerId); + } + this.maybeCleanupAfterMissingPointerUp(event.nativeEvent); this.maybeUnfollowRemoteUser(); diff --git a/packages/excalidraw/components/LibraryMenu.tsx b/packages/excalidraw/components/LibraryMenu.tsx index 4b76dfc4a..0162d93a0 100644 --- a/packages/excalidraw/components/LibraryMenu.tsx +++ b/packages/excalidraw/components/LibraryMenu.tsx @@ -2,8 +2,9 @@ import React, { useState, useCallback, useMemo, - useRef, useEffect, + memo, + useRef, } from "react"; import type Library from "../data/library"; import { @@ -17,6 +18,7 @@ import type { LibraryItem, ExcalidrawProps, UIAppState, + AppClassProperties, } from "../types"; import LibraryMenuItems from "./LibraryMenuItems"; import { trackEvent } from "../analytics"; @@ -33,9 +35,12 @@ import { useUIAppState } from "../context/ui-appState"; import "./LibraryMenu.scss"; import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; -import { isShallowEqual } from "../utils"; -import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "../element/types"; import { LIBRARY_DISABLED_TYPES } from "../constants"; +import { isShallowEqual } from "../utils"; export const isLibraryMenuOpenAtom = atom(false); @@ -43,170 +48,215 @@ const LibraryMenuWrapper = ({ children }: { children: React.ReactNode }) => { return

{children}
; }; -export const LibraryMenuContent = ({ - onInsertLibraryItems, - pendingElements, - onAddToLibrary, - setAppState, - libraryReturnUrl, - library, - id, - theme, - selectedItems, - onSelectItems, -}: { - pendingElements: LibraryItem["elements"]; - onInsertLibraryItems: (libraryItems: LibraryItems) => void; - onAddToLibrary: () => void; - setAppState: React.Component["setState"]; - libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"]; - library: Library; - id: string; - theme: UIAppState["theme"]; - selectedItems: LibraryItem["id"][]; - onSelectItems: (id: LibraryItem["id"][]) => void; -}) => { - const [libraryItemsData] = useAtom(libraryItemsAtom); +const LibraryMenuContent = memo( + ({ + onInsertLibraryItems, + pendingElements, + onAddToLibrary, + setAppState, + libraryReturnUrl, + library, + id, + theme, + selectedItems, + onSelectItems, + }: { + pendingElements: LibraryItem["elements"]; + onInsertLibraryItems: (libraryItems: LibraryItems) => void; + onAddToLibrary: () => void; + setAppState: React.Component["setState"]; + libraryReturnUrl: ExcalidrawProps["libraryReturnUrl"]; + library: Library; + id: string; + theme: UIAppState["theme"]; + selectedItems: LibraryItem["id"][]; + onSelectItems: (id: LibraryItem["id"][]) => void; + }) => { + const [libraryItemsData] = useAtom(libraryItemsAtom); - const _onAddToLibrary = useCallback( - (elements: LibraryItem["elements"]) => { - const addToLibrary = async ( - processedElements: LibraryItem["elements"], - libraryItems: LibraryItems, - ) => { - trackEvent("element", "addToLibrary", "ui"); - for (const type of LIBRARY_DISABLED_TYPES) { - if (processedElements.some((element) => element.type === type)) { - return setAppState({ - errorMessage: t(`errors.libraryElementTypeError.${type}`), - }); + const _onAddToLibrary = useCallback( + (elements: LibraryItem["elements"]) => { + const addToLibrary = async ( + processedElements: LibraryItem["elements"], + libraryItems: LibraryItems, + ) => { + trackEvent("element", "addToLibrary", "ui"); + for (const type of LIBRARY_DISABLED_TYPES) { + if (processedElements.some((element) => element.type === type)) { + return setAppState({ + errorMessage: t(`errors.libraryElementTypeError.${type}`), + }); + } } - } - const nextItems: LibraryItems = [ - { - status: "unpublished", - elements: processedElements, - id: randomId(), - created: Date.now(), - }, - ...libraryItems, - ]; - onAddToLibrary(); - library.setLibrary(nextItems).catch(() => { - setAppState({ errorMessage: t("alerts.errorAddingToLibrary") }); - }); - }; - addToLibrary(elements, libraryItemsData.libraryItems); - }, - [onAddToLibrary, library, setAppState, libraryItemsData.libraryItems], - ); + const nextItems: LibraryItems = [ + { + status: "unpublished", + elements: processedElements, + id: randomId(), + created: Date.now(), + }, + ...libraryItems, + ]; + onAddToLibrary(); + library.setLibrary(nextItems).catch(() => { + setAppState({ errorMessage: t("alerts.errorAddingToLibrary") }); + }); + }; + addToLibrary(elements, libraryItemsData.libraryItems); + }, + [onAddToLibrary, library, setAppState, libraryItemsData.libraryItems], + ); - const libraryItems = useMemo( - () => libraryItemsData.libraryItems, - [libraryItemsData], - ); + const libraryItems = useMemo( + () => libraryItemsData.libraryItems, + [libraryItemsData], + ); + + if ( + libraryItemsData.status === "loading" && + !libraryItemsData.isInitialized + ) { + return ( + +
+
+ + {t("labels.libraryLoadingMessage")} +
+
+
+ ); + } + + const showBtn = + libraryItemsData.libraryItems.length > 0 || pendingElements.length > 0; - if ( - libraryItemsData.status === "loading" && - !libraryItemsData.isInitialized - ) { return ( -
-
- - {t("labels.libraryLoadingMessage")} -
-
-
- ); - } - - const showBtn = - libraryItemsData.libraryItems.length > 0 || pendingElements.length > 0; - - return ( - - - {showBtn && ( - - )} - - ); -}; + {showBtn && ( + + )} + + ); + }, +); + +const getPendingElements = ( + elements: readonly NonDeletedExcalidrawElement[], + selectedElementIds: UIAppState["selectedElementIds"], +) => ({ + elements, + pending: getSelectedElements( + elements, + { selectedElementIds }, + { + includeBoundTextElement: true, + includeElementsInFrames: true, + }, + ), + selectedElementIds, +}); const usePendingElementsMemo = ( appState: UIAppState, - elements: readonly NonDeletedExcalidrawElement[], + app: AppClassProperties, ) => { - const create = useCallback( - (appState: UIAppState, elements: readonly NonDeletedExcalidrawElement[]) => - getSelectedElements(elements, appState, { - includeBoundTextElement: true, - includeElementsInFrames: true, - }), - [], + const elements = useExcalidrawElements(); + const [state, setState] = useState(() => + getPendingElements(elements, appState.selectedElementIds), ); - const val = useRef(create(appState, elements)); - const prevAppState = useRef(appState); - const prevElements = useRef(elements); + const selectedElementVersions = useRef( + new Map(), + ); - const update = useCallback(() => { - if ( - !isShallowEqual( - appState.selectedElementIds, - prevAppState.current.selectedElementIds, - ) || - !isShallowEqual(elements, prevElements.current) - ) { - val.current = create(appState, elements); - prevAppState.current = appState; - prevElements.current = elements; + useEffect(() => { + for (const element of state.pending) { + selectedElementVersions.current.set(element.id, element.version); } - }, [create, appState, elements]); + }, [state.pending]); - return useMemo( - () => ({ - update, - value: val.current, - }), - [update, val], - ); + useEffect(() => { + if ( + // Only update once pointer is released. + // Reading directly from app.state to make it clear it's not reactive + // (hence, there's potential for stale state) + app.state.cursorButton === "up" && + app.state.activeTool.type === "selection" + ) { + setState((prev) => { + // if selectedElementIds changed, we don't have to compare versions + // --------------------------------------------------------------------- + if ( + !isShallowEqual(prev.selectedElementIds, appState.selectedElementIds) + ) { + selectedElementVersions.current.clear(); + return getPendingElements(elements, appState.selectedElementIds); + } + // otherwise we need to check whether selected elements changed + // --------------------------------------------------------------------- + const elementsMap = app.scene.getNonDeletedElementsMap(); + for (const id of Object.keys(appState.selectedElementIds)) { + const currVersion = elementsMap.get(id)?.version; + if ( + currVersion && + currVersion !== selectedElementVersions.current.get(id) + ) { + // we can't update the selectedElementVersions in here + // because of double render in StrictMode which would overwrite + // the state in the second pass with the old `prev` state. + // Thus, we update versions in a separate effect. May create + // a race condition since current effect is not fully reactive. + return getPendingElements(elements, appState.selectedElementIds); + } + } + // nothing changed + // --------------------------------------------------------------------- + return prev; + }); + } + }, [ + app, + app.state.cursorButton, + app.state.activeTool.type, + appState.selectedElementIds, + elements, + ]); + + return state.pending; }; /** * This component is meant to be rendered inside inside our * or host apps Sidebar components. */ -export const LibraryMenu = () => { - const { library, id, onInsertElements } = useApp(); +export const LibraryMenu = memo(() => { + const app = useApp(); + const { onInsertElements } = app; const appProps = useAppProps(); const appState = useUIAppState(); - const app = useApp(); const setAppState = useExcalidrawSetAppState(); - const elements = useExcalidrawElements(); const [selectedItems, setSelectedItems] = useState([]); - const memoizedLibrary = useMemo(() => library, [library]); - // BUG: pendingElements are still causing some unnecessary rerenders because clicking into canvas returns some ids even when no element is selected. - const pendingElements = usePendingElementsMemo(appState, elements); + const memoizedLibrary = useMemo(() => app.library, [app.library]); + const pendingElements = usePendingElementsMemo(appState, app); const onInsertLibraryItems = useCallback( (libraryItems: LibraryItems) => { @@ -223,22 +273,18 @@ export const LibraryMenu = () => { }); }, [setAppState]); - useEffect(() => { - return app.onPointerUpEmitter.on(() => pendingElements.update()); - }, [app, pendingElements]); - return ( ); -}; +}); diff --git a/setupTests.ts b/setupTests.ts index d8f0b5217..20d2cc517 100644 --- a/setupTests.ts +++ b/setupTests.ts @@ -7,6 +7,9 @@ import polyfill from "./packages/excalidraw/polyfill"; import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills"; import { yellow } from "./packages/excalidraw/tests/helpers/colorize"; +// mock for pep.js not working with setPointerCapture() +HTMLElement.prototype.setPointerCapture = vi.fn(); + Object.assign(globalThis, testPolyfills); require("fake-indexeddb/auto"); From b0c8c5f7a7ed72d8356851deb723894267cdb6be Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Thu, 6 Feb 2025 10:52:03 +0100 Subject: [PATCH 14/51] feat: change empty arrowhead icon (#9100) --- packages/excalidraw/components/icons.tsx | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/excalidraw/components/icons.tsx b/packages/excalidraw/components/icons.tsx index ddea3d8ed..073d7a9f7 100644 --- a/packages/excalidraw/components/icons.tsx +++ b/packages/excalidraw/components/icons.tsx @@ -1216,11 +1216,12 @@ export const EdgeRoundIcon = createIcon( ); export const ArrowheadNoneIcon = createIcon( - , - { - width: 40, - height: 20, - }, + + + + + , + tablerIconProps, ); export const ArrowheadArrowIcon = React.memo( From 9e49c9254b4740613917cdcff5651d3e2b0c9d7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Thu, 6 Feb 2025 14:45:49 +0100 Subject: [PATCH 15/51] fix: IFrame and elbow arrow interaction fix (#9101) --- packages/excalidraw/element/binding.ts | 50 ++++++++++++++++++++-- packages/excalidraw/scene/comparisons.ts | 53 ------------------------ packages/excalidraw/scene/index.ts | 2 - 3 files changed, 46 insertions(+), 59 deletions(-) diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 5b45d982b..fa5b46181 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -32,7 +32,6 @@ import type { Bounds } from "./bounds"; import { getCenterForBounds, getElementAbsoluteCoords } from "./bounds"; import type { AppState } from "../types"; import { isPointOnShape } from "../../utils/collision"; -import { getElementAtPosition } from "../scene"; import { isArrowElement, isBindableElement, @@ -79,7 +78,6 @@ import { clamp, } from "../../math"; import { segmentIntersectRectangleElement } from "../../utils/geometry/shape"; -import { getElementsAtPosition } from "../scene/comparisons"; export type SuggestedBinding = | NonDeleted @@ -568,7 +566,7 @@ export const getHoveredElementForBinding = ( ): NonDeleted | null => { if (considerAllElements) { let cullRest = false; - const candidateElements = getElementsAtPosition( + const candidateElements = getAllElementsAtPositionForBinding( elements, (element) => isBindableElement(element, false) && @@ -622,7 +620,7 @@ export const getHoveredElementForBinding = ( .pop() as NonDeleted; } - const hoveredElement = getElementAtPosition( + const hoveredElement = getElementAtPositionForBinding( elements, (element) => isBindableElement(element, false) && @@ -641,6 +639,50 @@ export const getHoveredElementForBinding = ( return hoveredElement as NonDeleted | null; }; +const getElementAtPositionForBinding = ( + elements: readonly NonDeletedExcalidrawElement[], + isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean, +) => { + let hitElement = null; + // We need to to hit testing from front (end of the array) to back (beginning of the array) + // because array is ordered from lower z-index to highest and we want element z-index + // with higher z-index + for (let index = elements.length - 1; index >= 0; --index) { + const element = elements[index]; + if (element.isDeleted) { + continue; + } + if (isAtPositionFn(element)) { + hitElement = element; + break; + } + } + + return hitElement; +}; + +const getAllElementsAtPositionForBinding = ( + elements: readonly NonDeletedExcalidrawElement[], + isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean, +) => { + const elementsAtPosition: NonDeletedExcalidrawElement[] = []; + // We need to to hit testing from front (end of the array) to back (beginning of the array) + // because array is ordered from lower z-index to highest and we want element z-index + // with higher z-index + for (let index = elements.length - 1; index >= 0; --index) { + const element = elements[index]; + if (element.isDeleted) { + continue; + } + + if (isAtPositionFn(element)) { + elementsAtPosition.push(element); + } + } + + return elementsAtPosition; +}; + const calculateFocusAndGap = ( linearElement: NonDeleted, hoveredElement: ExcalidrawBindableElement, diff --git a/packages/excalidraw/scene/comparisons.ts b/packages/excalidraw/scene/comparisons.ts index 47561fdf9..9af3e66cb 100644 --- a/packages/excalidraw/scene/comparisons.ts +++ b/packages/excalidraw/scene/comparisons.ts @@ -1,8 +1,3 @@ -import { isIframeElement } from "../element/typeChecks"; -import type { - ExcalidrawIframeElement, - NonDeletedExcalidrawElement, -} from "../element/types"; import type { ElementOrToolType } from "../types"; export const hasBackground = (type: ElementOrToolType) => @@ -47,51 +42,3 @@ export const canChangeRoundness = (type: ElementOrToolType) => export const toolIsArrow = (type: ElementOrToolType) => type === "arrow"; export const canHaveArrowheads = (type: ElementOrToolType) => type === "arrow"; - -export const getElementAtPosition = ( - elements: readonly NonDeletedExcalidrawElement[], - isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean, -) => { - let hitElement = null; - // We need to to hit testing from front (end of the array) to back (beginning of the array) - // because array is ordered from lower z-index to highest and we want element z-index - // with higher z-index - for (let index = elements.length - 1; index >= 0; --index) { - const element = elements[index]; - if (element.isDeleted) { - continue; - } - if (isAtPositionFn(element)) { - hitElement = element; - break; - } - } - - return hitElement; -}; - -export const getElementsAtPosition = ( - elements: readonly NonDeletedExcalidrawElement[], - isAtPositionFn: (element: NonDeletedExcalidrawElement) => boolean, -) => { - const iframeLikes: ExcalidrawIframeElement[] = []; - const elementsAtPosition: NonDeletedExcalidrawElement[] = []; - // We need to to hit testing from front (end of the array) to back (beginning of the array) - // because array is ordered from lower z-index to highest and we want element z-index - // with higher z-index - for (let index = elements.length - 1; index >= 0; --index) { - const element = elements[index]; - if (element.isDeleted) { - continue; - } - if (isIframeElement(element)) { - iframeLikes.push(element); - continue; - } - if (isAtPositionFn(element)) { - elementsAtPosition.push(element); - } - } - - return elementsAtPosition.concat(iframeLikes); -}; diff --git a/packages/excalidraw/scene/index.ts b/packages/excalidraw/scene/index.ts index 0f8b7ad85..1c0b795f1 100644 --- a/packages/excalidraw/scene/index.ts +++ b/packages/excalidraw/scene/index.ts @@ -12,8 +12,6 @@ export { hasStrokeStyle, canHaveArrowheads, canChangeRoundness, - getElementAtPosition, - getElementsAtPosition, } from "./comparisons"; export { getNormalizedZoom, From c8f4a4cb41ea743b58765444ee064aaebca5d8c3 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Mon, 10 Feb 2025 15:20:18 +0100 Subject: [PATCH 16/51] feat: add `props.onDuplicate` (#9117) * feat: add `props.onDuplicate` * docs * clarify docs * fix docs --- .../actions/actionDuplicateSelection.tsx | 16 ++++++++++++-- packages/excalidraw/components/App.tsx | 21 +++++++++++++++++-- packages/excalidraw/index.tsx | 2 ++ packages/excalidraw/types.ts | 16 ++++++++++++++ 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index 735c5cf23..28dddd640 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -69,8 +69,20 @@ export const actionDuplicateSelection = register({ } } + const nextState = duplicateElements(elements, appState); + + if (app.props.onDuplicate && nextState.elements) { + const mappedElements = app.props.onDuplicate( + nextState.elements, + elements, + ); + if (mappedElements) { + nextState.elements = mappedElements; + } + } + return { - ...duplicateElements(elements, appState), + ...nextState, storeAction: StoreAction.CAPTURE, }; }, @@ -92,7 +104,7 @@ export const actionDuplicateSelection = register({ const duplicateElements = ( elements: readonly ExcalidrawElement[], appState: AppState, -): Partial => { +): Partial> => { // --------------------------------------------------------------------------- const groupIdMap = new Map(); diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 9699c8a8a..663b29193 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -3228,7 +3228,14 @@ class App extends React.Component { ); const prevElements = this.scene.getElementsIncludingDeleted(); - const nextElements = [...prevElements, ...newElements]; + let nextElements = [...prevElements, ...newElements]; + + const mappedNewSceneElements = this.props.onDuplicate?.( + nextElements, + prevElements, + ); + + nextElements = mappedNewSceneElements || nextElements; syncMovedIndices(nextElements, arrayToMap(newElements)); @@ -8442,7 +8449,17 @@ class App extends React.Component { } } - const nextSceneElements = [...nextElements, ...elementsToAppend]; + let nextSceneElements: ExcalidrawElement[] = [ + ...nextElements, + ...elementsToAppend, + ]; + + const mappedNewSceneElements = this.props.onDuplicate?.( + nextSceneElements, + elements, + ); + + nextSceneElements = mappedNewSceneElements || nextSceneElements; syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend)); diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index 0af660f19..6c9544a38 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -46,6 +46,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => { onPointerDown, onPointerUp, onScrollChange, + onDuplicate, children, validateEmbeddable, renderEmbeddable, @@ -136,6 +137,7 @@ const ExcalidrawBase = (props: ExcalidrawProps) => { onPointerDown={onPointerDown} onPointerUp={onPointerUp} onScrollChange={onScrollChange} + onDuplicate={onDuplicate} validateEmbeddable={validateEmbeddable} renderEmbeddable={renderEmbeddable} aiEnabled={aiEnabled !== false} diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 84fe45308..4974f4214 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -512,6 +512,22 @@ export interface ExcalidrawProps { data: ClipboardData, event: ClipboardEvent | null, ) => Promise | boolean; + /** + * Called when element(s) are duplicated so you can listen or modify as + * needed. + * + * Called when duplicating via mouse-drag, keyboard, paste, library insert + * etc. + * + * Returned elements will be used in place of the next elements + * (you should return all elements, including deleted, and not mutate + * the element if changes are made) + */ + onDuplicate?: ( + nextElements: readonly ExcalidrawElement[], + /** excludes the duplicated elements */ + prevElements: readonly ExcalidrawElement[], + ) => ExcalidrawElement[] | void; renderTopRightUI?: ( isMobile: boolean, appState: UIAppState, From c329470b736b5aa6e8223617c07af4d64f8ddc92 Mon Sep 17 00:00:00 2001 From: Kyosuke Fujimoto <31386431+lusingander@users.noreply.github.com> Date: Mon, 10 Feb 2025 23:24:08 +0900 Subject: [PATCH 17/51] fix: Fix inconsistency in resizing while maintaining aspect ratio (#9116) --- packages/excalidraw/element/resizeElements.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index 9789f721a..1d1ceb65b 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -771,8 +771,8 @@ const getResizedOrigin = ( x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1), y: y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle), + ((prevWidth - newWidth) / 2) * Math.sin(angle) + + (prevHeight - newHeight) / 2, }; case "west-side": return { From e3060dfb8fbb34e3c6773f566b188a6f3c4c98f0 Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Tue, 11 Feb 2025 14:23:08 +0100 Subject: [PATCH 18/51] feat: custom text metrics provider (#9121) --- .../excalidraw/actions/actionBoundText.tsx | 2 +- .../actions/actionTextAutoResize.ts | 2 +- packages/excalidraw/components/App.tsx | 16 +- packages/excalidraw/components/SearchMenu.tsx | 4 +- packages/excalidraw/data/restore.ts | 3 +- packages/excalidraw/data/transform.ts | 2 +- packages/excalidraw/element/dragElements.ts | 3 +- packages/excalidraw/element/newElement.ts | 7 +- packages/excalidraw/element/resizeElements.ts | 10 +- .../excalidraw/element/textElement.test.ts | 3 +- packages/excalidraw/element/textElement.ts | 230 +----------------- .../excalidraw/element/textMeasurements.ts | 224 +++++++++++++++++ packages/excalidraw/element/textWrapping.ts | 12 +- packages/excalidraw/element/textWysiwyg.tsx | 6 +- packages/excalidraw/fonts/Fonts.ts | 3 +- packages/excalidraw/index.tsx | 2 + packages/excalidraw/renderer/renderElement.ts | 2 +- .../excalidraw/renderer/staticSvgScene.ts | 2 +- packages/excalidraw/tests/clipboard.test.tsx | 2 +- 19 files changed, 268 insertions(+), 267 deletions(-) create mode 100644 packages/excalidraw/element/textMeasurements.ts diff --git a/packages/excalidraw/actions/actionBoundText.tsx b/packages/excalidraw/actions/actionBoundText.tsx index f47346036..d6386ab27 100644 --- a/packages/excalidraw/actions/actionBoundText.tsx +++ b/packages/excalidraw/actions/actionBoundText.tsx @@ -10,7 +10,6 @@ import { computeBoundTextPosition, computeContainerDimensionForBoundText, getBoundTextElement, - measureText, redrawTextBoundingBox, } from "../element/textElement"; import { @@ -35,6 +34,7 @@ import { arrayToMap, getFontString } from "../utils"; import { register } from "./register"; import { syncMovedIndices } from "../fractionalIndex"; import { StoreAction } from "../store"; +import { measureText } from "../element/textMeasurements"; export const actionUnbindText = register({ name: "unbindText", diff --git a/packages/excalidraw/actions/actionTextAutoResize.ts b/packages/excalidraw/actions/actionTextAutoResize.ts index 3093f3090..cbf9684e4 100644 --- a/packages/excalidraw/actions/actionTextAutoResize.ts +++ b/packages/excalidraw/actions/actionTextAutoResize.ts @@ -1,6 +1,6 @@ import { isTextElement } from "../element"; import { newElementWith } from "../element/mutateElement"; -import { measureText } from "../element/textElement"; +import { measureText } from "../element/textMeasurements"; import { getSelectedElements } from "../scene"; import { StoreAction } from "../store"; import type { AppClassProperties } from "../types"; diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 663b29193..326203359 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -331,17 +331,10 @@ import type { FileSystemHandle } from "../data/filesystem"; import { fileOpen } from "../data/filesystem"; import { bindTextToShapeAfterDuplication, - getApproxMinLineHeight, - getApproxMinLineWidth, getBoundTextElement, getContainerCenter, getContainerElement, - getLineHeightInPx, - getMinTextElementWidth, - isMeasureTextSupported, isValidTextContainer, - measureText, - normalizeText, } from "../element/textElement"; import { showHyperlinkTooltip, @@ -465,6 +458,15 @@ import { cropElement } from "../element/cropElement"; import { wrapText } from "../element/textWrapping"; import { actionCopyElementLink } from "../actions/actionElementLink"; import { isElementLink, parseElementLinkFromURL } from "../element/elementLink"; +import { + isMeasureTextSupported, + normalizeText, + measureText, + getLineHeightInPx, + getApproxMinLineWidth, + getApproxMinLineHeight, + getMinTextElementWidth, +} from "../element/textMeasurements"; const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); diff --git a/packages/excalidraw/components/SearchMenu.tsx b/packages/excalidraw/components/SearchMenu.tsx index c8bf08ac3..f9b3143f3 100644 --- a/packages/excalidraw/components/SearchMenu.tsx +++ b/packages/excalidraw/components/SearchMenu.tsx @@ -7,7 +7,6 @@ import { debounce } from "lodash"; import type { AppClassProperties } from "../types"; import { isTextElement, newTextElement } from "../element"; import type { ExcalidrawTextElement } from "../element/types"; -import { measureText } from "../element/textElement"; import { addEventListener, getFontString } from "../utils"; import { KEYS } from "../keys"; import clsx from "clsx"; @@ -20,6 +19,7 @@ import { useStable } from "../hooks/useStable"; import "./SearchMenu.scss"; import { round } from "../../math"; +import { measureText } from "../element/textMeasurements"; const searchQueryAtom = atom(""); export const searchItemInFocusAtom = atom(null); @@ -607,7 +607,6 @@ const getMatchedLines = ( textToStart, getFontString(textElement), textElement.lineHeight, - true, ); // measureText returns a non-zero width for the empty string @@ -621,7 +620,6 @@ const getMatchedLines = ( lineIndexRange.line, getFontString(textElement), textElement.lineHeight, - true, ); const spaceToStart = diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 42695b413..2ee843376 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -46,7 +46,7 @@ import { bumpVersion } from "../element/mutateElement"; import { getUpdatedTimestamp, updateActiveTool } from "../utils"; import { arrayToMap } from "../utils"; import type { MarkOptional, Mutable } from "../utility-types"; -import { detectLineHeight, getContainerElement } from "../element/textElement"; +import { getContainerElement } from "../element/textElement"; import { normalizeLink } from "./url"; import { syncInvalidIndices } from "../fractionalIndex"; import { getSizeFromPoints } from "../points"; @@ -59,6 +59,7 @@ import { } from "../scene"; import type { LocalPoint, Radians } from "../../math"; import { isFiniteNumber, pointFrom } from "../../math"; +import { detectLineHeight } from "../element/textMeasurements"; type RestoredAppState = Omit< AppState, diff --git a/packages/excalidraw/data/transform.ts b/packages/excalidraw/data/transform.ts index d1fab0db9..f15de763c 100644 --- a/packages/excalidraw/data/transform.ts +++ b/packages/excalidraw/data/transform.ts @@ -19,7 +19,6 @@ import { newMagicFrameElement, newTextElement, } from "../element/newElement"; -import { measureText, normalizeText } from "../element/textElement"; import type { ElementsMap, ExcalidrawArrowElement, @@ -55,6 +54,7 @@ import { syncInvalidIndices } from "../fractionalIndex"; import { getLineHeight } from "../fonts"; import { isArrowElement } from "../element/typeChecks"; import { pointFrom, type LocalPoint } from "../../math"; +import { measureText, normalizeText } from "../element/textMeasurements"; export type ValidLinearElement = { type: "arrow" | "line"; diff --git a/packages/excalidraw/element/dragElements.ts b/packages/excalidraw/element/dragElements.ts index 1fd771ba4..bb8fd237e 100644 --- a/packages/excalidraw/element/dragElements.ts +++ b/packages/excalidraw/element/dragElements.ts @@ -10,7 +10,7 @@ import type { NullableGridSize, PointerDownState, } from "../types"; -import { getBoundTextElement, getMinTextElementWidth } from "./textElement"; +import { getBoundTextElement } from "./textElement"; import type Scene from "../scene/Scene"; import { isArrowElement, @@ -22,6 +22,7 @@ import { import { getFontString } from "../utils"; import { TEXT_AUTOWRAP_THRESHOLD } from "../constants"; import { getGridPoint } from "../snapping"; +import { getMinTextElementWidth } from "./textMeasurements"; export const dragSelectedElements = ( pointerDownState: PointerDownState, diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 58b5ec43f..e1039537c 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -33,11 +33,7 @@ import { getNewGroupIdsForDuplication } from "../groups"; import type { AppState } from "../types"; import { getElementAbsoluteCoords } from "."; import { getResizedElementAbsoluteCoords } from "./bounds"; -import { - measureText, - normalizeText, - getBoundTextMaxWidth, -} from "./textElement"; +import { getBoundTextMaxWidth } from "./textElement"; import { wrapText } from "./textWrapping"; import { DEFAULT_ELEMENT_PROPS, @@ -51,6 +47,7 @@ import { import type { MarkOptional, Merge, Mutable } from "../utility-types"; import { getLineHeight } from "../fonts"; import type { Radians } from "../../math"; +import { normalizeText, measureText } from "./textMeasurements"; export type ElementConstructorOpts = MarkOptional< Omit, diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index 1d1ceb65b..4b46757c6 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -41,15 +41,11 @@ import type { import type { PointerDownState } from "../types"; import type Scene from "../scene/Scene"; import { - getApproxMinLineWidth, getBoundTextElement, getBoundTextElementId, getContainerElement, handleBindTextResize, getBoundTextMaxWidth, - getApproxMinLineHeight, - measureText, - getMinTextElementWidth, } from "./textElement"; import { wrapText } from "./textWrapping"; import { LinearElementEditor } from "./linearElementEditor"; @@ -64,6 +60,12 @@ import { type Radians, type LocalPoint, } from "../../math"; +import { + getMinTextElementWidth, + measureText, + getApproxMinLineWidth, + getApproxMinLineHeight, +} from "./textMeasurements"; // Returns true when transform (resizing/rotation) happened export const transformElements = ( diff --git a/packages/excalidraw/element/textElement.test.ts b/packages/excalidraw/element/textElement.test.ts index cfc078c81..2c23c2b06 100644 --- a/packages/excalidraw/element/textElement.test.ts +++ b/packages/excalidraw/element/textElement.test.ts @@ -6,9 +6,8 @@ import { getContainerCoords, getBoundTextMaxWidth, getBoundTextMaxHeight, - detectLineHeight, - getLineHeightInPx, } from "./textElement"; +import { detectLineHeight, getLineHeightInPx } from "./textMeasurements"; import type { ExcalidrawTextElementWithContainer } from "./types"; describe("Test measureText", () => { diff --git a/packages/excalidraw/element/textElement.ts b/packages/excalidraw/element/textElement.ts index 8c4bc5988..de948d9ce 100644 --- a/packages/excalidraw/element/textElement.ts +++ b/packages/excalidraw/element/textElement.ts @@ -1,4 +1,4 @@ -import { getFontString, arrayToMap, isTestEnv, normalizeEOL } from "../utils"; +import { getFontString, arrayToMap } from "../utils"; import type { ElementsMap, ExcalidrawElement, @@ -6,7 +6,6 @@ import type { ExcalidrawTextContainer, ExcalidrawTextElement, ExcalidrawTextElementWithContainer, - FontString, NonDeletedExcalidrawElement, } from "./types"; import { mutateElement } from "./mutateElement"; @@ -14,7 +13,6 @@ import { ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, ARROW_LABEL_WIDTH_FRACTION, BOUND_TEXT_PADDING, - DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, TEXT_ALIGN, VERTICAL_ALIGN, @@ -30,18 +28,7 @@ import { updateOriginalContainerCache, } from "./containerCache"; import type { ExtractSetType } from "../utility-types"; - -export const normalizeText = (text: string) => { - return ( - normalizeEOL(text) - // replace tabs with spaces so they render and measure correctly - .replace(/\t/g, " ") - ); -}; - -const splitIntoLines = (text: string) => { - return normalizeText(text).split("\n"); -}; +import { measureText } from "./textMeasurements"; export const redrawTextBoundingBox = ( textElement: ExcalidrawTextElement, @@ -281,201 +268,6 @@ export const computeBoundTextPosition = ( return { x, y }; }; -export const measureText = ( - text: string, - font: FontString, - lineHeight: ExcalidrawTextElement["lineHeight"], - forceAdvanceWidth?: true, -) => { - const _text = text - .split("\n") - // replace empty lines with single space because leading/trailing empty - // lines would be stripped from computation - .map((x) => x || " ") - .join("\n"); - const fontSize = parseFloat(font); - const height = getTextHeight(_text, fontSize, lineHeight); - const width = getTextWidth(_text, font, forceAdvanceWidth); - return { width, height }; -}; - -/** - * To get unitless line-height (if unknown) we can calculate it by dividing - * height-per-line by fontSize. - */ -export const detectLineHeight = (textElement: ExcalidrawTextElement) => { - const lineCount = splitIntoLines(textElement.text).length; - return (textElement.height / - lineCount / - textElement.fontSize) as ExcalidrawTextElement["lineHeight"]; -}; - -/** - * We calculate the line height from the font size and the unitless line height, - * aligning with the W3C spec. - */ -export const getLineHeightInPx = ( - fontSize: ExcalidrawTextElement["fontSize"], - lineHeight: ExcalidrawTextElement["lineHeight"], -) => { - return fontSize * lineHeight; -}; - -// FIXME rename to getApproxMinContainerHeight -export const getApproxMinLineHeight = ( - fontSize: ExcalidrawTextElement["fontSize"], - lineHeight: ExcalidrawTextElement["lineHeight"], -) => { - return getLineHeightInPx(fontSize, lineHeight) + BOUND_TEXT_PADDING * 2; -}; - -let canvas: HTMLCanvasElement | undefined; - -/** - * @param forceAdvanceWidth use to force retrieve the "advance width" ~ `metrics.width`, instead of the actual boundind box width. - * - * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position. - * - * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for: - * - text wrapping - * - wysiwyg editor (+padding) - * - * Everything else should be based on the actual bounding box width. - * - * `Math.ceil` of the final width adds additional buffer which stabilizes slight wrapping incosistencies. - */ -export const getLineWidth = ( - text: string, - font: FontString, - forceAdvanceWidth?: true, -) => { - if (!canvas) { - canvas = document.createElement("canvas"); - } - const canvas2dContext = canvas.getContext("2d")!; - canvas2dContext.font = font; - const metrics = canvas2dContext.measureText(text); - - const advanceWidth = metrics.width; - - // retrieve the actual bounding box width if these metrics are available (as of now > 95% coverage) - if ( - !forceAdvanceWidth && - window.TextMetrics && - "actualBoundingBoxLeft" in window.TextMetrics.prototype && - "actualBoundingBoxRight" in window.TextMetrics.prototype - ) { - // could be negative, therefore getting the absolute value - const actualWidth = - Math.abs(metrics.actualBoundingBoxLeft) + - Math.abs(metrics.actualBoundingBoxRight); - - // fallback to advance width if the actual width is zero, i.e. on text editing start - // or when actual width does not respect whitespace chars, i.e. spaces - // otherwise actual width should always be bigger - return Math.max(actualWidth, advanceWidth); - } - - // since in test env the canvas measureText algo - // doesn't measure text and instead just returns number of - // characters hence we assume that each letteris 10px - if (isTestEnv()) { - return advanceWidth * 10; - } - - return advanceWidth; -}; - -export const getTextWidth = ( - text: string, - font: FontString, - forceAdvanceWidth?: true, -) => { - const lines = splitIntoLines(text); - let width = 0; - lines.forEach((line) => { - width = Math.max(width, getLineWidth(line, font, forceAdvanceWidth)); - }); - - return width; -}; - -export const getTextHeight = ( - text: string, - fontSize: number, - lineHeight: ExcalidrawTextElement["lineHeight"], -) => { - const lineCount = splitIntoLines(text).length; - return getLineHeightInPx(fontSize, lineHeight) * lineCount; -}; - -export const charWidth = (() => { - const cachedCharWidth: { [key: FontString]: Array } = {}; - - const calculate = (char: string, font: FontString) => { - const unicode = char.charCodeAt(0); - if (!cachedCharWidth[font]) { - cachedCharWidth[font] = []; - } - if (!cachedCharWidth[font][unicode]) { - const width = getLineWidth(char, font, true); - cachedCharWidth[font][unicode] = width; - } - - return cachedCharWidth[font][unicode]; - }; - - const getCache = (font: FontString) => { - return cachedCharWidth[font]; - }; - - const clearCache = (font: FontString) => { - cachedCharWidth[font] = []; - }; - - return { - calculate, - getCache, - clearCache, - }; -})(); - -const DUMMY_TEXT = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toLocaleUpperCase(); - -// FIXME rename to getApproxMinContainerWidth -export const getApproxMinLineWidth = ( - font: FontString, - lineHeight: ExcalidrawTextElement["lineHeight"], -) => { - const maxCharWidth = getMaxCharWidth(font); - if (maxCharWidth === 0) { - return ( - measureText(DUMMY_TEXT.split("").join("\n"), font, lineHeight).width + - BOUND_TEXT_PADDING * 2 - ); - } - return maxCharWidth + BOUND_TEXT_PADDING * 2; -}; - -export const getMinCharWidth = (font: FontString) => { - const cache = charWidth.getCache(font); - if (!cache) { - return 0; - } - const cacheWithOutEmpty = cache.filter((val) => val !== undefined); - - return Math.min(...cacheWithOutEmpty); -}; - -export const getMaxCharWidth = (font: FontString) => { - const cache = charWidth.getCache(font); - if (!cache) { - return 0; - } - const cacheWithOutEmpty = cache.filter((val) => val !== undefined); - return Math.max(...cacheWithOutEmpty); -}; - export const getBoundTextElementId = (container: ExcalidrawElement | null) => { return container?.boundElements?.length ? container?.boundElements?.find((ele) => ele.type === "text")?.id || null @@ -712,24 +504,6 @@ export const getBoundTextMaxHeight = ( return height - BOUND_TEXT_PADDING * 2; }; -export const isMeasureTextSupported = () => { - const width = getTextWidth( - DUMMY_TEXT, - getFontString({ - fontSize: DEFAULT_FONT_SIZE, - fontFamily: DEFAULT_FONT_FAMILY, - }), - ); - return width > 0; -}; - -export const getMinTextElementWidth = ( - font: FontString, - lineHeight: ExcalidrawTextElement["lineHeight"], -) => { - return measureText("", font, lineHeight).width + BOUND_TEXT_PADDING * 2; -}; - /** retrieves text from text elements and concatenates to a single string */ export const getTextFromElements = ( elements: readonly ExcalidrawElement[], diff --git a/packages/excalidraw/element/textMeasurements.ts b/packages/excalidraw/element/textMeasurements.ts new file mode 100644 index 000000000..f2a132a3a --- /dev/null +++ b/packages/excalidraw/element/textMeasurements.ts @@ -0,0 +1,224 @@ +import { + BOUND_TEXT_PADDING, + DEFAULT_FONT_SIZE, + DEFAULT_FONT_FAMILY, +} from "../constants"; +import { getFontString, isTestEnv, normalizeEOL } from "../utils"; +import type { FontString, ExcalidrawTextElement } from "./types"; + +export const measureText = ( + text: string, + font: FontString, + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + const _text = text + .split("\n") + // replace empty lines with single space because leading/trailing empty + // lines would be stripped from computation + .map((x) => x || " ") + .join("\n"); + const fontSize = parseFloat(font); + const height = getTextHeight(_text, fontSize, lineHeight); + const width = getTextWidth(_text, font); + return { width, height }; +}; + +const DUMMY_TEXT = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".toLocaleUpperCase(); + +// FIXME rename to getApproxMinContainerWidth +export const getApproxMinLineWidth = ( + font: FontString, + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + const maxCharWidth = getMaxCharWidth(font); + if (maxCharWidth === 0) { + return ( + measureText(DUMMY_TEXT.split("").join("\n"), font, lineHeight).width + + BOUND_TEXT_PADDING * 2 + ); + } + return maxCharWidth + BOUND_TEXT_PADDING * 2; +}; + +export const getMinTextElementWidth = ( + font: FontString, + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + return measureText("", font, lineHeight).width + BOUND_TEXT_PADDING * 2; +}; + +export const isMeasureTextSupported = () => { + const width = getTextWidth( + DUMMY_TEXT, + getFontString({ + fontSize: DEFAULT_FONT_SIZE, + fontFamily: DEFAULT_FONT_FAMILY, + }), + ); + return width > 0; +}; + +export const normalizeText = (text: string) => { + return ( + normalizeEOL(text) + // replace tabs with spaces so they render and measure correctly + .replace(/\t/g, " ") + ); +}; + +const splitIntoLines = (text: string) => { + return normalizeText(text).split("\n"); +}; + +/** + * To get unitless line-height (if unknown) we can calculate it by dividing + * height-per-line by fontSize. + */ +export const detectLineHeight = (textElement: ExcalidrawTextElement) => { + const lineCount = splitIntoLines(textElement.text).length; + return (textElement.height / + lineCount / + textElement.fontSize) as ExcalidrawTextElement["lineHeight"]; +}; + +/** + * We calculate the line height from the font size and the unitless line height, + * aligning with the W3C spec. + */ +export const getLineHeightInPx = ( + fontSize: ExcalidrawTextElement["fontSize"], + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + return fontSize * lineHeight; +}; + +// FIXME rename to getApproxMinContainerHeight +export const getApproxMinLineHeight = ( + fontSize: ExcalidrawTextElement["fontSize"], + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + return getLineHeightInPx(fontSize, lineHeight) + BOUND_TEXT_PADDING * 2; +}; + +let textMetricsProvider: TextMetricsProvider | undefined; + +/** + * Set a custom text metrics provider. + * + * Useful for overriding the width calculation algorithm where canvas API is not available / desired. + */ +export const setCustomTextMetricsProvider = (provider: TextMetricsProvider) => { + textMetricsProvider = provider; +}; + +export interface TextMetricsProvider { + getLineWidth(text: string, fontString: FontString): number; +} + +class CanvasTextMetricsProvider implements TextMetricsProvider { + private canvas: HTMLCanvasElement; + + constructor() { + this.canvas = document.createElement("canvas"); + } + + /** + * We need to use the advance width as that's the closest thing to the browser wrapping algo, hence using it for: + * - text wrapping + * - wysiwyg editor (+padding) + * + * > The advance width is the distance between the glyph's initial pen position and the next glyph's initial pen position. + */ + public getLineWidth(text: string, fontString: FontString): number { + const context = this.canvas.getContext("2d")!; + context.font = fontString; + const metrics = context.measureText(text); + const advanceWidth = metrics.width; + + // since in test env the canvas measureText algo + // doesn't measure text and instead just returns number of + // characters hence we assume that each letteris 10px + if (isTestEnv()) { + return advanceWidth * 10; + } + + return advanceWidth; + } +} + +export const getLineWidth = (text: string, font: FontString) => { + if (!textMetricsProvider) { + textMetricsProvider = new CanvasTextMetricsProvider(); + } + + return textMetricsProvider.getLineWidth(text, font); +}; + +export const getTextWidth = (text: string, font: FontString) => { + const lines = splitIntoLines(text); + let width = 0; + lines.forEach((line) => { + width = Math.max(width, getLineWidth(line, font)); + }); + + return width; +}; + +export const getTextHeight = ( + text: string, + fontSize: number, + lineHeight: ExcalidrawTextElement["lineHeight"], +) => { + const lineCount = splitIntoLines(text).length; + return getLineHeightInPx(fontSize, lineHeight) * lineCount; +}; + +export const charWidth = (() => { + const cachedCharWidth: { [key: FontString]: Array } = {}; + + const calculate = (char: string, font: FontString) => { + const unicode = char.charCodeAt(0); + if (!cachedCharWidth[font]) { + cachedCharWidth[font] = []; + } + if (!cachedCharWidth[font][unicode]) { + const width = getLineWidth(char, font); + cachedCharWidth[font][unicode] = width; + } + + return cachedCharWidth[font][unicode]; + }; + + const getCache = (font: FontString) => { + return cachedCharWidth[font]; + }; + + const clearCache = (font: FontString) => { + cachedCharWidth[font] = []; + }; + + return { + calculate, + getCache, + clearCache, + }; +})(); + +export const getMinCharWidth = (font: FontString) => { + const cache = charWidth.getCache(font); + if (!cache) { + return 0; + } + const cacheWithOutEmpty = cache.filter((val) => val !== undefined); + + return Math.min(...cacheWithOutEmpty); +}; + +export const getMaxCharWidth = (font: FontString) => { + const cache = charWidth.getCache(font); + if (!cache) { + return 0; + } + const cacheWithOutEmpty = cache.filter((val) => val !== undefined); + return Math.max(...cacheWithOutEmpty); +}; diff --git a/packages/excalidraw/element/textWrapping.ts b/packages/excalidraw/element/textWrapping.ts index 597f62e15..1913f6ed3 100644 --- a/packages/excalidraw/element/textWrapping.ts +++ b/packages/excalidraw/element/textWrapping.ts @@ -1,5 +1,5 @@ import { ENV } from "../constants"; -import { charWidth, getLineWidth } from "./textElement"; +import { charWidth, getLineWidth } from "./textMeasurements"; import type { FontString } from "./types"; let cachedCjkRegex: RegExp | undefined; @@ -385,7 +385,7 @@ export const wrapText = ( const originalLines = text.split("\n"); for (const originalLine of originalLines) { - const currentLineWidth = getLineWidth(originalLine, font, true); + const currentLineWidth = getLineWidth(originalLine, font); if (currentLineWidth <= maxWidth) { lines.push(originalLine); @@ -423,7 +423,7 @@ const wrapLine = ( // cache single codepoint whitespace, CJK or emoji width calc. as kerning should not apply here const testLineWidth = isSingleCharacter(token) ? currentLineWidth + charWidth.calculate(token, font) - : getLineWidth(testLine, font, true); + : getLineWidth(testLine, font); // build up the current line, skipping length check for possibly trailing whitespaces if (/\s/.test(token) || testLineWidth <= maxWidth) { @@ -443,7 +443,7 @@ const wrapLine = ( // trailing line of the wrapped word might still be joined with next token/s currentLine = trailingLine; - currentLineWidth = getLineWidth(trailingLine, font, true); + currentLineWidth = getLineWidth(trailingLine, font); iterator = tokenIterator.next(); } else { // push & reset, but don't iterate on the next token, as we didn't use it yet! @@ -514,7 +514,7 @@ const wrapWord = ( * Similarly to browsers, does not trim all trailing whitespaces, but only those exceeding the `maxWidth`. */ const trimLine = (line: string, font: FontString, maxWidth: number) => { - const shouldTrimWhitespaces = getLineWidth(line, font, true) > maxWidth; + const shouldTrimWhitespaces = getLineWidth(line, font) > maxWidth; if (!shouldTrimWhitespaces) { return line; @@ -527,7 +527,7 @@ const trimLine = (line: string, font: FontString, maxWidth: number) => { "", ]; - let trimmedLineWidth = getLineWidth(trimmedLine, font, true); + let trimmedLineWidth = getLineWidth(trimmedLine, font); for (const whitespace of Array.from(whitespaces)) { const _charWidth = charWidth.calculate(whitespace, font); diff --git a/packages/excalidraw/element/textWysiwyg.tsx b/packages/excalidraw/element/textWysiwyg.tsx index efe27bc6e..a7570862d 100644 --- a/packages/excalidraw/element/textWysiwyg.tsx +++ b/packages/excalidraw/element/textWysiwyg.tsx @@ -24,8 +24,6 @@ import { getBoundTextElementId, getContainerElement, getTextElementAngle, - getTextWidth, - normalizeText, redrawTextBoundingBox, getBoundTextMaxHeight, getBoundTextMaxWidth, @@ -50,6 +48,8 @@ import { originalContainerCache, updateOriginalContainerCache, } from "./containerCache"; +import { getTextWidth } from "./textMeasurements"; +import { normalizeText } from "./textMeasurements"; const getTransform = ( width: number, @@ -350,7 +350,7 @@ export const textWysiwyg = ({ font, getBoundTextMaxWidth(container, boundTextElement), ); - const width = getTextWidth(wrappedText, font, true); + const width = getTextWidth(wrappedText, font); editable.style.width = `${width}px`; } }; diff --git a/packages/excalidraw/fonts/Fonts.ts b/packages/excalidraw/fonts/Fonts.ts index d8f257c03..4b8ba7828 100644 --- a/packages/excalidraw/fonts/Fonts.ts +++ b/packages/excalidraw/fonts/Fonts.ts @@ -6,7 +6,7 @@ import { getFontFamilyFallbacks, } from "../constants"; import { isTextElement } from "../element"; -import { charWidth, getContainerElement } from "../element/textElement"; +import { getContainerElement } from "../element/textElement"; import { containsCJK } from "../element/textWrapping"; import { ShapeCache } from "../scene/ShapeCache"; import { getFontString, PromisePool, promiseTry } from "../utils"; @@ -31,6 +31,7 @@ import type { } from "../element/types"; import type Scene from "../scene/Scene"; import type { ValueOf } from "../utility-types"; +import { charWidth } from "../element/textMeasurements"; export class Fonts { // it's ok to track fonts across multiple instances only once, so let's use diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index 6c9544a38..bd3d0f148 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -295,3 +295,5 @@ export { export { DiagramToCodePlugin } from "./components/DiagramToCodePlugin/DiagramToCodePlugin"; export { getDataURL } from "./data/blob"; export { isElementLink } from "./element/elementLink"; + +export { setCustomTextMetricsProvider } from "./element/textMeasurements"; diff --git a/packages/excalidraw/renderer/renderElement.ts b/packages/excalidraw/renderer/renderElement.ts index 50da857a2..3e87ebaf5 100644 --- a/packages/excalidraw/renderer/renderElement.ts +++ b/packages/excalidraw/renderer/renderElement.ts @@ -52,7 +52,6 @@ import { getBoundTextElement, getContainerCoords, getContainerElement, - getLineHeightInPx, getBoundTextMaxHeight, getBoundTextMaxWidth, } from "../element/textElement"; @@ -64,6 +63,7 @@ import { getVerticalOffset } from "../fonts"; import { isRightAngleRads } from "../../math"; import { getCornerRadius } from "../shapes"; import { getUncroppedImageElement } from "../element/cropElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; // using a stronger invert (100% vs our regular 93%) and saturate // as a temp hack to make images in dark theme look closer to original diff --git a/packages/excalidraw/renderer/staticSvgScene.ts b/packages/excalidraw/renderer/staticSvgScene.ts index e6cbb8d7c..b14faf7f4 100644 --- a/packages/excalidraw/renderer/staticSvgScene.ts +++ b/packages/excalidraw/renderer/staticSvgScene.ts @@ -16,7 +16,6 @@ import { LinearElementEditor } from "../element/linearElementEditor"; import { getBoundTextElement, getContainerElement, - getLineHeightInPx, } from "../element/textElement"; import { isArrowElement, @@ -38,6 +37,7 @@ import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement"; import { getVerticalOffset } from "../fonts"; import { getCornerRadius, isPathALoop } from "../shapes"; import { getUncroppedWidthAndHeight } from "../element/cropElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; const roughSVGDrawWithPrecision = ( rsvg: RoughSVG, diff --git a/packages/excalidraw/tests/clipboard.test.tsx b/packages/excalidraw/tests/clipboard.test.tsx index 63e26dbc3..94c785d4a 100644 --- a/packages/excalidraw/tests/clipboard.test.tsx +++ b/packages/excalidraw/tests/clipboard.test.tsx @@ -5,7 +5,7 @@ import { render, waitFor, GlobalTestState } from "./test-utils"; import { Pointer, Keyboard } from "./helpers/ui"; import { Excalidraw } from "../index"; import { KEYS } from "../keys"; -import { getLineHeightInPx } from "../element/textElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; import { getElementBounds } from "../element"; import type { NormalizedZoomValue } from "../types"; import { API } from "./helpers/api"; From 26f02bebeae1d422a11a0ca9e7a96752c9926881 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Wed, 12 Feb 2025 13:02:53 +0100 Subject: [PATCH 19/51] fix: stop using structuredClone (#9128) fix: stop using `structuredClone` --- packages/excalidraw/element/elbowArrow.ts | 16 ++++++++-------- packages/excalidraw/element/types.ts | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 498e59d71..a2762adfa 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -104,7 +104,7 @@ const handleSegmentRenormalization = ( elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, ) => { const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments - ? structuredClone(arrow.fixedSegments) + ? arrow.fixedSegments.slice() : null; if (nextFixedSegments) { @@ -270,7 +270,7 @@ const handleSegmentRenormalization = ( const handleSegmentRelease = ( arrow: ExcalidrawElbowArrowElement, - fixedSegments: FixedSegment[], + fixedSegments: readonly FixedSegment[], elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, ) => { const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index); @@ -444,7 +444,7 @@ const handleSegmentRelease = ( */ const handleSegmentMove = ( arrow: ExcalidrawElbowArrowElement, - fixedSegments: FixedSegment[], + fixedSegments: readonly FixedSegment[], startHeading: Heading, endHeading: Heading, hoveredStartElement: ExcalidrawBindableElement | null, @@ -686,7 +686,7 @@ const handleSegmentMove = ( const handleEndpointDrag = ( arrow: ExcalidrawElbowArrowElement, updatedPoints: readonly LocalPoint[], - fixedSegments: FixedSegment[], + fixedSegments: readonly FixedSegment[], startHeading: Heading, endHeading: Heading, startGlobalPoint: GlobalPoint, @@ -944,8 +944,8 @@ export const updateElbowArrowPoints = ( ? updates.points![1] : p, ) - : structuredClone(updates.points) - : structuredClone(arrow.points); + : updates.points.slice() + : arrow.points.slice(); const { startHeading, @@ -1965,7 +1965,7 @@ const getBindableElementForId = ( const normalizeArrowElementUpdate = ( global: GlobalPoint[], - nextFixedSegments: FixedSegment[] | null, + nextFixedSegments: readonly FixedSegment[] | null, startIsSpecial?: ExcalidrawElbowArrowElement["startIsSpecial"], endIsSpecial?: ExcalidrawElbowArrowElement["startIsSpecial"], ): { @@ -1974,7 +1974,7 @@ const normalizeArrowElementUpdate = ( y: number; width: number; height: number; - fixedSegments: FixedSegment[] | null; + fixedSegments: readonly FixedSegment[] | null; startIsSpecial?: ExcalidrawElbowArrowElement["startIsSpecial"]; endIsSpecial?: ExcalidrawElbowArrowElement["startIsSpecial"]; } => { diff --git a/packages/excalidraw/element/types.ts b/packages/excalidraw/element/types.ts index 0ab88358d..ecd5ffecd 100644 --- a/packages/excalidraw/element/types.ts +++ b/packages/excalidraw/element/types.ts @@ -337,7 +337,7 @@ export type ExcalidrawElbowArrowElement = Merge< elbowed: true; startBinding: FixedPointBinding | null; endBinding: FixedPointBinding | null; - fixedSegments: FixedSegment[] | null; + fixedSegments: readonly FixedSegment[] | null; /** * Marks that the 3rd point should be used as the 2nd point of the arrow in * order to temporarily hide the first segment of the arrow without losing From 77dc055d81269a0ae4d15a5c93c5ccc407ca139b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Wed, 12 Feb 2025 15:02:35 +0100 Subject: [PATCH 20/51] chore: Revert aspect ratio fix with element size limits and chk (#9131) --- excalidraw-app/sentry.ts | 3 + packages/excalidraw/data/restore.ts | 38 +++++++++ packages/excalidraw/element/elbowArrow.ts | 79 ++++++++++++++++++- packages/excalidraw/element/newElement.ts | 24 ++++++ packages/excalidraw/element/resizeElements.ts | 22 +++++- 5 files changed, 161 insertions(+), 5 deletions(-) diff --git a/excalidraw-app/sentry.ts b/excalidraw-app/sentry.ts index d224a266a..26dbde336 100644 --- a/excalidraw-app/sentry.ts +++ b/excalidraw-app/sentry.ts @@ -23,6 +23,9 @@ Sentry.init({ release: import.meta.env.VITE_APP_GIT_SHA, ignoreErrors: [ "undefined is not an object (evaluating 'window.__pad.performLoop')", // Only happens on Safari, but spams our servers. Doesn't break anything + "InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.", // Not much we can do about the IndexedDB closing error + /TypeError: Failed to fetch dynamically imported module: https:\/\/excalidraw\.com\/assets\/index\.esm.*/i, // This is happening when a service worker tries to load an old asset + /TypeError: error loading dynamically imported module: https:\/\/excalidraw\.com\/assets\/index\.esm.*/i, // This is happening when a service worker tries to load an old asset ], integrations: [ new SentryIntegrations.CaptureConsole({ diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 2ee843376..0c9811559 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -206,6 +206,25 @@ const restoreElementWithProperties = < "customData" in extra ? extra.customData : element.customData; } + // NOTE (mtolmacs): This is a temporary check to detect extremely large + // element position or sizing + if ( + element.x < -1e6 || + element.x > 1e6 || + element.y < -1e6 || + element.y > 1e6 || + element.width < -1e6 || + element.width > 1e6 || + element.height < -1e6 || + element.height > 1e6 + ) { + console.error( + `Restore element with properties size or position is too large ${JSON.stringify( + element, + )}`, + ); + } + return { // spread the original element properties to not lose unknown ones // for forward-compatibility @@ -220,6 +239,25 @@ const restoreElementWithProperties = < const restoreElement = ( element: Exclude, ): typeof element | null => { + // NOTE (mtolmacs): This is a temporary check to detect extremely large + // element position or sizing + if ( + element.x < -1e6 || + element.x > 1e6 || + element.y < -1e6 || + element.y > 1e6 || + element.width < -1e6 || + element.width > 1e6 || + element.height < -1e6 || + element.height > 1e6 + ) { + console.error( + `Restore element size or position is too large ${JSON.stringify( + element, + )}`, + ); + } + switch (element.type) { case "text": let fontSize = element.fontSize; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index a2762adfa..4c5f57791 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -1,4 +1,5 @@ import { + clamp, pointDistance, pointFrom, pointScaleFromOrigin, @@ -863,6 +864,8 @@ const handleEndpointDrag = ( ); }; +const MAX_POS = 1e6; + /** * */ @@ -883,6 +886,48 @@ export const updateElbowArrowPoints = ( return { points: updates.points ?? arrow.points }; } + // NOTE (mtolmacs): This is a temporary check to ensure that the incoming elbow + // arrow size is valid. This check will be removed once the issue is identified + if ( + arrow.x < -MAX_POS || + arrow.x > MAX_POS || + arrow.y < -MAX_POS || + arrow.y > MAX_POS || + arrow.x + (updates?.points?.[updates?.points?.length - 1]?.[0] ?? 0) < + -MAX_POS || + arrow.x + (updates?.points?.[updates?.points?.length - 1]?.[0] ?? 0) > + MAX_POS || + arrow.y + (updates?.points?.[updates?.points?.length - 1]?.[1] ?? 0) < + -MAX_POS || + arrow.y + (updates?.points?.[updates?.points?.length - 1]?.[1] ?? 0) > + MAX_POS || + arrow.x + (arrow?.points?.[arrow?.points?.length - 1]?.[0] ?? 0) < + -MAX_POS || + arrow.x + (arrow?.points?.[arrow?.points?.length - 1]?.[0] ?? 0) > + MAX_POS || + arrow.y + (arrow?.points?.[arrow?.points?.length - 1]?.[1] ?? 0) < + -MAX_POS || + arrow.y + (arrow?.points?.[arrow?.points?.length - 1]?.[1] ?? 0) > MAX_POS + ) { + console.error( + `Elbow arrow (or update) is outside reasonable bounds (> 1e6) arrow: ${JSON.stringify( + arrow, + )} updates: ${JSON.stringify(updates)}`, + ); + } + // @ts-ignore See above note + arrow.x = clamp(arrow.x, -MAX_POS, MAX_POS); + // @ts-ignore See above note + arrow.y = clamp(arrow.y, -MAX_POS, MAX_POS); + if (updates.points) { + updates.points = updates.points.map(([x, y]) => + pointFrom( + clamp(x, -MAX_POS, MAX_POS), + clamp(y, -MAX_POS, MAX_POS), + ), + ); + } + if (!import.meta.env.PROD) { invariant( !updates.points || updates.points.length >= 2, @@ -1981,17 +2026,45 @@ const normalizeArrowElementUpdate = ( const offsetX = global[0][0]; const offsetY = global[0][1]; - const points = global.map((p) => + let points = global.map((p) => pointTranslate( p, vectorScale(vectorFromPoint(global[0]), -1), ), ); + // NOTE (mtolmacs): This is a temporary check to see if the normalization + // creates an overly large arrow. This should be removed once we have an answer. + if ( + offsetX < -MAX_POS || + offsetX > MAX_POS || + offsetY < -MAX_POS || + offsetY > MAX_POS || + offsetX + points[points.length - 1][0] < -MAX_POS || + offsetY + points[points.length - 1][0] > MAX_POS || + offsetX + points[points.length - 1][1] < -MAX_POS || + offsetY + points[points.length - 1][1] > MAX_POS + ) { + console.error( + `Elbow arrow normalization is outside reasonable bounds (> 1e6) arrow: ${JSON.stringify( + { + x: offsetX, + y: offsetY, + points, + ...getSizeFromPoints(points), + }, + )}`, + ); + } + + points = points.map(([x, y]) => + pointFrom(clamp(x, -1e6, 1e6), clamp(y, -1e6, 1e6)), + ); + return { points, - x: offsetX, - y: offsetY, + x: clamp(offsetX, -1e6, 1e6), + y: clamp(offsetY, -1e6, 1e6), fixedSegments: (nextFixedSegments?.length ?? 0) > 0 ? nextFixedSegments : null, ...getSizeFromPoints(points), diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index e1039537c..ab417356c 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -99,6 +99,30 @@ const _newElementBase = ( ...rest }: ElementConstructorOpts & Omit, "type">, ) => { + // NOTE (mtolmacs): This is a temporary check to detect extremely large + // element position or sizing + if ( + x < -1e6 || + x > 1e6 || + y < -1e6 || + y > 1e6 || + width < -1e6 || + width > 1e6 || + height < -1e6 || + height > 1e6 + ) { + console.error( + `New element size or position is too large ${JSON.stringify({ + x, + y, + width, + height, + // @ts-ignore + points: rest.points, + })}`, + ); + } + // assign type to guard against excess properties const element: Merge = { id: rest.id || randomId(), diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index 4b46757c6..ee9c5b872 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -769,12 +769,30 @@ const getResizedOrigin = ( y: y - (newHeight - prevHeight) / 2, }; case "east-side": + // NOTE (mtolmacs): Reverting this for a short period to test if it is + // the cause of the megasized elbow arrows showing up. + if ( + Math.abs( + y + + ((prevWidth - newWidth) / 2) * Math.sin(angle) + + (prevHeight - newHeight) / 2, + ) > 1e6 + ) { + console.error( + `getResizedOrigin() new calculation creates extremely large (> 1e6) y value where the old calculation resulted in ${ + y + + (newHeight - prevHeight) / 2 + + ((prevWidth - newWidth) / 2) * Math.sin(angle) + }`, + ); + } + return { x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1), y: y + - ((prevWidth - newWidth) / 2) * Math.sin(angle) + - (prevHeight - newHeight) / 2, + (newHeight - prevHeight) / 2 + + ((prevWidth - newWidth) / 2) * Math.sin(angle), }; case "west-side": return { From f12b92ce9de0c00d3e97658a07675ef1917e3d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Thu, 13 Feb 2025 12:47:27 +0100 Subject: [PATCH 21/51] chore: Upgrade Sentry to latest and update debug messages (#9134) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- excalidraw-app/package.json | 4 +- excalidraw-app/sentry.ts | 48 +++++++- packages/excalidraw/data/restore.ts | 11 +- packages/excalidraw/element/elbowArrow.ts | 21 ++-- packages/excalidraw/element/newElement.ts | 18 ++- packages/excalidraw/element/resizeElements.ts | 12 +- yarn.lock | 112 +++++++----------- 7 files changed, 116 insertions(+), 110 deletions(-) diff --git a/excalidraw-app/package.json b/excalidraw-app/package.json index c5e1cdc5d..bc95abd01 100644 --- a/excalidraw-app/package.json +++ b/excalidraw-app/package.json @@ -27,8 +27,8 @@ }, "dependencies": { "@excalidraw/random-username": "1.0.0", - "@sentry/browser": "6.2.5", - "@sentry/integrations": "6.2.5", + "@sentry/browser": "9.0.1", + "callsites": "4.2.0", "firebase": "8.3.3", "i18next-browser-languagedetector": "6.1.4", "idb-keyval": "6.0.3", diff --git a/excalidraw-app/sentry.ts b/excalidraw-app/sentry.ts index 26dbde336..30b84f3f6 100644 --- a/excalidraw-app/sentry.ts +++ b/excalidraw-app/sentry.ts @@ -1,8 +1,9 @@ import * as Sentry from "@sentry/browser"; -import * as SentryIntegrations from "@sentry/integrations"; +import callsites from "callsites"; const SentryEnvHostnameMap: { [key: string]: string } = { "excalidraw.com": "production", + "staging.excalidraw.com": "staging", "vercel.app": "staging", }; @@ -24,11 +25,12 @@ Sentry.init({ ignoreErrors: [ "undefined is not an object (evaluating 'window.__pad.performLoop')", // Only happens on Safari, but spams our servers. Doesn't break anything "InvalidStateError: Failed to execute 'transaction' on 'IDBDatabase': The database connection is closing.", // Not much we can do about the IndexedDB closing error - /TypeError: Failed to fetch dynamically imported module: https:\/\/excalidraw\.com\/assets\/index\.esm.*/i, // This is happening when a service worker tries to load an old asset - /TypeError: error loading dynamically imported module: https:\/\/excalidraw\.com\/assets\/index\.esm.*/i, // This is happening when a service worker tries to load an old asset + /(Failed to fetch|(fetch|loading) dynamically imported module)/i, // This is happening when a service worker tries to load an old asset + /QuotaExceededError: (The quota has been exceeded|.*setItem.*Storage)/i, // localStorage quota exceeded + "Internal error opening backing store for indexedDB.open", // Private mode and disabled indexedDB ], integrations: [ - new SentryIntegrations.CaptureConsole({ + Sentry.captureConsoleIntegration({ levels: ["error"], }), ], @@ -36,6 +38,44 @@ Sentry.init({ if (event.request?.url) { event.request.url = event.request.url.replace(/#.*$/, ""); } + + if (!event.exception) { + event.exception = { + values: [ + { + type: "ConsoleError", + value: event.message ?? "Unknown error", + stacktrace: { + frames: callsites() + .slice(1) + .filter( + (frame) => + frame.getFileName() && + !frame.getFileName()?.includes("@sentry_browser.js"), + ) + .map((frame) => ({ + filename: frame.getFileName() ?? undefined, + function: frame.getFunctionName() ?? undefined, + in_app: !( + frame.getFileName()?.includes("node_modules") ?? false + ), + lineno: frame.getLineNumber() ?? undefined, + colno: frame.getColumnNumber() ?? undefined, + })), + }, + mechanism: { + type: "instrument", + handled: true, + data: { + function: "console.error", + handler: "Sentry.beforeSend", + }, + }, + }, + ], + }; + } + return event; }, }); diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 0c9811559..550b88071 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -219,9 +219,8 @@ const restoreElementWithProperties = < element.height > 1e6 ) { console.error( - `Restore element with properties size or position is too large ${JSON.stringify( - element, - )}`, + "Restore element with properties size or position is too large", + { element }, ); } @@ -251,11 +250,7 @@ const restoreElement = ( element.height < -1e6 || element.height > 1e6 ) { - console.error( - `Restore element size or position is too large ${JSON.stringify( - element, - )}`, - ); + console.error("Restore element size or position is too large", { element }); } switch (element.type) { diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 4c5f57791..d3154cae9 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -910,9 +910,11 @@ export const updateElbowArrowPoints = ( arrow.y + (arrow?.points?.[arrow?.points?.length - 1]?.[1] ?? 0) > MAX_POS ) { console.error( - `Elbow arrow (or update) is outside reasonable bounds (> 1e6) arrow: ${JSON.stringify( + "Elbow arrow (or update) is outside reasonable bounds (> 1e6)", + { arrow, - )} updates: ${JSON.stringify(updates)}`, + updates, + }, ); } // @ts-ignore See above note @@ -2046,14 +2048,13 @@ const normalizeArrowElementUpdate = ( offsetY + points[points.length - 1][1] > MAX_POS ) { console.error( - `Elbow arrow normalization is outside reasonable bounds (> 1e6) arrow: ${JSON.stringify( - { - x: offsetX, - y: offsetY, - points, - ...getSizeFromPoints(points), - }, - )}`, + "Elbow arrow normalization is outside reasonable bounds (> 1e6)", + { + x: offsetX, + y: offsetY, + points, + ...getSizeFromPoints(points), + }, ); } diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index ab417356c..464641288 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -111,16 +111,14 @@ const _newElementBase = ( height < -1e6 || height > 1e6 ) { - console.error( - `New element size or position is too large ${JSON.stringify({ - x, - y, - width, - height, - // @ts-ignore - points: rest.points, - })}`, - ); + console.error("New element size or position is too large", { + x, + y, + width, + height, + // @ts-ignore + points: rest.points, + }); } // assign type to guard against excess properties diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index ee9c5b872..63923c5d8 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -779,11 +779,13 @@ const getResizedOrigin = ( ) > 1e6 ) { console.error( - `getResizedOrigin() new calculation creates extremely large (> 1e6) y value where the old calculation resulted in ${ - y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle) - }`, + "getResizedOrigin() new calculation creates extremely large (> 1e6) y value where the old calculation resulted in", + { + result: + y + + (newHeight - prevHeight) / 2 + + ((prevWidth - newWidth) / 2) * Math.sin(angle), + }, ); } diff --git a/yarn.lock b/yarn.lock index a71ad5738..7ccc3d956 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2821,67 +2821,51 @@ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== -"@sentry/browser@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.2.5.tgz#35e259e16521d26f348a06b31eb495e0033111d6" - integrity sha512-nlvaE+D7oaj4MxoY9ikw+krQDOjftnDYJQnOwOraXPk7KYM6YwmkakLuE+x/AkaH3FQVTQF330VAa9d6SWETlA== +"@sentry-internal/browser-utils@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-9.0.1.tgz#c8edf0b0af7c4e7f1cca46cf5c523453c0de6568" + integrity sha512-/2karfYpQFtnkFrWxQgi/DuOf83OGhIdJcEmRDYDZKvj3mGHQ6n7fzIFD8fc0hPupBA/xi2kHVu7DX7scx5Fbw== dependencies: - "@sentry/core" "6.2.5" - "@sentry/types" "6.2.5" - "@sentry/utils" "6.2.5" - tslib "^1.9.3" + "@sentry/core" "9.0.1" -"@sentry/core@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.2.5.tgz#e75093f8598becc0a4a0be927f32f7ac49e8588f" - integrity sha512-I+AkgIFO6sDUoHQticP6I27TT3L+i6TUS03in3IEtpBcSeP2jyhlxI8l/wdA7gsBqUPdQ4GHOOaNgtFIcr8qag== +"@sentry-internal/feedback@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-9.0.1.tgz#1403b09bb1790e90a3fdade7a0d4b55efacffa29" + integrity sha512-U43WMmhTXx9+wtXaJRnfoFfHz2Zv9fIEWDinYZQ03yGhjnAj3033Ca+mH+wMM0SQjF0KhGLG8Os4B/OGoQzB2g== dependencies: - "@sentry/hub" "6.2.5" - "@sentry/minimal" "6.2.5" - "@sentry/types" "6.2.5" - "@sentry/utils" "6.2.5" - tslib "^1.9.3" + "@sentry/core" "9.0.1" -"@sentry/hub@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.2.5.tgz#324cae0c90d736cd1032e94104bf3f18becec4d6" - integrity sha512-YlEFdEhcfqpl2HC+/dWXBsBJEljyMzFS7LRRjCk8QANcOdp9PhwQjwebUB4/ulOBjHPP2WZk7fBBd/IKDasTUg== +"@sentry-internal/replay-canvas@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-9.0.1.tgz#c57a29b15550be98af856b040e741f252511ed99" + integrity sha512-7PBCkqNZQjbAunQmfSRkMKqviQ+jOqB/dy0nvL/T7EaahoD7VzVCGAbL29cLkPmpP3a9dzYk7ALrUqKLApwhRg== dependencies: - "@sentry/types" "6.2.5" - "@sentry/utils" "6.2.5" - tslib "^1.9.3" + "@sentry-internal/replay" "9.0.1" + "@sentry/core" "9.0.1" -"@sentry/integrations@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.2.5.tgz#37cac11b486779707d62751da36aaaefbb44951a" - integrity sha512-4LOgO8lSeGaRV4w1Y03YWtTqrZdm56ciD7k0GLhv+PcFLpiu0exsS1XSs/9vET5LB5GtIgBTeJNNbxVFvvmv8g== +"@sentry-internal/replay@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-9.0.1.tgz#494f7a33fd78bceb31f6a205aac8c29a24663678" + integrity sha512-QzHClQWOgTEjOiBaCoQMytTSyZUKo/F2SYnzeWF30qNHtOKZSXEUugOeF3Ph0wc47NdH/4qPjYZgbNEYARf2qw== dependencies: - "@sentry/types" "6.2.5" - "@sentry/utils" "6.2.5" - localforage "^1.8.1" - tslib "^1.9.3" + "@sentry-internal/browser-utils" "9.0.1" + "@sentry/core" "9.0.1" -"@sentry/minimal@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.2.5.tgz#3e963e868bfa68e97581403521fd4e09a8965b02" - integrity sha512-RKP4Qx3p7Cv0oX1cPKAkNVFYM7p2k1t32cNk1+rrVQS4hwlJ7Eg6m6fsqsO+85jd6Ne/FnyYsfo9cDD3ImTlWQ== +"@sentry/browser@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-9.0.1.tgz#b6066a24c52550141d71afaeca2d39ea9e9349b9" + integrity sha512-alI1r1NyIARjzEm5493QuOPhiT2W1gelGDV30B1oL5cKo1arjqRLHp8Ny5odlTnyDTFC4EIx5Z69J+iyhW0CvQ== dependencies: - "@sentry/hub" "6.2.5" - "@sentry/types" "6.2.5" - tslib "^1.9.3" + "@sentry-internal/browser-utils" "9.0.1" + "@sentry-internal/feedback" "9.0.1" + "@sentry-internal/replay" "9.0.1" + "@sentry-internal/replay-canvas" "9.0.1" + "@sentry/core" "9.0.1" -"@sentry/types@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.2.5.tgz#34b75285b149e0b9bc5fd54fcc2c445d978c7f2e" - integrity sha512-1Sux6CLYrV9bETMsGP/HuLFLouwKoX93CWzG8BjMueW+Di0OGxZphYjXrGuDs8xO8bAKEVGCHgVQdcB2jevS0w== - -"@sentry/utils@6.2.5": - version "6.2.5" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.2.5.tgz#be90d056b09ed1216097d7a29e3e81ba39238e1b" - integrity sha512-fJoLUZHrd5MPylV1dT4qL74yNFDl1Ur/dab+pKNSyvnHPnbZ/LRM7aJ8VaRY/A7ZdpRowU+E14e/Yeem2c6gtQ== - dependencies: - "@sentry/types" "6.2.5" - tslib "^1.9.3" +"@sentry/core@9.0.1": + version "9.0.1" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-9.0.1.tgz#da0207f7a4f74eb4af4ba26ad4244056968b3e41" + integrity sha512-RQ3B3NfF+BdmQz1c+vj4OBO+kxvxSsYMcmCDxSEZ7YrS/6Er1kMy0fwfxmdZJMdM1LlzXmO0XWF2g1IO9CzKyQ== "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -4450,6 +4434,11 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: get-intrinsic "^1.2.4" set-function-length "^1.2.1" +callsites@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-4.2.0.tgz#98761d5be3ce092e4b9c92f7fb8c8eb9b83cadc8" + integrity sha512-kfzR4zzQtAE9PC7CzZsjl3aBNbXWuXiSeOCdLcPpBfGW8YuCqQHcRPFDbr/BPVmd3EEPVpuFzLyuT/cUhPr4OQ== + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -6863,11 +6852,6 @@ image-blob-reduce@3.0.1: dependencies: pica "^7.1.0" -immediate@~3.0.5: - version "3.0.6" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" - integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== - immutable@^4.0.0: version "4.3.6" resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" @@ -7548,13 +7532,6 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lie@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" - integrity sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw== - dependencies: - immediate "~3.0.5" - lilconfig@2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.4.tgz#f4507d043d7058b380b6a8f5cb7bcd4b34cee082" @@ -7618,13 +7595,6 @@ loader-utils@^2.0.0: emojis-list "^3.0.0" json5 "^2.1.2" -localforage@^1.8.1: - version "1.10.0" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.10.0.tgz#5c465dc5f62b2807c3a84c0c6a1b1b3212781dd4" - integrity sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg== - dependencies: - lie "3.1.1" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -10055,7 +10025,7 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1, tslib@^1.9.3: +tslib@^1.8.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== From 16b86d7d1671f766580f3a45c79ecb465523cad1 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Thu, 13 Feb 2025 13:57:14 +0100 Subject: [PATCH 22/51] chore: update firebase@8 to @11 (#9136) --- .../components/ExportToExcalidrawPlus.tsx | 19 +- excalidraw-app/data/firebase.ts | 147 ++-- excalidraw-app/package.json | 2 +- yarn.lock | 749 ++++++++++-------- 4 files changed, 494 insertions(+), 423 deletions(-) diff --git a/excalidraw-app/components/ExportToExcalidrawPlus.tsx b/excalidraw-app/components/ExportToExcalidrawPlus.tsx index 1ba82a0c7..f9f9f678b 100644 --- a/excalidraw-app/components/ExportToExcalidrawPlus.tsx +++ b/excalidraw-app/components/ExportToExcalidrawPlus.tsx @@ -25,6 +25,7 @@ import { MIME_TYPES } from "../../packages/excalidraw/constants"; import { trackEvent } from "../../packages/excalidraw/analytics"; import { getFrame } from "../../packages/excalidraw/utils"; import { ExcalidrawLogo } from "../../packages/excalidraw/components/ExcalidrawLogo"; +import { uploadBytes, ref } from "firebase/storage"; export const exportToExcalidrawPlus = async ( elements: readonly NonDeletedExcalidrawElement[], @@ -32,7 +33,7 @@ export const exportToExcalidrawPlus = async ( files: BinaryFiles, name: string, ) => { - const firebase = await loadFirebaseStorage(); + const storage = await loadFirebaseStorage(); const id = `${nanoid(12)}`; @@ -49,15 +50,13 @@ export const exportToExcalidrawPlus = async ( }, ); - await firebase - .storage() - .ref(`/migrations/scenes/${id}`) - .put(blob, { - customMetadata: { - data: JSON.stringify({ version: 2, name }), - created: Date.now().toString(), - }, - }); + const storageRef = ref(storage, `/migrations/scenes/${id}`); + await uploadBytes(storageRef, blob, { + customMetadata: { + data: JSON.stringify({ version: 2, name }), + created: Date.now().toString(), + }, + }); const filesMap = new Map(); for (const element of elements) { diff --git a/excalidraw-app/data/firebase.ts b/excalidraw-app/data/firebase.ts index 299f3ee98..bc275b39c 100644 --- a/excalidraw-app/data/firebase.ts +++ b/excalidraw-app/data/firebase.ts @@ -22,9 +22,17 @@ import { import { MIME_TYPES } from "../../packages/excalidraw/constants"; import type { SyncableExcalidrawElement } from "."; import { getSyncableElements } from "."; -import type { ResolutionType } from "../../packages/excalidraw/utility-types"; import type { Socket } from "socket.io-client"; import type { RemoteExcalidrawElement } from "../../packages/excalidraw/data/reconcile"; +import { initializeApp } from "firebase/app"; +import { + getFirestore, + doc, + getDoc, + runTransaction, + Bytes, +} from "firebase/firestore"; +import { getStorage, ref, uploadBytes } from "firebase/storage"; // private // ----------------------------------------------------------------------------- @@ -41,80 +49,42 @@ try { FIREBASE_CONFIG = {}; } -let firebasePromise: Promise | null = - null; -let firestorePromise: Promise | null | true = null; -let firebaseStoragePromise: Promise | null | true = null; +let firebaseApp: ReturnType | null = null; +let firestore: ReturnType | null = null; +let firebaseStorage: ReturnType | null = null; -let isFirebaseInitialized = false; - -const _loadFirebase = async () => { - const firebase = ( - await import(/* webpackChunkName: "firebase" */ "firebase/app") - ).default; - - if (!isFirebaseInitialized) { - try { - firebase.initializeApp(FIREBASE_CONFIG); - } catch (error: any) { - // trying initialize again throws. Usually this is harmless, and happens - // mainly in dev (HMR) - if (error.code === "app/duplicate-app") { - console.warn(error.name, error.code); - } else { - throw error; - } - } - isFirebaseInitialized = true; +const _initializeFirebase = () => { + if (!firebaseApp) { + firebaseApp = initializeApp(FIREBASE_CONFIG); } - - return firebase; + return firebaseApp; }; -const _getFirebase = async (): Promise< - typeof import("firebase/app").default -> => { - if (!firebasePromise) { - firebasePromise = _loadFirebase(); +const _getFirestore = () => { + if (!firestore) { + firestore = getFirestore(_initializeFirebase()); } - return firebasePromise; + return firestore; +}; + +const _getStorage = () => { + if (!firebaseStorage) { + firebaseStorage = getStorage(_initializeFirebase()); + } + return firebaseStorage; }; // ----------------------------------------------------------------------------- -const loadFirestore = async () => { - const firebase = await _getFirebase(); - if (!firestorePromise) { - firestorePromise = import( - /* webpackChunkName: "firestore" */ "firebase/firestore" - ); - } - if (firestorePromise !== true) { - await firestorePromise; - firestorePromise = true; - } - return firebase; -}; - export const loadFirebaseStorage = async () => { - const firebase = await _getFirebase(); - if (!firebaseStoragePromise) { - firebaseStoragePromise = import( - /* webpackChunkName: "storage" */ "firebase/storage" - ); - } - if (firebaseStoragePromise !== true) { - await firebaseStoragePromise; - firebaseStoragePromise = true; - } - return firebase; + return _getStorage(); }; -interface FirebaseStoredScene { +type FirebaseStoredScene = { sceneVersion: number; - iv: firebase.default.firestore.Blob; - ciphertext: firebase.default.firestore.Blob; -} + iv: Bytes; + ciphertext: Bytes; +}; const encryptElements = async ( key: string, @@ -175,7 +145,7 @@ export const saveFilesToFirebase = async ({ prefix: string; files: { id: FileId; buffer: Uint8Array }[]; }) => { - const firebase = await loadFirebaseStorage(); + const storage = await loadFirebaseStorage(); const erroredFiles: FileId[] = []; const savedFiles: FileId[] = []; @@ -183,17 +153,10 @@ export const saveFilesToFirebase = async ({ await Promise.all( files.map(async ({ id, buffer }) => { try { - await firebase - .storage() - .ref(`${prefix}/${id}`) - .put( - new Blob([buffer], { - type: MIME_TYPES.binary, - }), - { - cacheControl: `public, max-age=${FILE_CACHE_MAX_AGE_SEC}`, - }, - ); + const storageRef = ref(storage, `${prefix}/${id}`); + await uploadBytes(storageRef, buffer, { + cacheControl: `public, max-age=${FILE_CACHE_MAX_AGE_SEC}`, + }); savedFiles.push(id); } catch (error: any) { erroredFiles.push(id); @@ -205,7 +168,6 @@ export const saveFilesToFirebase = async ({ }; const createFirebaseSceneDocument = async ( - firebase: ResolutionType, elements: readonly SyncableExcalidrawElement[], roomKey: string, ) => { @@ -213,10 +175,8 @@ const createFirebaseSceneDocument = async ( const { ciphertext, iv } = await encryptElements(roomKey, elements); return { sceneVersion, - ciphertext: firebase.firestore.Blob.fromUint8Array( - new Uint8Array(ciphertext), - ), - iv: firebase.firestore.Blob.fromUint8Array(iv), + ciphertext: Bytes.fromUint8Array(new Uint8Array(ciphertext)), + iv: Bytes.fromUint8Array(iv), } as FirebaseStoredScene; }; @@ -236,20 +196,14 @@ export const saveToFirebase = async ( return null; } - const firebase = await loadFirestore(); - const firestore = firebase.firestore(); + const firestore = _getFirestore(); + const docRef = doc(firestore, "scenes", roomId); - const docRef = firestore.collection("scenes").doc(roomId); - - const storedScene = await firestore.runTransaction(async (transaction) => { + const storedScene = await runTransaction(firestore, async (transaction) => { const snapshot = await transaction.get(docRef); - if (!snapshot.exists) { - const storedScene = await createFirebaseSceneDocument( - firebase, - elements, - roomKey, - ); + if (!snapshot.exists()) { + const storedScene = await createFirebaseSceneDocument(elements, roomKey); transaction.set(docRef, storedScene); @@ -269,7 +223,6 @@ export const saveToFirebase = async ( ); const storedScene = await createFirebaseSceneDocument( - firebase, reconciledElements, roomKey, ); @@ -294,15 +247,13 @@ export const loadFromFirebase = async ( roomKey: string, socket: Socket | null, ): Promise => { - const firebase = await loadFirestore(); - const db = firebase.firestore(); - - const docRef = db.collection("scenes").doc(roomId); - const doc = await docRef.get(); - if (!doc.exists) { + const firestore = _getFirestore(); + const docRef = doc(firestore, "scenes", roomId); + const docSnap = await getDoc(docRef); + if (!docSnap.exists()) { return null; } - const storedScene = doc.data() as FirebaseStoredScene; + const storedScene = docSnap.data() as FirebaseStoredScene; const elements = getSyncableElements( restoreElements(await decryptElements(storedScene, roomKey), null), ); diff --git a/excalidraw-app/package.json b/excalidraw-app/package.json index bc95abd01..2da2b37c2 100644 --- a/excalidraw-app/package.json +++ b/excalidraw-app/package.json @@ -29,7 +29,7 @@ "@excalidraw/random-username": "1.0.0", "@sentry/browser": "9.0.1", "callsites": "4.2.0", - "firebase": "8.3.3", + "firebase": "11.3.1", "i18next-browser-languagedetector": "6.1.4", "idb-keyval": "6.0.3", "jotai": "2.11.0", diff --git a/yarn.lock b/yarn.lock index 7ccc3d956..d4727368c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1915,229 +1915,396 @@ resolved "https://registry.yarnpkg.com/@excalidraw/random-username/-/random-username-1.1.0.tgz#6f388d6a9708cf655b8c9c6aa3fa569ee71ecf0f" integrity sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA== -"@firebase/analytics-types@0.4.0": +"@firebase/analytics-compat@0.2.17": + version "0.2.17" + resolved "https://registry.yarnpkg.com/@firebase/analytics-compat/-/analytics-compat-0.2.17.tgz#c3cfc8ffb863d574ec26d86f9c8344d752832995" + integrity sha512-SJNVOeTvzdqZQvXFzj7yAirXnYcLDxh57wBFROfeowq/kRN1AqOw1tG6U4OiFOEhqi7s3xLze/LMkZatk2IEww== + dependencies: + "@firebase/analytics" "0.10.11" + "@firebase/analytics-types" "0.8.3" + "@firebase/component" "0.6.12" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/analytics-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.8.3.tgz#d08cd39a6209693ca2039ba7a81570dfa6c1518f" + integrity sha512-VrIp/d8iq2g501qO46uGz3hjbDb8xzYMrbu8Tp0ovzIzrvJZ2fvmj649gTjge/b7cCCcjT0H37g1gVtlNhnkbg== + +"@firebase/analytics@0.10.11": + version "0.10.11" + resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.10.11.tgz#6896413e92613573af775c45050af889a43676da" + integrity sha512-zwuPiRE0+hgcS95JZbJ6DFQN4xYFO8IyGxpeePTV51YJMwCf3lkBa6FnZ/iXIqDKcBPMgMuuEZozI0BJWaLEYg== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/installations" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/app-check-compat@0.3.18": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@firebase/app-check-compat/-/app-check-compat-0.3.18.tgz#abe63858fca86b61ea431e0d9e58ccb8bac1b275" + integrity sha512-qjozwnwYmAIdrsVGrJk+hnF1WBois54IhZR6gO0wtZQoTvWL/GtiA2F31TIgAhF0ayUiZhztOv1RfC7YyrZGDQ== + dependencies: + "@firebase/app-check" "0.8.11" + "@firebase/app-check-types" "0.5.3" + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/app-check-interop-types@0.3.3": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-interop-types/-/app-check-interop-types-0.3.3.tgz#ed9c4a4f48d1395ef378f007476db3940aa5351a" + integrity sha512-gAlxfPLT2j8bTI/qfe3ahl2I2YcBQ8cFIBdhAQA4I2f3TndcO+22YizyGYuttLHPQEpWkhmpFW60VCFEPg4g5A== + +"@firebase/app-check-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/app-check-types/-/app-check-types-0.5.3.tgz#38ba954acf4bffe451581a32fffa20337f11d8e5" + integrity sha512-hyl5rKSj0QmwPdsAxrI5x1otDlByQ7bvNvVt8G/XPO2CSwE++rmSVf3VEhaeOR4J8ZFaF0Z0NDSmLejPweZ3ng== + +"@firebase/app-check@0.8.11": + version "0.8.11" + resolved "https://registry.yarnpkg.com/@firebase/app-check/-/app-check-0.8.11.tgz#3c67148046fea0a0a9a1eecf1a17fdc31a76eda7" + integrity sha512-42zIfRI08/7bQqczAy7sY2JqZYEv3a1eNa4fLFdtJ54vNevbBIRSEA3fZgRqWFNHalh5ohsBXdrYgFqaRIuCcQ== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/app-compat@0.2.50": + version "0.2.50" + resolved "https://registry.yarnpkg.com/@firebase/app-compat/-/app-compat-0.2.50.tgz#665b6db432414229b96763e6b1cf5e38463c58d0" + integrity sha512-7yD362icKgjoNvFxwth420TNZgqCfuTJ28yQCdpyjC2fXyaZHhAbxVKnHEXGTAaUKSHWxsIy46lBKGi/x/Mflw== + dependencies: + "@firebase/app" "0.11.1" + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/app-types@0.9.3": + version "0.9.3" + resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.9.3.tgz#8408219eae9b1fb74f86c24e7150a148460414ad" + integrity sha512-kRVpIl4vVGJ4baogMDINbyrIOtOxqhkZQg4jTq3l8Lw6WSk0xfpEYzezFu+Kl4ve4fbPl79dvwRtaFqAC/ucCw== + +"@firebase/app@0.11.1": + version "0.11.1" + resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.11.1.tgz#20663522be71307c8e5c74828bb621cdcdd3f5b4" + integrity sha512-Vz4DrNLPfDx3RwQf+4klXtu7OUYDO6xz2hlRyFawWskS7YqdtNzkDDxrqH20KDfjCF1lib46/NgchIj1+8h4wQ== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/auth-compat@0.5.18": + version "0.5.18" + resolved "https://registry.yarnpkg.com/@firebase/auth-compat/-/auth-compat-0.5.18.tgz#ba1674287e6df4f95675866d6f960a9fc4a9abfc" + integrity sha512-dFBev8AMNb2AgIt9afwf/Ku4/0Wq9R9OFSeBB/xjyJt+RfQ9PnNWqU2oFphews23byLg6jle8twRA7iOYfRGRw== + dependencies: + "@firebase/auth" "1.9.0" + "@firebase/auth-types" "0.13.0" + "@firebase/component" "0.6.12" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/auth-interop-types@0.2.4": + version "0.2.4" + resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.2.4.tgz#176a08686b0685596ff03d7879b7e4115af53de0" + integrity sha512-JPgcXKCuO+CWqGDnigBtvo09HeBs5u/Ktc2GaFj2m01hLarbxthLNm7Fk8iOP1aqAtXV+fnnGj7U28xmk7IwVA== + +"@firebase/auth-types@0.13.0": + version "0.13.0" + resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.13.0.tgz#ae6e0015e3bd4bfe18edd0942b48a0a118a098d9" + integrity sha512-S/PuIjni0AQRLF+l9ck0YpsMOdE8GO2KU6ubmBB7P+7TJUCQDa3R1dlgYm9UzGbbePMZsp0xzB93f2b/CgxMOg== + +"@firebase/auth@1.9.0": + version "1.9.0" + resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-1.9.0.tgz#eea1ab78fd3d68db3cdef69a0d7fba3663a940c5" + integrity sha512-Xz2mbEYauF689qXG/4HppS2+/yGo9R7B6eNUBh3H2+XpAZTGdx8d8TFsW/BMTAK9Q95NB0pb1Bbvfx0lwofq8Q== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/component@0.6.12": + version "0.6.12" + resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.6.12.tgz#08905a534e9b769164e7e1b1e80f6e7611eb67f3" + integrity sha512-YnxqjtohLbnb7raXt2YuA44cC1wA9GiehM/cmxrsoxKlFxBLy2V0OkRSj9gpngAE0UoJ421Wlav9ycO7lTPAUw== + dependencies: + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/data-connect@0.3.0": + version "0.3.0" + resolved "https://registry.yarnpkg.com/@firebase/data-connect/-/data-connect-0.3.0.tgz#5602986c28e2ac94df2499a7cf68ad622957089e" + integrity sha512-inbLq0JyQD/d02Al3Lso0Hc8z1BVpB3dYSMFcQkeKhYyjn5bspLczLdasPbCOEUp8MOkLblLZhJuRs7Q/spFnw== + dependencies: + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/database-compat@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@firebase/database-compat/-/database-compat-2.0.3.tgz#87f18e814c06d62fea4bfb10d3b833f4259345ca" + integrity sha512-uHGQrSUeJvsDfA+IyHW5O4vdRPsCksEzv4T4Jins+bmQgYy20ZESU4x01xrQCn/nzqKHuQMEW99CoCO7D+5NiQ== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/database" "1.0.12" + "@firebase/database-types" "1.0.8" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/database-types@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-1.0.8.tgz#eddcce594be118bf9aebb043b5a6d51cfb6de620" + integrity sha512-6lPWIGeufhUq1heofZULyVvWFhD01TUrkkB9vyhmksjZ4XF7NaivQp9rICMk7QNhqwa+uDCaj4j+Q8qqcSVZ9g== + dependencies: + "@firebase/app-types" "0.9.3" + "@firebase/util" "1.10.3" + +"@firebase/database@1.0.12": + version "1.0.12" + resolved "https://registry.yarnpkg.com/@firebase/database/-/database-1.0.12.tgz#4e1807b82dc734df8596eac44d7766ff96c2de24" + integrity sha512-psFl5t6rSFHq3i3fnU1QQlc4BB9Hnhh8TgEqvQlPPm8kDLw8gYxvjqYw3c5CZW0+zKR837nwT6im/wtJUivMKw== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + faye-websocket "0.11.4" + tslib "^2.1.0" + +"@firebase/firestore-compat@0.3.43": + version "0.3.43" + resolved "https://registry.yarnpkg.com/@firebase/firestore-compat/-/firestore-compat-0.3.43.tgz#c62994b9b26d011a96265d6aa524a0d6b45a2c1b" + integrity sha512-zxg7YS07XQnTetGs3GADM/eA6HB4vWUp+Av4iugmTbft0fQxuTSnGm7ifctaYuR7VMTPckU9CW+oFC9QUNSYvg== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/firestore" "4.7.8" + "@firebase/firestore-types" "3.0.3" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/firestore-types@3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-3.0.3.tgz#7d0c3dd8850c0193d8f5ee0cc8f11961407742c1" + integrity sha512-hD2jGdiWRxB/eZWF89xcK9gF8wvENDJkzpVFb4aGkzfEaKxVRD1kjz1t1Wj8VZEp2LCB53Yx1zD8mrhQu87R6Q== + +"@firebase/firestore@4.7.8": + version "4.7.8" + resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-4.7.8.tgz#38b124a4d50a390934f70d916a84546376abdf4e" + integrity sha512-eDvVJ/I5vSmIdGmLHJAK1OcviigIxjjia6i5/AkMFq6vZMt7CBXA0B5Xz9pGRCZ7WewFcsCbK1ZUQoYJ91+Cew== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + "@firebase/webchannel-wrapper" "1.0.3" + "@grpc/grpc-js" "~1.9.0" + "@grpc/proto-loader" "^0.7.8" + tslib "^2.1.0" + +"@firebase/functions-compat@0.3.19": + version "0.3.19" + resolved "https://registry.yarnpkg.com/@firebase/functions-compat/-/functions-compat-0.3.19.tgz#f1d1ce51674a6ee8d5449b721374d35243dc3002" + integrity sha512-uw4tR8NcJCDu86UD63Za8A8SgFgmAVFb1XsGlkuBY7gpLyZWEFavWnwRkZ/8cUwpqUhp/SptXFZ1WFJSnOokLw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/functions" "0.12.2" + "@firebase/functions-types" "0.6.3" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/functions-types@0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.6.3.tgz#f5faf770248b13f45d256f614230da6a11bfb654" + integrity sha512-EZoDKQLUHFKNx6VLipQwrSMh01A1SaL3Wg6Hpi//x6/fJ6Ee4hrAeswK99I5Ht8roiniKHw4iO0B1Oxj5I4plg== + +"@firebase/functions@0.12.2": + version "0.12.2" + resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.12.2.tgz#bea33b35437278228be563dfc02520d8623d43f4" + integrity sha512-iKpFDoCYk/Qm+Qwv5ynRb9/yq64QOt0A0+t9NuekyAZnSoV56kSNq/PmsVmBauar5SlmEjhHk6QKdMBP9S0gXA== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/auth-interop-types" "0.2.4" + "@firebase/component" "0.6.12" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/installations-compat@0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@firebase/installations-compat/-/installations-compat-0.2.12.tgz#ee6396f3cc787c0dd4fc5dd87fec1db9dbb40c97" + integrity sha512-RhcGknkxmFu92F6Jb3rXxv6a4sytPjJGifRZj8MSURPuv2Xu+/AispCXEfY1ZraobhEHTG5HLGsP6R4l9qB5aA== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/installations" "0.6.12" + "@firebase/installations-types" "0.5.3" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/installations-types@0.5.3": + version "0.5.3" + resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.5.3.tgz#cac8a14dd49f09174da9df8ae453f9b359c3ef2f" + integrity sha512-2FJI7gkLqIE0iYsNQ1P751lO3hER+Umykel+TkLwHj6plzWVxqvfclPUZhcKFVQObqloEBTmpi2Ozn7EkCABAA== + +"@firebase/installations@0.6.12": + version "0.6.12" + resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.6.12.tgz#6d9ad14e60caa8fae4ec0120c0e46ceb9d6fbdae" + integrity sha512-ES/WpuAV2k2YtBTvdaknEo7IY8vaGjIjS3zhnHSAIvY9KwTR8XZFXOJoZ3nSkjN1A5R4MtEh+07drnzPDg9vaw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/util" "1.10.3" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/logger@0.4.4": + version "0.4.4" + resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.4.4.tgz#29e8379d20fd1149349a195ee6deee4573a86f48" + integrity sha512-mH0PEh1zoXGnaR8gD1DeGeNZtWFKbnz9hDO91dIml3iou1gpOnLqXQ2dJfB71dj6dpmUjcQ6phY3ZZJbjErr9g== + dependencies: + tslib "^2.1.0" + +"@firebase/messaging-compat@0.2.16": + version "0.2.16" + resolved "https://registry.yarnpkg.com/@firebase/messaging-compat/-/messaging-compat-0.2.16.tgz#533af4542a54b932146d175d5687aedd428be972" + integrity sha512-9HZZ88Ig3zQ0ok/Pwt4gQcNsOhoEy8hDHoGsV1am6ulgMuGuDVD2gl11Lere2ksL+msM12Lddi2x/7TCqmODZw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/messaging" "0.12.16" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/messaging-interop-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/messaging-interop-types/-/messaging-interop-types-0.2.3.tgz#e647c9cd1beecfe6a6e82018a6eec37555e4da3e" + integrity sha512-xfzFaJpzcmtDjycpDeCUj0Ge10ATFi/VHVIvEEjDNc3hodVBQADZ7BWQU7CuFpjSHE+eLuBI13z5F/9xOoGX8Q== + +"@firebase/messaging@0.12.16": + version "0.12.16" + resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.12.16.tgz#bd8a768274bdc4368396bd9eaa356bffb998bef2" + integrity sha512-VJ8sCEIeP3+XkfbJA7410WhYGHdloYFZXoHe/vt+vNVDGw8JQPTQSVTRvjrUprEf5I4Tbcnpr2H34lS6zhCHSA== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/installations" "0.6.12" + "@firebase/messaging-interop-types" "0.2.3" + "@firebase/util" "1.10.3" + idb "7.1.1" + tslib "^2.1.0" + +"@firebase/performance-compat@0.2.13": + version "0.2.13" + resolved "https://registry.yarnpkg.com/@firebase/performance-compat/-/performance-compat-0.2.13.tgz#29bb94909c10553b40ca97e7f7d0e163bad8a77d" + integrity sha512-pB0SMQj2TLQ6roDcX0YQDWvUnVgsVOl0VnUvyT/VBdCUuQYDHobZsPEuQsoEqmPA44KS/Gl0oyKqf+I8UPtRgw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/performance" "0.7.0" + "@firebase/performance-types" "0.2.3" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/performance-types@0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.2.3.tgz#5ce64e90fa20ab5561f8b62a305010cf9fab86fb" + integrity sha512-IgkyTz6QZVPAq8GSkLYJvwSLr3LS9+V6vNPQr0x4YozZJiLF5jYixj0amDtATf1X0EtYHqoPO48a9ija8GocxQ== + +"@firebase/performance@0.7.0": + version "0.7.0" + resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.7.0.tgz#1cd82039f7e06e0f059287dfa21705c68ec9a691" + integrity sha512-L91PwYuiJdKXKSRqsWNicvTppAJVzKjye03UlegeD6TkpKjb93T8AmJ9B0Mt0bcWHCNtnnRBCdSCvD2U9GZDjw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/installations" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + web-vitals "^4.2.4" + +"@firebase/remote-config-compat@0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@firebase/remote-config-compat/-/remote-config-compat-0.2.12.tgz#ae0b597b3228deef0e3c6b2c6e631f19213eca4c" + integrity sha512-91jLWPtubIuPBngg9SzwvNCWzhMLcyBccmt7TNZP+y1cuYFNOWWHKUXQ3IrxCLB7WwLqQaEu7fTDAjHsTyBsSw== + dependencies: + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/remote-config" "0.5.0" + "@firebase/remote-config-types" "0.4.0" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/remote-config-types@0.4.0": version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/analytics-types/-/analytics-types-0.4.0.tgz#d6716f9fa36a6e340bc0ecfe68af325aa6f60508" - integrity sha512-Jj2xW+8+8XPfWGkv9HPv/uR+Qrmq37NPYT352wf7MvE9LrstpLVmFg3LqG6MCRr5miLAom5sen2gZ+iOhVDeRA== + resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.4.0.tgz#91b9a836d5ca30ced68c1516163b281fbb544537" + integrity sha512-7p3mRE/ldCNYt8fmWMQ/MSGRmXYlJ15Rvs9Rk17t8p0WwZDbeK7eRmoI1tvCPaDzn9Oqh+yD6Lw+sGLsLg4kKg== -"@firebase/analytics@0.6.8": - version "0.6.8" - resolved "https://registry.yarnpkg.com/@firebase/analytics/-/analytics-0.6.8.tgz#ec69a8673df2e0381bdebc892d28448e2d97ee8a" - integrity sha512-cPbQIQo3uqpImtiGIB42F9s9fw8cPseCj1ZMR3VshL6u/6kzC9ptOpgg8PMCLOgZvBwC993LbT1UOTuufTd49Q== - dependencies: - "@firebase/analytics-types" "0.4.0" - "@firebase/component" "0.4.0" - "@firebase/installations" "0.4.24" - "@firebase/logger" "0.2.6" - "@firebase/util" "0.4.1" - tslib "^2.1.0" - -"@firebase/app-types@0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@firebase/app-types/-/app-types-0.6.2.tgz#8578cb1061a83ced4570188be9e225d54e0f27fb" - integrity sha512-2VXvq/K+n8XMdM4L2xy5bYp2ZXMawJXluUIDzUBvMthVR+lhxK4pfFiqr1mmDbv9ydXvEAuFsD+6DpcZuJcSSw== - -"@firebase/app@0.6.19": - version "0.6.19" - resolved "https://registry.yarnpkg.com/@firebase/app/-/app-0.6.19.tgz#40fe266889436ab0fcf035ee5a415db7339c1936" - integrity sha512-qDimGNoukCuWvGYcsosGV2tOKbJ98RuRHLoK2j4t73TupY6rH+4QeR3tf5E3q1gZ5mtaFZloXc6aZWWOgtfwoQ== - dependencies: - "@firebase/app-types" "0.6.2" - "@firebase/component" "0.4.0" - "@firebase/logger" "0.2.6" - "@firebase/util" "0.4.1" - dom-storage "2.1.0" - tslib "^2.1.0" - xmlhttprequest "1.8.0" - -"@firebase/auth-interop-types@0.1.5": - version "0.1.5" - resolved "https://registry.yarnpkg.com/@firebase/auth-interop-types/-/auth-interop-types-0.1.5.tgz#9fc9bd7c879f16b8d1bb08373a0f48c3a8b74557" - integrity sha512-88h74TMQ6wXChPA6h9Q3E1Jg6TkTHep2+k63OWg3s0ozyGVMeY+TTOti7PFPzq5RhszQPQOoCi59es4MaRvgCw== - -"@firebase/auth-types@0.10.2": - version "0.10.2" - resolved "https://registry.yarnpkg.com/@firebase/auth-types/-/auth-types-0.10.2.tgz#3fad953380c447b7545122430a4c7a9bc8355001" - integrity sha512-0GMWVWh5TBCYIQfVerxzDsuvhoFpK0++O9LtP3FWkwYo7EAxp6w0cftAg/8ntU1E5Wg56Ry0b6ti/YGP6g0jlg== - -"@firebase/auth@0.16.4": - version "0.16.4" - resolved "https://registry.yarnpkg.com/@firebase/auth/-/auth-0.16.4.tgz#6249d80f1e974b0db122930ae9fac885eccead5c" - integrity sha512-zgHPK6/uL6+nAyG9zqammHTF1MQpAN7z/jVRLYkDZS4l81H08b2SzApLbRfW/fmy665xqb5MK7sVH0V1wsiCNw== - dependencies: - "@firebase/auth-types" "0.10.2" - -"@firebase/component@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/component/-/component-0.4.0.tgz#90baa455d75160c8a5134b3e9d642df11f0ac818" - integrity sha512-L7kLKpW1v5qxPfIhx/VqHuVi+vr5IcnDS4zCJFb+/eYe23i6czSOWR1urAoJ4r42Dk0XB5kDt6Idojdd9BGMEA== - dependencies: - "@firebase/util" "0.4.1" - tslib "^2.1.0" - -"@firebase/database-types@0.7.1": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@firebase/database-types/-/database-types-0.7.1.tgz#3505e3e8d57e94a3ce6038649a95afe0af040757" - integrity sha512-465ceJXSMqFFMnL2lxYx+YhYajcyk+VpGiXf9T6KNME0lKne5hYuqYr7XmS8/sTeyV0huhmTb8K1nxlA7hiPOg== - dependencies: - "@firebase/app-types" "0.6.2" - -"@firebase/database@0.9.8": - version "0.9.8" - resolved "https://registry.yarnpkg.com/@firebase/database/-/database-0.9.8.tgz#244eb897033ecacfc4a1fa5f031cda9b5e4009e5" - integrity sha512-bqZUDR6jIQSQcY7oZVGmI/Bg7SfmUUW/toaZBCfaddWAnniBthaa8o0Hyv1ypPxjEZCu1CfPQwtpMhlSTjG0tA== - dependencies: - "@firebase/auth-interop-types" "0.1.5" - "@firebase/component" "0.4.0" - "@firebase/database-types" "0.7.1" - "@firebase/logger" "0.2.6" - "@firebase/util" "0.4.1" - faye-websocket "0.11.3" - tslib "^2.1.0" - -"@firebase/firestore-types@2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@firebase/firestore-types/-/firestore-types-2.2.0.tgz#9a3f3f2906232c3b4a726d988a6ef077f35f9093" - integrity sha512-5kZZtQ32FIRJP1029dw+ZVNRCclKOErHv1+Xn0pw/5Fq3dxroA/ZyFHqDu+uV52AyWHhNLjCqX43ibm4YqOzRw== - -"@firebase/firestore@2.2.3": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@firebase/firestore/-/firestore-2.2.3.tgz#e76d9191c48ef4c51ae73c2fcce7d547be2a8c17" - integrity sha512-efJxJahP9936QlIHeATvatCO4c3UEk6nz7pc812xxkgTVezkg8K66IDUe0fncV70zbDrIyxUIl8yRcxhXytiGw== - dependencies: - "@firebase/component" "0.4.0" - "@firebase/firestore-types" "2.2.0" - "@firebase/logger" "0.2.6" - "@firebase/util" "0.4.1" - "@firebase/webchannel-wrapper" "0.4.1" - "@grpc/grpc-js" "^1.0.0" - "@grpc/proto-loader" "^0.5.0" - node-fetch "2.6.1" - tslib "^2.1.0" - -"@firebase/functions-types@0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@firebase/functions-types/-/functions-types-0.4.0.tgz#0b789f4fe9a9c0b987606c4da10139345b40f6b9" - integrity sha512-3KElyO3887HNxtxNF1ytGFrNmqD+hheqjwmT3sI09FaDCuaxGbOnsXAXH2eQ049XRXw9YQpHMgYws/aUNgXVyQ== - -"@firebase/functions@0.6.6": - version "0.6.6" - resolved "https://registry.yarnpkg.com/@firebase/functions/-/functions-0.6.6.tgz#06b786e68b269a615fc83598d99cda7b11ec740e" - integrity sha512-cvZiqcL3X7+6ObkwcRUV54iFHaVxVgio2t610p2qwjzMxyYfiHWDA+GwKPioObDWqyXmNtkU8cw2WLoGf46cnA== - dependencies: - "@firebase/component" "0.4.0" - "@firebase/functions-types" "0.4.0" - "@firebase/messaging-types" "0.5.0" - node-fetch "2.6.1" - tslib "^2.1.0" - -"@firebase/installations-types@0.3.4": - version "0.3.4" - resolved "https://registry.yarnpkg.com/@firebase/installations-types/-/installations-types-0.3.4.tgz#589a941d713f4f64bf9f4feb7f463505bab1afa2" - integrity sha512-RfePJFovmdIXb6rYwtngyxuEcWnOrzdZd9m7xAW0gRxDIjBT20n3BOhjpmgRWXo/DAxRmS7bRjWAyTHY9cqN7Q== - -"@firebase/installations@0.4.24": - version "0.4.24" - resolved "https://registry.yarnpkg.com/@firebase/installations/-/installations-0.4.24.tgz#acaf3d48c156f3a3a5ddb53e8e8c63a89fce2f55" - integrity sha512-cMWI3IfnmdJ4SzPav56yaHwEhpPPl5b03AVtv7AeKnmDZ61eBqPzEnYSL8Iso73/FeKpr8BYcZelAx0EyxcJ3Q== - dependencies: - "@firebase/component" "0.4.0" - "@firebase/installations-types" "0.3.4" - "@firebase/util" "0.4.1" - idb "3.0.2" - tslib "^2.1.0" - -"@firebase/logger@0.2.6": - version "0.2.6" - resolved "https://registry.yarnpkg.com/@firebase/logger/-/logger-0.2.6.tgz#3aa2ca4fe10327cabf7808bd3994e88db26d7989" - integrity sha512-KIxcUvW/cRGWlzK9Vd2KB864HlUnCfdTH0taHE0sXW5Xl7+W68suaeau1oKNEqmc3l45azkd4NzXTCWZRZdXrw== - -"@firebase/messaging-types@0.5.0": +"@firebase/remote-config@0.5.0": version "0.5.0" - resolved "https://registry.yarnpkg.com/@firebase/messaging-types/-/messaging-types-0.5.0.tgz#c5d0ef309ced1758fda93ef3ac70a786de2e73c4" - integrity sha512-QaaBswrU6umJYb/ZYvjR5JDSslCGOH6D9P136PhabFAHLTR4TWjsaACvbBXuvwrfCXu10DtcjMxqfhdNIB1Xfg== - -"@firebase/messaging@0.7.8": - version "0.7.8" - resolved "https://registry.yarnpkg.com/@firebase/messaging/-/messaging-0.7.8.tgz#90119a2f1cd5055fd61206732024e0281de80616" - integrity sha512-rXYvVQPZd+rCMV7+/FgpvsHad0HuEhoyH5OQgYxeBgSsgFn6mOyvAtYcoCFjPTvTV5eyGH1I4hQtNOyY8zVzzg== + resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.5.0.tgz#30212fa77adba8a62fc6408eb32122147ae80790" + integrity sha512-weiEbpBp5PBJTHUWR4GwI7ZacaAg68BKha5QnZ8Go65W4oQjEWqCW/rfskABI/OkrGijlL3CUmCB/SA6mVo0qA== dependencies: - "@firebase/component" "0.4.0" - "@firebase/installations" "0.4.24" - "@firebase/messaging-types" "0.5.0" - "@firebase/util" "0.4.1" - idb "3.0.2" + "@firebase/component" "0.6.12" + "@firebase/installations" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" tslib "^2.1.0" -"@firebase/performance-types@0.0.13": - version "0.0.13" - resolved "https://registry.yarnpkg.com/@firebase/performance-types/-/performance-types-0.0.13.tgz#58ce5453f57e34b18186f74ef11550dfc558ede6" - integrity sha512-6fZfIGjQpwo9S5OzMpPyqgYAUZcFzZxHFqOyNtorDIgNXq33nlldTL/vtaUZA8iT9TT5cJlCrF/jthKU7X21EA== - -"@firebase/performance@0.4.10": - version "0.4.10" - resolved "https://registry.yarnpkg.com/@firebase/performance/-/performance-0.4.10.tgz#c78ed1c15c26884eae23edf1498e930bb729b51f" - integrity sha512-gyAOd9Z/GVlLE5V8U5pVQDZpjr4Msdx5yJr7oQE/xkh6dNZGuYp5qJh1pAmJs2ZI8eMTs+j2bXJEMYk6w7ehRg== +"@firebase/storage-compat@0.3.16": + version "0.3.16" + resolved "https://registry.yarnpkg.com/@firebase/storage-compat/-/storage-compat-0.3.16.tgz#49ab9c572bb172e6335c099d95a48bee0f17cc98" + integrity sha512-EeMuok/s0r938lEomia8XILEqSYULm7HcYZ/GTZLDWur0kMf2ktuPVZiTdRiwEV3Iki7FtQO5txrQ/0pLRVLAw== dependencies: - "@firebase/component" "0.4.0" - "@firebase/installations" "0.4.24" - "@firebase/logger" "0.2.6" - "@firebase/performance-types" "0.0.13" - "@firebase/util" "0.4.1" + "@firebase/component" "0.6.12" + "@firebase/storage" "0.13.6" + "@firebase/storage-types" "0.8.3" + "@firebase/util" "1.10.3" tslib "^2.1.0" -"@firebase/polyfill@0.3.36": - version "0.3.36" - resolved "https://registry.yarnpkg.com/@firebase/polyfill/-/polyfill-0.3.36.tgz#c057cce6748170f36966b555749472b25efdb145" - integrity sha512-zMM9oSJgY6cT2jx3Ce9LYqb0eIpDE52meIzd/oe/y70F+v9u1LDqk5kUF5mf16zovGBWMNFmgzlsh6Wj0OsFtg== - dependencies: - core-js "3.6.5" - promise-polyfill "8.1.3" - whatwg-fetch "2.0.4" +"@firebase/storage-types@0.8.3": + version "0.8.3" + resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.8.3.tgz#2531ef593a3452fc12c59117195d6485c6632d3d" + integrity sha512-+Muk7g9uwngTpd8xn9OdF/D48uiQ7I1Fae7ULsWPuKoCH3HU7bfFPhxtJYzyhjdniowhuDpQcfPmuNRAqZEfvg== -"@firebase/remote-config-types@0.1.9": - version "0.1.9" - resolved "https://registry.yarnpkg.com/@firebase/remote-config-types/-/remote-config-types-0.1.9.tgz#fe6bbe4d08f3b6e92fce30e4b7a9f4d6a96d6965" - integrity sha512-G96qnF3RYGbZsTRut7NBX0sxyczxt1uyCgXQuH/eAfUCngxjEGcZQnBdy6mvSdqdJh5mC31rWPO4v9/s7HwtzA== - -"@firebase/remote-config@0.1.35": - version "0.1.35" - resolved "https://registry.yarnpkg.com/@firebase/remote-config/-/remote-config-0.1.35.tgz#792b6d9e2d8e5db0a883ee53579629c2412ae1f5" - integrity sha512-szhu48LTyb46S33hUR3sC4kiykEoc+B5M7HWWHhjp7Ne+524G8pH/9+/r9ZA8eVj48c5cihXyQKQ/6yCQotnUA== +"@firebase/storage@0.13.6": + version "0.13.6" + resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.13.6.tgz#322def6cda335df991ce9787aa5ef5650db901bd" + integrity sha512-BEJLYQzVgAoglRl5VRIRZ91RRBZgS/O37/PSGQJBYNuoLmFZUrtwrlLTOAwG776NlO9VQR+K2j15/36Lr2EqHA== dependencies: - "@firebase/component" "0.4.0" - "@firebase/installations" "0.4.24" - "@firebase/logger" "0.2.6" - "@firebase/remote-config-types" "0.1.9" - "@firebase/util" "0.4.1" + "@firebase/component" "0.6.12" + "@firebase/util" "1.10.3" tslib "^2.1.0" -"@firebase/storage-types@0.3.13": - version "0.3.13" - resolved "https://registry.yarnpkg.com/@firebase/storage-types/-/storage-types-0.3.13.tgz#cd43e939a2ab5742e109eb639a313673a48b5458" - integrity sha512-pL7b8d5kMNCCL0w9hF7pr16POyKkb3imOW7w0qYrhBnbyJTdVxMWZhb0HxCFyQWC0w3EiIFFmxoz8NTFZDEFog== - -"@firebase/storage@0.4.7": - version "0.4.7" - resolved "https://registry.yarnpkg.com/@firebase/storage/-/storage-0.4.7.tgz#541a2d96af6da9c345b190858345c1106650fce0" - integrity sha512-5DFb+VncNBomPzpzYqJzzJjfiZhOWg0FHTBkw90K9OdE2wUfKqzhhbIAjyaXcu+2YLB2hjft8BKbjQfV5BDFnw== - dependencies: - "@firebase/component" "0.4.0" - "@firebase/storage-types" "0.3.13" - "@firebase/util" "0.4.1" - tslib "^2.1.0" - -"@firebase/util@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@firebase/util/-/util-0.4.1.tgz#fe76cf0238901dc5455b341cf02e298e7bf68df4" - integrity sha512-XhYCOwq4AH+YeQBEnDQvigz50WiiBU4LnJh2+//VMt4J2Ybsk0eTgUHNngUzXsmp80EJrwal3ItODg55q1ajWg== +"@firebase/util@1.10.3": + version "1.10.3" + resolved "https://registry.yarnpkg.com/@firebase/util/-/util-1.10.3.tgz#63fc5fea7b36236219c4875731597494416678d1" + integrity sha512-wfoF5LTy0m2ufUapV0ZnpcGQvuavTbJ5Qr1Ze9OJGL70cSMvhDyjS4w2121XdA3lGZSTOsDOyGhpoDtYwck85A== dependencies: tslib "^2.1.0" -"@firebase/webchannel-wrapper@0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-0.4.1.tgz#600f2275ff54739ad5ac0102f1467b8963cd5f71" - integrity sha512-0yPjzuzGMkW1GkrC8yWsiN7vt1OzkMIi9HgxRmKREZl2wnNPOKo/yScTjXf/O57HM8dltqxPF6jlNLFVtc2qdw== +"@firebase/vertexai@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@firebase/vertexai/-/vertexai-1.0.4.tgz#1966ddfb32492d004f595f639e57162d488c84ba" + integrity sha512-Nkf/r4u166b4Id6zrrW0Qtg1KyZpQvvYchtkebamnHtIfY+Qnt51I/sx4Saos/WrmO8SnrSU850LfmJ7pehYXg== + dependencies: + "@firebase/app-check-interop-types" "0.3.3" + "@firebase/component" "0.6.12" + "@firebase/logger" "0.4.4" + "@firebase/util" "1.10.3" + tslib "^2.1.0" + +"@firebase/webchannel-wrapper@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@firebase/webchannel-wrapper/-/webchannel-wrapper-1.0.3.tgz#a73bab8eb491d7b8b7be2f0e6c310647835afe83" + integrity sha512-2xCRM9q9FlzGZCdgDMJwc0gyUkWFtkosy7Xxr6sFgQwn+wMNIWd7xIvYNauU1r64B5L5rsGKy/n9TKJ0aAFeqQ== "@floating-ui/core@^0.7.3": version "0.7.3" @@ -2159,23 +2326,15 @@ "@floating-ui/dom" "^0.5.3" use-isomorphic-layout-effect "^1.1.1" -"@grpc/grpc-js@^1.0.0": - version "1.10.8" - resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.10.8.tgz#99787785cd8335be861afd1cd485ae9f058e4484" - integrity sha512-vYVqYzHicDqyKB+NQhAc54I1QWCBLCrYG6unqOIcBTHx+7x8C9lcoLj3KVJXs2VB4lUbpWY+Kk9NipcbXYWmvg== +"@grpc/grpc-js@~1.9.0": + version "1.9.15" + resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" + integrity sha512-nqE7Hc0AzI+euzUwDAy0aY5hCp10r734gMGRdU+qOPX0XSceI2ULrcXB5U2xSc5VkWwalCj4M7GzCAygZl2KoQ== dependencies: - "@grpc/proto-loader" "^0.7.13" - "@js-sdsl/ordered-map" "^4.4.2" + "@grpc/proto-loader" "^0.7.8" + "@types/node" ">=12.12.47" -"@grpc/proto-loader@^0.5.0": - version "0.5.6" - resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.5.6.tgz#1dea4b8a6412b05e2d58514d507137b63a52a98d" - integrity sha512-DT14xgw3PSzPxwS13auTEwxhMMOoz33DPUKNtmYK/QYbBSpLXJy78FGGs5yVoxVobEqPm4iW9MOIoz0A3bLTRQ== - dependencies: - lodash.camelcase "^4.3.0" - protobufjs "^6.8.6" - -"@grpc/proto-loader@^0.7.13": +"@grpc/proto-loader@^0.7.8": version "0.7.13" resolved "https://registry.yarnpkg.com/@grpc/proto-loader/-/proto-loader-0.7.13.tgz#f6a44b2b7c9f7b609f5748c6eac2d420e37670cf" integrity sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw== @@ -2287,11 +2446,6 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@js-sdsl/ordered-map@^4.4.2": - version "4.4.2" - resolved "https://registry.yarnpkg.com/@js-sdsl/ordered-map/-/ordered-map-4.4.2.tgz#9299f82874bab9e4c7f9c48d865becbfe8d6907c" - integrity sha512-iUKgm52T8HOE/makSxjqoWhe95ZJA1/G1sYsGev2JDKUSS14KAgg1LHb+Ba+IPow0xflbnSkOsZcO08C7w1gYw== - "@next/env@14.1.4": version "14.1.4" resolved "https://registry.yarnpkg.com/@next/env/-/env-14.1.4.tgz#432e80651733fbd67230bf262aee28be65252674" @@ -3179,11 +3333,6 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7" integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ== -"@types/long@^4.0.1": - version "4.0.2" - resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" - integrity sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA== - "@types/mdast@^3.0.0": version "3.0.15" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.15.tgz#49c524a263f30ffa28b71ae282f813ed000ab9f5" @@ -3203,6 +3352,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@>=12.12.47": + version "22.13.2" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.2.tgz#6f401c5ccadac75354f5652128e9fcc3b0cf23b7" + integrity sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg== + dependencies: + undici-types "~6.20.0" + "@types/pako@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/pako/-/pako-1.0.3.tgz#2e61c2b02020b5f44e2e5e946dfac74f4ec33c58" @@ -4740,11 +4896,6 @@ core-js-compat@^3.31.0, core-js-compat@^3.36.1: dependencies: browserslist "^4.23.0" -core-js@3.6.5: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" - integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== - core-js@^2.4.0: version "2.6.12" resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" @@ -5386,11 +5537,6 @@ dom-serializer@^1.0.1: domhandler "^4.2.0" entities "^2.0.0" -dom-storage@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/dom-storage/-/dom-storage-2.1.0.tgz#00fb868bc9201357ea243c7bcfd3304c1e34ea39" - integrity sha512-g6RpyWXzl0RR6OTElHKBl7nwnK87GUyZMYC7JWsB/IA73vpqK2K6LT39x4VepLxlSsWBFrPVLnsSR5Jyty0+2Q== - domelementtype@^2.0.1, domelementtype@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" @@ -6237,10 +6383,10 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" -faye-websocket@0.11.3: - version "0.11.3" - resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" - integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== dependencies: websocket-driver ">=0.5.1" @@ -6307,25 +6453,39 @@ find-up@^4.0.0: locate-path "^5.0.0" path-exists "^4.0.0" -firebase@8.3.3: - version "8.3.3" - resolved "https://registry.yarnpkg.com/firebase/-/firebase-8.3.3.tgz#21d8fb8eec2c43b0d8f98ab6bda5535b7454fa54" - integrity sha512-eRkW7bD25aevlGwtCEsP53xBo5/Fi4wkxvfvmDW6R2/oSHjy+hVLkQILP4kQFFXgFL0LBjxIPOchXoQ5MUbTCA== +firebase@11.3.1: + version "11.3.1" + resolved "https://registry.yarnpkg.com/firebase/-/firebase-11.3.1.tgz#1507b2b1e3af17418fbe009e82d7bc30a6b5117c" + integrity sha512-P4YVFM0Bm2d8aO61SCEMF8E1pYgieGLrmr/LFw7vs6sAMebwuwHt+Wug+1qL2fhAHWPwpWbCLsdJH8NQ+4Sw8Q== dependencies: - "@firebase/analytics" "0.6.8" - "@firebase/app" "0.6.19" - "@firebase/app-types" "0.6.2" - "@firebase/auth" "0.16.4" - "@firebase/database" "0.9.8" - "@firebase/firestore" "2.2.3" - "@firebase/functions" "0.6.6" - "@firebase/installations" "0.4.24" - "@firebase/messaging" "0.7.8" - "@firebase/performance" "0.4.10" - "@firebase/polyfill" "0.3.36" - "@firebase/remote-config" "0.1.35" - "@firebase/storage" "0.4.7" - "@firebase/util" "0.4.1" + "@firebase/analytics" "0.10.11" + "@firebase/analytics-compat" "0.2.17" + "@firebase/app" "0.11.1" + "@firebase/app-check" "0.8.11" + "@firebase/app-check-compat" "0.3.18" + "@firebase/app-compat" "0.2.50" + "@firebase/app-types" "0.9.3" + "@firebase/auth" "1.9.0" + "@firebase/auth-compat" "0.5.18" + "@firebase/data-connect" "0.3.0" + "@firebase/database" "1.0.12" + "@firebase/database-compat" "2.0.3" + "@firebase/firestore" "4.7.8" + "@firebase/firestore-compat" "0.3.43" + "@firebase/functions" "0.12.2" + "@firebase/functions-compat" "0.3.19" + "@firebase/installations" "0.6.12" + "@firebase/installations-compat" "0.2.12" + "@firebase/messaging" "0.12.16" + "@firebase/messaging-compat" "0.2.16" + "@firebase/performance" "0.7.0" + "@firebase/performance-compat" "0.2.13" + "@firebase/remote-config" "0.5.0" + "@firebase/remote-config-compat" "0.2.12" + "@firebase/storage" "0.13.6" + "@firebase/storage-compat" "0.3.16" + "@firebase/util" "1.10.3" + "@firebase/vertexai" "1.0.4" flat-cache@^3.0.4: version "3.2.0" @@ -6820,12 +6980,7 @@ idb-keyval@6.0.3: dependencies: safari-14-idb-fix "^3.0.0" -idb@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/idb/-/idb-3.0.2.tgz#c8e9122d5ddd40f13b60ae665e4862f8b13fa384" - integrity sha512-+FLa/0sTXqyux0o6C+i2lOR0VoS60LU/jzUo5xjfY6+7sEEgy4Gz1O7yFBXvjd7N0NyIGWIRg8DcQSLEG+VSPw== - -idb@^7.0.1: +idb@7.1.1, idb@^7.0.1: version "7.1.1" resolved "https://registry.yarnpkg.com/idb/-/idb-7.1.1.tgz#d910ded866d32c7ced9befc5bfdf36f572ced72b" integrity sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ== @@ -7652,11 +7807,6 @@ log-update@^4.0.0: slice-ansi "^4.0.0" wrap-ansi "^6.2.0" -long@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/long/-/long-4.0.0.tgz#9a7b71cfb7d361a194ea555241c92f7468d5bf28" - integrity sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA== - long@^5.0.0: version "5.2.3" resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" @@ -8216,11 +8366,6 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" -node-fetch@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" - integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== - node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -8763,11 +8908,6 @@ progress@2.0.3, progress@^2.0.0: resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== -promise-polyfill@8.1.3: - version "8.1.3" - resolved "https://registry.yarnpkg.com/promise-polyfill/-/promise-polyfill-8.1.3.tgz#8c99b3cf53f3a91c68226ffde7bde81d7f904116" - integrity sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g== - prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -8777,25 +8917,6 @@ prop-types@^15.8.1: object-assign "^4.1.1" react-is "^16.13.1" -protobufjs@^6.8.6: - version "6.11.4" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.4.tgz#29a412c38bf70d89e537b6d02d904a6f448173aa" - integrity sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw== - dependencies: - "@protobufjs/aspromise" "^1.1.2" - "@protobufjs/base64" "^1.1.2" - "@protobufjs/codegen" "^2.0.4" - "@protobufjs/eventemitter" "^1.1.0" - "@protobufjs/fetch" "^1.1.0" - "@protobufjs/float" "^1.0.2" - "@protobufjs/inquire" "^1.1.0" - "@protobufjs/path" "^1.1.2" - "@protobufjs/pool" "^1.1.0" - "@protobufjs/utf8" "^1.1.0" - "@types/long" "^4.0.1" - "@types/node" ">=13.7.0" - long "^4.0.0" - protobufjs@^7.2.5: version "7.3.0" resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.0.tgz#a32ec0422c039798c41a0700306a6e305b9cb32c" @@ -10167,6 +10288,11 @@ undici-types@~5.26.4: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.20.0: + version "6.20.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" + integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== + unicode-canonical-property-names-ecmascript@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" @@ -10513,6 +10639,11 @@ wawoff2@2.0.1: dependencies: argparse "^2.0.1" +web-vitals@^4.2.4: + version "4.2.4" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" + integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== + web-worker@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" @@ -10671,11 +10802,6 @@ whatwg-encoding@^2.0.0: dependencies: iconv-lite "0.6.3" -whatwg-fetch@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== - whatwg-mimetype@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz#5fa1a7623867ff1af6ca3dc72ad6b8a4208beba7" @@ -11031,11 +11157,6 @@ xmlhttprequest-ssl@~2.0.0: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== - y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" From 9ee0b8ffcbd3664a47748a93262860321a203821 Mon Sep 17 00:00:00 2001 From: Abhinav Pant <67090539+abhitrueprogrammer@users.noreply.github.com> Date: Thu, 13 Feb 2025 18:37:44 +0530 Subject: [PATCH 23/51] Enhancement: grouped together Undo and Redo buttons on mobile (#9109) * bugfix: put the redo and undo button under the same div so that they look grouped together * fixed the position of the redo and undo buttons to the right --- packages/excalidraw/components/MobileMenu.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/excalidraw/components/MobileMenu.tsx b/packages/excalidraw/components/MobileMenu.tsx index e0b8fb2c0..56408d50a 100644 --- a/packages/excalidraw/components/MobileMenu.tsx +++ b/packages/excalidraw/components/MobileMenu.tsx @@ -145,12 +145,14 @@ export const MobileMenu = ({
{actionManager.renderAction("toggleEditMenu")} - {actionManager.renderAction("undo")} - {actionManager.renderAction("redo")} {actionManager.renderAction( appState.multiElement ? "finalize" : "duplicateSelection", )} {actionManager.renderAction("deleteSelectedElements")} +
+ {actionManager.renderAction("undo")} + {actionManager.renderAction("redo")} +
); }; From 31e8476c78aca31df1342dc26903e42301d2c3fd Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Tue, 25 Feb 2025 19:18:42 +0100 Subject: [PATCH 24/51] chore: upgrade to react@19 (#9182) --- dev-docs/package.json | 4 +- examples/excalidraw/package.json | 4 +- examples/excalidraw/with-nextjs/package.json | 8 +- .../with-script-in-browser/package.json | 4 +- excalidraw-app/collab/CollabError.tsx | 6 +- excalidraw-app/components/DebugCanvas.tsx | 55 +- excalidraw-app/package.json | 4 +- package.json | 11 +- packages/excalidraw/components/ButtonIcon.tsx | 1 + .../excalidraw/components/ButtonIconCycle.tsx | 1 + .../components/ButtonIconSelect.tsx | 1 + .../components/FontPicker/FontPickerList.tsx | 1 + .../FontPicker/keyboardNavHandlers.ts | 2 +- packages/excalidraw/components/HelpDialog.tsx | 1 + packages/excalidraw/components/IconPicker.tsx | 1 + .../excalidraw/components/MagicButton.tsx | 5 +- packages/excalidraw/components/MobileMenu.tsx | 1 + .../excalidraw/components/Sidebar/common.ts | 1 + packages/excalidraw/components/Stack.tsx | 1 - .../components/TTDDialog/TTDDialogOutput.tsx | 2 +- .../components/TTDDialog/TTDDialogTrigger.tsx | 1 + .../excalidraw/components/TTDDialog/common.ts | 4 +- .../components/canvases/InteractiveCanvas.tsx | 2 +- .../dropdownMenu/DropdownMenuItem.tsx | 1 + .../dropdownMenu/DropdownMenuItemContent.tsx | 1 + .../dropdownMenu/DropdownMenuItemLink.tsx | 1 + .../welcome-screen/WelcomeScreen.Center.tsx | 1 + .../excalidraw/element/flowchart.test.tsx | 5 +- .../excalidraw/element/textWysiwyg.test.tsx | 11 +- packages/excalidraw/fonts/FontMetadata.ts | 1 + packages/excalidraw/global.d.ts | 12 +- packages/excalidraw/hooks/useOutsideClick.ts | 2 +- .../excalidraw/hooks/useScrollPosition.ts | 2 +- packages/excalidraw/package.json | 8 +- packages/excalidraw/tests/App.test.tsx | 6 +- packages/excalidraw/tests/align.test.tsx | 6 +- packages/excalidraw/tests/clipboard.test.tsx | 10 +- .../excalidraw/tests/contextmenu.test.tsx | 5 +- .../excalidraw/tests/cropElement.test.tsx | 6 +- .../data/__snapshots__/restore.test.ts.snap | 15 +- .../excalidraw/tests/data/reconcile.test.ts | 26 +- .../excalidraw/tests/data/restore.test.ts | 2 + packages/excalidraw/tests/dragCreate.test.tsx | 5 +- .../excalidraw/tests/elementLocking.test.tsx | 5 +- packages/excalidraw/tests/flip.test.tsx | 5 +- packages/excalidraw/tests/helpers/api.ts | 9 +- .../tests/linearElementEditor.test.tsx | 12 +- packages/excalidraw/tests/move.test.tsx | 6 +- .../tests/multiPointCreate.test.tsx | 5 +- .../excalidraw/tests/regressionTests.test.tsx | 5 +- packages/excalidraw/tests/resize.test.tsx | 5 +- packages/excalidraw/tests/rotate.test.tsx | 5 +- packages/excalidraw/tests/selection.test.tsx | 5 +- packages/excalidraw/tests/test-utils.ts | 10 +- packages/excalidraw/tests/zindex.test.tsx | 6 +- packages/excalidraw/types.ts | 1 + tsconfig.json | 1 + yarn.lock | 5275 ++++++++--------- 58 files changed, 2774 insertions(+), 2828 deletions(-) diff --git a/dev-docs/package.json b/dev-docs/package.json index b3e8d7bb3..da2e5e48a 100644 --- a/dev-docs/package.json +++ b/dev-docs/package.json @@ -23,8 +23,8 @@ "clsx": "^1.2.1", "docusaurus-plugin-sass": "0.2.3", "prism-react-renderer": "^1.3.5", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "19.0.0", + "react-dom": "19.0.0", "sass": "1.57.1" }, "devDependencies": { diff --git a/examples/excalidraw/package.json b/examples/excalidraw/package.json index fe48d5532..0d720b537 100644 --- a/examples/excalidraw/package.json +++ b/examples/excalidraw/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "19.0.0", + "react-dom": "19.0.0", "@excalidraw/excalidraw": "*" }, "devDependencies": { diff --git a/examples/excalidraw/with-nextjs/package.json b/examples/excalidraw/with-nextjs/package.json index 335f87db7..9d96becdd 100644 --- a/examples/excalidraw/with-nextjs/package.json +++ b/examples/excalidraw/with-nextjs/package.json @@ -13,13 +13,13 @@ "dependencies": { "@excalidraw/excalidraw": "*", "next": "14.1", - "react": "18.2.0", - "react-dom": "18.2.0" + "react": "19.0.0", + "react-dom": "19.0.0" }, "devDependencies": { "@types/node": "^20", - "@types/react": "18.2.0", - "@types/react-dom": "18.2.0", + "@types/react": "19.0.10", + "@types/react-dom": "19.0.4", "path2d-polyfill": "2.0.1", "typescript": "^5" } diff --git a/examples/excalidraw/with-script-in-browser/package.json b/examples/excalidraw/with-script-in-browser/package.json index 6e3d09fd1..4f3583ab8 100644 --- a/examples/excalidraw/with-script-in-browser/package.json +++ b/examples/excalidraw/with-script-in-browser/package.json @@ -3,8 +3,8 @@ "version": "1.0.0", "private": true, "dependencies": { - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "19.0.0", + "react-dom": "19.0.0", "@excalidraw/excalidraw": "*" }, "devDependencies": { diff --git a/excalidraw-app/collab/CollabError.tsx b/excalidraw-app/collab/CollabError.tsx index 10ff1e1d0..ea9159fcd 100644 --- a/excalidraw-app/collab/CollabError.tsx +++ b/excalidraw-app/collab/CollabError.tsx @@ -19,16 +19,16 @@ export const collabErrorIndicatorAtom = atom({ const CollabError = ({ collabError }: { collabError: ErrorIndicator }) => { const [isAnimating, setIsAnimating] = useState(false); - const clearAnimationRef = useRef(); + const clearAnimationRef = useRef(0); useEffect(() => { setIsAnimating(true); - clearAnimationRef.current = setTimeout(() => { + clearAnimationRef.current = window.setTimeout(() => { setIsAnimating(false); }, 1000); return () => { - clearTimeout(clearAnimationRef.current); + window.clearTimeout(clearAnimationRef.current); }; }, [collabError.message, collabError.nonce]); diff --git a/excalidraw-app/components/DebugCanvas.tsx b/excalidraw-app/components/DebugCanvas.tsx index 471167989..fe2c617fc 100644 --- a/excalidraw-app/components/DebugCanvas.tsx +++ b/excalidraw-app/components/DebugCanvas.tsx @@ -1,4 +1,4 @@ -import { forwardRef, useCallback, useImperativeHandle, useRef } from "react"; +import { useCallback, useImperativeHandle, useRef } from "react"; import { type AppState } from "../../packages/excalidraw/types"; import { throttleRAF } from "../../packages/excalidraw/utils"; import { @@ -276,36 +276,35 @@ export const DebugFooter = ({ onChange }: { onChange: () => void }) => { interface DebugCanvasProps { appState: AppState; scale: number; + ref?: React.Ref; } -const DebugCanvas = forwardRef( - ({ appState, scale }, ref) => { - const { width, height } = appState; +const DebugCanvas = ({ appState, scale, ref }: DebugCanvasProps) => { + const { width, height } = appState; - const canvasRef = useRef(null); - useImperativeHandle( - ref, - () => canvasRef.current, - [canvasRef], - ); + const canvasRef = useRef(null); + useImperativeHandle( + ref, + () => canvasRef.current, + [canvasRef], + ); - return ( - - Debug Canvas - - ); - }, -); + return ( + + Debug Canvas + + ); +}; export default DebugCanvas; diff --git a/excalidraw-app/package.json b/excalidraw-app/package.json index 2da2b37c2..e5dcde033 100644 --- a/excalidraw-app/package.json +++ b/excalidraw-app/package.json @@ -33,8 +33,8 @@ "i18next-browser-languagedetector": "6.1.4", "idb-keyval": "6.0.3", "jotai": "2.11.0", - "react": "18.2.0", - "react-dom": "18.2.0", + "react": "19.0.0", + "react-dom": "19.0.0", "socket.io-client": "4.7.2", "vite-plugin-html": "3.2.2" }, diff --git a/package.json b/package.json index 3bd87196e..1289a22c6 100644 --- a/package.json +++ b/package.json @@ -17,11 +17,11 @@ "@types/chai": "4.3.0", "@types/jest": "27.4.0", "@types/lodash.throttle": "4.1.7", - "@types/react": "18.2.0", - "@types/react-dom": "18.2.0", + "@types/react": "19.0.10", + "@types/react-dom": "19.0.4", "@types/socket.io-client": "3.0.0", "@vitejs/plugin-react": "3.1.0", - "@vitest/coverage-v8": "2.0.5", + "@vitest/coverage-v8": "3.0.7", "@vitest/ui": "2.0.5", "chai": "4.3.6", "dotenv": "16.0.1", @@ -39,9 +39,9 @@ "vite": "5.0.12", "vite-plugin-checker": "0.7.2", "vite-plugin-ejs": "1.7.0", - "vite-plugin-pwa": "0.17.4", + "vite-plugin-pwa": "0.21.1", "vite-plugin-svgr": "4.2.0", - "vitest": "2.0.5", + "vitest": "3.0.6", "vitest-canvas-mock": "0.3.3" }, "engines": { @@ -83,7 +83,6 @@ "clean-install": "yarn rm:node_modules && yarn install" }, "resolutions": { - "@types/react": "18.2.0", "strip-ansi": "6.0.1" } } diff --git a/packages/excalidraw/components/ButtonIcon.tsx b/packages/excalidraw/components/ButtonIcon.tsx index 5421f4c3a..cbbd73df9 100644 --- a/packages/excalidraw/components/ButtonIcon.tsx +++ b/packages/excalidraw/components/ButtonIcon.tsx @@ -1,4 +1,5 @@ import { forwardRef } from "react"; +import type { JSX } from "react"; import clsx from "clsx"; import "./ButtonIcon.scss"; diff --git a/packages/excalidraw/components/ButtonIconCycle.tsx b/packages/excalidraw/components/ButtonIconCycle.tsx index 98a6aa8ad..b73a8ec5a 100644 --- a/packages/excalidraw/components/ButtonIconCycle.tsx +++ b/packages/excalidraw/components/ButtonIconCycle.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import clsx from "clsx"; export const ButtonIconCycle = ({ diff --git a/packages/excalidraw/components/ButtonIconSelect.tsx b/packages/excalidraw/components/ButtonIconSelect.tsx index c3a390257..26191b50b 100644 --- a/packages/excalidraw/components/ButtonIconSelect.tsx +++ b/packages/excalidraw/components/ButtonIconSelect.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import clsx from "clsx"; import { ButtonIcon } from "./ButtonIcon"; diff --git a/packages/excalidraw/components/FontPicker/FontPickerList.tsx b/packages/excalidraw/components/FontPicker/FontPickerList.tsx index 6e1bf56c3..3a680b8fe 100644 --- a/packages/excalidraw/components/FontPicker/FontPickerList.tsx +++ b/packages/excalidraw/components/FontPicker/FontPickerList.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React, { useMemo, useState, diff --git a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts index abbfb94b3..19c4adccc 100644 --- a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts +++ b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts @@ -4,7 +4,7 @@ import { type FontDescriptor } from "./FontPickerList"; interface FontPickerKeyNavHandlerProps { event: React.KeyboardEvent; - inputRef: React.RefObject; + inputRef: React.RefObject; hoveredFont: Node | undefined; filteredFonts: Node[]; onClose: () => void; diff --git a/packages/excalidraw/components/HelpDialog.tsx b/packages/excalidraw/components/HelpDialog.tsx index c233d74af..926096c69 100644 --- a/packages/excalidraw/components/HelpDialog.tsx +++ b/packages/excalidraw/components/HelpDialog.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React from "react"; import { t } from "../i18n"; import { KEYS } from "../keys"; diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index 1a96a175d..ee83f905a 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React, { useEffect } from "react"; import * as Popover from "@radix-ui/react-popover"; import { isArrowKey, KEYS } from "../keys"; diff --git a/packages/excalidraw/components/MagicButton.tsx b/packages/excalidraw/components/MagicButton.tsx index 2a7e834eb..eedc63b3d 100644 --- a/packages/excalidraw/components/MagicButton.tsx +++ b/packages/excalidraw/components/MagicButton.tsx @@ -1,8 +1,9 @@ -import "./ToolIcon.scss"; - +import type { JSX } from "react"; import clsx from "clsx"; import type { ToolButtonSize } from "./ToolButton"; +import "./ToolIcon.scss"; + const DEFAULT_SIZE: ToolButtonSize = "small"; export const ElementCanvasButton = (props: { diff --git a/packages/excalidraw/components/MobileMenu.tsx b/packages/excalidraw/components/MobileMenu.tsx index 56408d50a..bef99a91a 100644 --- a/packages/excalidraw/components/MobileMenu.tsx +++ b/packages/excalidraw/components/MobileMenu.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React from "react"; import type { AppClassProperties, diff --git a/packages/excalidraw/components/Sidebar/common.ts b/packages/excalidraw/components/Sidebar/common.ts index 05493d44b..35c0c8bb1 100644 --- a/packages/excalidraw/components/Sidebar/common.ts +++ b/packages/excalidraw/components/Sidebar/common.ts @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React from "react"; import type { AppState, SidebarName, SidebarTabName } from "../../types"; diff --git a/packages/excalidraw/components/Stack.tsx b/packages/excalidraw/components/Stack.tsx index c54a6aef8..f45d47118 100644 --- a/packages/excalidraw/components/Stack.tsx +++ b/packages/excalidraw/components/Stack.tsx @@ -10,7 +10,6 @@ type StackProps = { justifyContent?: "center" | "space-around" | "space-between"; className?: string | boolean; style?: React.CSSProperties; - ref: React.RefObject; }; const RowStack = forwardRef( diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx index c05093fee..084a67f4f 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogOutput.tsx @@ -13,7 +13,7 @@ const ErrorComp = ({ error }: { error: string }) => { interface TTDDialogOutputProps { error: Error | null; - canvasRef: React.RefObject; + canvasRef: React.RefObject; loaded: boolean; } diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx index 033fa8b6c..a73f31a68 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import type { ReactNode } from "react"; import { useTunnels } from "../../context/tunnels"; import DropdownMenu from "../dropdownMenu/DropdownMenu"; diff --git a/packages/excalidraw/components/TTDDialog/common.ts b/packages/excalidraw/components/TTDDialog/common.ts index ddaa93045..4191126a4 100644 --- a/packages/excalidraw/components/TTDDialog/common.ts +++ b/packages/excalidraw/components/TTDDialog/common.ts @@ -12,7 +12,7 @@ const resetPreview = ({ canvasRef, setError, }: { - canvasRef: React.RefObject; + canvasRef: React.RefObject; setError: (error: Error | null) => void; }) => { const canvasNode = canvasRef.current; @@ -40,7 +40,7 @@ export interface MermaidToExcalidrawLibProps { } interface ConvertMermaidToExcalidrawFormatProps { - canvasRef: React.RefObject; + canvasRef: React.RefObject; mermaidToExcalidrawLib: MermaidToExcalidrawLibProps; mermaidDefinition: string; setError: (error: Error | null) => void; diff --git a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx index 7b8003332..03ae0f6b6 100644 --- a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx +++ b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx @@ -17,7 +17,7 @@ import { isRenderThrottlingEnabled } from "../../reactUtils"; import { renderInteractiveScene } from "../../renderer/interactiveScene"; type InteractiveCanvasProps = { - containerRef: React.RefObject; + containerRef: React.RefObject; canvas: HTMLCanvasElement | null; elementsMap: RenderableElementsMap; visibleElements: readonly NonDeletedExcalidrawElement[]; diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx index e1f46b697..1ff53f8af 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import React, { useEffect, useRef } from "react"; import { getDropdownMenuItemClassName, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx index 444b13707..000b8c344 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import { useDevice } from "../App"; const MenuItemContent = ({ diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx index 171c1c71e..2dbee7584 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx @@ -1,4 +1,5 @@ import MenuItemContent from "./DropdownMenuItemContent"; +import type { JSX } from "react"; import React from "react"; import { getDropdownMenuItemClassName, diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx index edc6618e9..4faa41bf7 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import { actionLoadScene, actionShortcuts } from "../../actions"; import { getShortcutFromShortcutName } from "../../actions/shortcuts"; import { t, useI18n } from "../../i18n"; diff --git a/packages/excalidraw/element/flowchart.test.tsx b/packages/excalidraw/element/flowchart.test.tsx index f832b20e4..d47c850b7 100644 --- a/packages/excalidraw/element/flowchart.test.tsx +++ b/packages/excalidraw/element/flowchart.test.tsx @@ -1,12 +1,11 @@ -import ReactDOM from "react-dom"; -import { render } from "../tests/test-utils"; +import { render, unmountComponent } from "../tests/test-utils"; import { reseed } from "../random"; import { UI, Keyboard, Pointer } from "../tests/helpers/ui"; import { Excalidraw } from "../index"; import { API } from "../tests/helpers/api"; import { KEYS } from "../keys"; -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/element/textWysiwyg.test.tsx b/packages/excalidraw/element/textWysiwyg.test.tsx index 2dc397a2d..80469d9e3 100644 --- a/packages/excalidraw/element/textWysiwyg.test.tsx +++ b/packages/excalidraw/element/textWysiwyg.test.tsx @@ -1,7 +1,11 @@ import React from "react"; -import ReactDOM from "react-dom"; import { Excalidraw } from "../index"; -import { GlobalTestState, render, screen } from "../tests/test-utils"; +import { + GlobalTestState, + render, + screen, + unmountComponent, +} from "../tests/test-utils"; import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; import { CODES, KEYS } from "../keys"; import { @@ -21,8 +25,7 @@ import { getOriginalContainerHeightFromCache } from "./containerCache"; import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; import { pointFrom } from "../../math"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const tab = " "; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/fonts/FontMetadata.ts b/packages/excalidraw/fonts/FontMetadata.ts index 2daefe57a..e93380e81 100644 --- a/packages/excalidraw/fonts/FontMetadata.ts +++ b/packages/excalidraw/fonts/FontMetadata.ts @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import { FreedrawIcon, FontFamilyNormalIcon, diff --git a/packages/excalidraw/global.d.ts b/packages/excalidraw/global.d.ts index 21a5d2057..207265716 100644 --- a/packages/excalidraw/global.d.ts +++ b/packages/excalidraw/global.d.ts @@ -99,8 +99,12 @@ declare module "image-blob-reduce" { export = reduce; } -declare namespace jest { - interface Expect { - toBeNonNaNNumber(): void; - } +interface CustomMatchers { + toBeNonNaNNumber(): void; + toCloselyEqualPoints(points: readonly [number, number][]): void; +} + +declare namespace jest { + interface Expect extends CustomMatchers {} + interface Matchers extends CustomMatchers {} } diff --git a/packages/excalidraw/hooks/useOutsideClick.ts b/packages/excalidraw/hooks/useOutsideClick.ts index c720a836b..da9a54d08 100644 --- a/packages/excalidraw/hooks/useOutsideClick.ts +++ b/packages/excalidraw/hooks/useOutsideClick.ts @@ -2,7 +2,7 @@ import { useEffect } from "react"; import { EVENT } from "../constants"; export function useOutsideClick( - ref: React.RefObject, + ref: React.RefObject, /** if performance is of concern, memoize the callback */ callback: (event: Event) => void, /** diff --git a/packages/excalidraw/hooks/useScrollPosition.ts b/packages/excalidraw/hooks/useScrollPosition.ts index cd913c07d..0be2eab95 100644 --- a/packages/excalidraw/hooks/useScrollPosition.ts +++ b/packages/excalidraw/hooks/useScrollPosition.ts @@ -5,7 +5,7 @@ import throttle from "lodash.throttle"; const scrollPositionAtom = atom(0); export const useScrollPosition = ( - elementRef: React.RefObject, + elementRef: React.RefObject, ) => { const [scrollPosition, setScrollPosition] = useAtom(scrollPositionAtom); diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json index b1f3e691b..c6e9d6575 100644 --- a/packages/excalidraw/package.json +++ b/packages/excalidraw/package.json @@ -52,8 +52,8 @@ ] }, "peerDependencies": { - "react": "^17.0.2 || ^18.2.0", - "react-dom": "^17.0.2 || ^18.2.0" + "react": "^17.0.2 || ^18.2.0 || ^19.0.0", + "react-dom": "^17.0.2 || ^18.2.0 || ^19.0.0" }, "dependencies": { "@braintree/sanitize-url": "6.0.2", @@ -98,8 +98,8 @@ "@babel/preset-typescript": "7.24.1", "@size-limit/preset-big-lib": "9.0.0", "@testing-library/dom": "10.4.0", - "@testing-library/jest-dom": "5.16.2", - "@testing-library/react": "16.0.0", + "@testing-library/jest-dom": "6.6.3", + "@testing-library/react": "16.2.0", "@types/pako": "1.0.3", "@types/pica": "5.1.3", "@types/resize-observer-browser": "0.1.7", diff --git a/packages/excalidraw/tests/App.test.tsx b/packages/excalidraw/tests/App.test.tsx index df8ee1582..ad62706a5 100644 --- a/packages/excalidraw/tests/App.test.tsx +++ b/packages/excalidraw/tests/App.test.tsx @@ -1,8 +1,7 @@ import React from "react"; -import ReactDOM from "react-dom"; import * as StaticScene from "../renderer/staticScene"; import { reseed } from "../random"; -import { render, queryByTestId } from "../tests/test-utils"; +import { render, queryByTestId, unmountComponent } from "../tests/test-utils"; import { Excalidraw } from "../index"; import { vi } from "vitest"; @@ -11,8 +10,7 @@ const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); describe("Test ", () => { beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); localStorage.clear(); renderStaticScene.mockClear(); reseed(7); diff --git a/packages/excalidraw/tests/align.test.tsx b/packages/excalidraw/tests/align.test.tsx index 63c329d64..47624e8f4 100644 --- a/packages/excalidraw/tests/align.test.tsx +++ b/packages/excalidraw/tests/align.test.tsx @@ -1,6 +1,5 @@ import React from "react"; -import ReactDOM from "react-dom"; -import { act, render } from "./test-utils"; +import { act, unmountComponent, render } from "./test-utils"; import { Excalidraw } from "../index"; import { defaultLang, setLanguage } from "../i18n"; import { UI, Pointer, Keyboard } from "./helpers/ui"; @@ -54,8 +53,7 @@ const createAndSelectTwoRectanglesWithDifferentSizes = () => { describe("aligning", () => { beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); mouse.reset(); await act(() => { diff --git a/packages/excalidraw/tests/clipboard.test.tsx b/packages/excalidraw/tests/clipboard.test.tsx index 94c785d4a..c2c0a5e2d 100644 --- a/packages/excalidraw/tests/clipboard.test.tsx +++ b/packages/excalidraw/tests/clipboard.test.tsx @@ -1,7 +1,11 @@ import React from "react"; import { vi } from "vitest"; -import ReactDOM from "react-dom"; -import { render, waitFor, GlobalTestState } from "./test-utils"; +import { + render, + waitFor, + GlobalTestState, + unmountComponent, +} from "./test-utils"; import { Pointer, Keyboard } from "./helpers/ui"; import { Excalidraw } from "../index"; import { KEYS } from "../keys"; @@ -63,7 +67,7 @@ const sleep = (ms: number) => { }; beforeEach(async () => { - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); localStorage.clear(); diff --git a/packages/excalidraw/tests/contextmenu.test.tsx b/packages/excalidraw/tests/contextmenu.test.tsx index 133c68222..bb3f415f1 100644 --- a/packages/excalidraw/tests/contextmenu.test.tsx +++ b/packages/excalidraw/tests/contextmenu.test.tsx @@ -1,5 +1,4 @@ import React from "react"; -import ReactDOM from "react-dom"; import { render, fireEvent, @@ -11,6 +10,7 @@ import { queryAllByText, waitFor, togglePopover, + unmountComponent, } from "./test-utils"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; @@ -38,8 +38,7 @@ const checkpoint = (name: string) => { const mouse = new Pointer("mouse"); -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); beforeEach(() => { diff --git a/packages/excalidraw/tests/cropElement.test.tsx b/packages/excalidraw/tests/cropElement.test.tsx index ca89b47b4..1fa33137c 100644 --- a/packages/excalidraw/tests/cropElement.test.tsx +++ b/packages/excalidraw/tests/cropElement.test.tsx @@ -1,9 +1,8 @@ import React from "react"; -import ReactDOM from "react-dom"; import { vi } from "vitest"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import type { ExcalidrawImageElement, ImageCrop } from "../element/types"; -import { act, GlobalTestState, render } from "./test-utils"; +import { act, GlobalTestState, render, unmountComponent } from "./test-utils"; import { Excalidraw, exportToCanvas, exportToSvg } from ".."; import { API } from "./helpers/api"; import type { NormalizedZoomValue } from "../types"; @@ -16,8 +15,7 @@ const { h } = window; const mouse = new Pointer("mouse"); beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); mouse.reset(); localStorage.clear(); diff --git a/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap index 95c49c2a7..7dd0c01c3 100644 --- a/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap +++ b/packages/excalidraw/tests/data/__snapshots__/restore.test.ts.snap @@ -173,7 +173,7 @@ exports[`restoreElements > should restore freedraw element correctly 1`] = ` "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 0, + "height": 100, "id": "id-freedraw01", "index": "a0", "isDeleted": false, @@ -181,7 +181,16 @@ exports[`restoreElements > should restore freedraw element correctly 1`] = ` "link": null, "locked": false, "opacity": 100, - "points": [], + "points": [ + [ + 0, + 0, + ], + [ + 10, + 10, + ], + ], "pressures": [], "roughness": 1, "roundness": { @@ -196,7 +205,7 @@ exports[`restoreElements > should restore freedraw element correctly 1`] = ` "updated": 1, "version": 2, "versionNonce": Any, - "width": 0, + "width": 100, "x": 0, "y": 0, } diff --git a/packages/excalidraw/tests/data/reconcile.test.ts b/packages/excalidraw/tests/data/reconcile.test.ts index 9770a79d8..f0e8105a1 100644 --- a/packages/excalidraw/tests/data/reconcile.test.ts +++ b/packages/excalidraw/tests/data/reconcile.test.ts @@ -80,9 +80,12 @@ const test = ( const reconciledIds = reconciled.map((x) => x.id); const reconciledIndices = reconciled.map((x) => x.index); - expect(target.length).equal(reconciled.length); - expect(reconciledIndices.length).equal(new Set([...reconciledIndices]).size); // expect no duplicated indices - expect(reconciledIds).deep.equal( + expect(target.length).toEqual(reconciled.length); + expect(reconciledIndices.length).toEqual( + new Set([...reconciledIndices]).size, + ); // expect no duplicated indices + assert.deepEqual( + reconciledIds, target.map((uid) => { const [, id, source] = uid.match(/^(\w+):([LR])$/)!; const element = (source === "L" ? _local : _remote).find( @@ -96,13 +99,15 @@ const test = ( // convergent reconciliation on the remote client try { - expect( + assert.deepEqual( reconcileElements( cloneJSON(_remote), cloneJSON(_local as RemoteExcalidrawElement[]), {} as AppState, ).map((x) => x.id), - ).deep.equal(reconciledIds, "convergent reconciliation"); + reconciledIds, + "convergent reconciliation", + ); } catch (error: any) { console.error("local original", _remote); console.error("remote original", _local); @@ -111,13 +116,15 @@ const test = ( // bidirectional re-reconciliation on remote client try { - expect( + assert.deepEqual( reconcileElements( cloneJSON(_remote), cloneJSON(reconciled as unknown as RemoteExcalidrawElement[]), {} as AppState, ).map((x) => x.id), - ).deep.equal(reconciledIds, "local re-reconciliation"); + reconciledIds, + "local re-reconciliation", + ); } catch (error: any) { console.error("local original", _remote); console.error("remote reconciled", reconciled); @@ -309,7 +316,10 @@ describe("elements reconciliation", () => { throw new Error("reconcileElements: duplicate elements found"); } - expect(ret.map((x) => x.id)).to.deep.equal(expected); + assert.deepEqual( + ret.map((x) => x.id), + expected, + ); }; // identical id/version/versionNonce/index diff --git a/packages/excalidraw/tests/data/restore.test.ts b/packages/excalidraw/tests/data/restore.test.ts index ef1e3198b..a3d6d7350 100644 --- a/packages/excalidraw/tests/data/restore.test.ts +++ b/packages/excalidraw/tests/data/restore.test.ts @@ -13,6 +13,7 @@ import type { NormalizedZoomValue } from "../../types"; import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; import { newElementWith } from "../../element/mutateElement"; import { vi } from "vitest"; +import { pointFrom } from "../../../math"; describe("restoreElements", () => { const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement"); @@ -103,6 +104,7 @@ describe("restoreElements", () => { const freedrawElement = API.createElement({ type: "freedraw", id: "id-freedraw01", + points: [pointFrom(0, 0), pointFrom(10, 10)], }); const restoredFreedraw = restore.restoreElements( diff --git a/packages/excalidraw/tests/dragCreate.test.tsx b/packages/excalidraw/tests/dragCreate.test.tsx index 7b0757858..743ba7947 100644 --- a/packages/excalidraw/tests/dragCreate.test.tsx +++ b/packages/excalidraw/tests/dragCreate.test.tsx @@ -1,5 +1,4 @@ import React from "react"; -import ReactDOM from "react-dom"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; import * as InteractiveScene from "../renderer/interactiveScene"; @@ -9,13 +8,13 @@ import { fireEvent, mockBoundingClientRect, restoreOriginalGetBoundingClientRect, + unmountComponent, } from "./test-utils"; import type { ExcalidrawLinearElement } from "../element/types"; import { reseed } from "../random"; import { vi } from "vitest"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const renderInteractiveScene = vi.spyOn( InteractiveScene, diff --git a/packages/excalidraw/tests/elementLocking.test.tsx b/packages/excalidraw/tests/elementLocking.test.tsx index e469ca542..281c26892 100644 --- a/packages/excalidraw/tests/elementLocking.test.tsx +++ b/packages/excalidraw/tests/elementLocking.test.tsx @@ -1,7 +1,6 @@ import React from "react"; -import ReactDOM from "react-dom"; import { Excalidraw } from "../index"; -import { render } from "../tests/test-utils"; +import { render, unmountComponent } from "../tests/test-utils"; import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; import { KEYS } from "../keys"; import { API } from "../tests/helpers/api"; @@ -9,7 +8,7 @@ import { actionSelectAll } from "../actions"; import { t } from "../i18n"; import { mutateElement } from "../element/mutateElement"; -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const mouse = new Pointer("mouse"); const h = window.h; diff --git a/packages/excalidraw/tests/flip.test.tsx b/packages/excalidraw/tests/flip.test.tsx index 03a2ac1fb..2cd617ebb 100644 --- a/packages/excalidraw/tests/flip.test.tsx +++ b/packages/excalidraw/tests/flip.test.tsx @@ -1,10 +1,10 @@ import React from "react"; -import ReactDOM from "react-dom"; import { fireEvent, GlobalTestState, render, screen, + unmountComponent, waitFor, } from "./test-utils"; import { UI, Pointer, Keyboard } from "./helpers/ui"; @@ -43,8 +43,7 @@ vi.mock("../data/blob", async (actual) => { }); beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); mouse.reset(); localStorage.clear(); diff --git a/packages/excalidraw/tests/helpers/api.ts b/packages/excalidraw/tests/helpers/api.ts index a6432666a..405bce396 100644 --- a/packages/excalidraw/tests/helpers/api.ts +++ b/packages/excalidraw/tests/helpers/api.ts @@ -189,7 +189,7 @@ export class API { containerId?: T extends "text" ? ExcalidrawTextElement["containerId"] : never; - points?: T extends "arrow" | "line" ? readonly LocalPoint[] : never; + points?: T extends "arrow" | "line" | "freedraw" ? readonly LocalPoint[] : never; locked?: boolean; fileId?: T extends "image" ? string : never; scale?: T extends "image" ? ExcalidrawImageElement["scale"] : never; @@ -228,8 +228,6 @@ export class API { const base: Omit< ExcalidrawGenericElement, | "id" - | "width" - | "height" | "type" | "version" | "versionNonce" @@ -241,6 +239,8 @@ export class API { seed: 1, x, y, + width, + height, frameId: rest.frameId ?? null, index: rest.index ?? null, angle: (rest.angle ?? 0) as Radians, @@ -272,8 +272,6 @@ export class API { case "ellipse": element = newElement({ type: type as "rectangle" | "diamond" | "ellipse", - width, - height, ...base, }); break; @@ -308,6 +306,7 @@ export class API { element = newFreeDrawElement({ type: type as "freedraw", simulatePressure: true, + points: rest.points, ...base, }); break; diff --git a/packages/excalidraw/tests/linearElementEditor.test.tsx b/packages/excalidraw/tests/linearElementEditor.test.tsx index 3f5acbf63..ef67329e0 100644 --- a/packages/excalidraw/tests/linearElementEditor.test.tsx +++ b/packages/excalidraw/tests/linearElementEditor.test.tsx @@ -1,5 +1,4 @@ import React from "react"; -import ReactDOM from "react-dom"; import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -12,7 +11,13 @@ import * as StaticScene from "../renderer/staticScene"; import * as InteractiveCanvas from "../renderer/interactiveScene"; import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { screen, render, fireEvent, GlobalTestState } from "./test-utils"; +import { + screen, + render, + fireEvent, + GlobalTestState, + unmountComponent, +} from "./test-utils"; import { API } from "../tests/helpers/api"; import { KEYS } from "../keys"; import { LinearElementEditor } from "../element/linearElementEditor"; @@ -43,8 +48,7 @@ describe("Test Linear Elements", () => { let interactiveCanvas: HTMLCanvasElement; beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); localStorage.clear(); renderInteractiveScene.mockClear(); renderStaticScene.mockClear(); diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 9cc3e4507..5e11fe5b6 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -1,6 +1,5 @@ import React from "react"; -import ReactDOM from "react-dom"; -import { render, fireEvent, act } from "./test-utils"; +import { render, fireEvent, act, unmountComponent } from "./test-utils"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; import * as InteractiveCanvas from "../renderer/interactiveScene"; @@ -16,8 +15,7 @@ import { KEYS } from "../keys"; import { vi } from "vitest"; import type Scene from "../scene/Scene"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const renderInteractiveScene = vi.spyOn( InteractiveCanvas, diff --git a/packages/excalidraw/tests/multiPointCreate.test.tsx b/packages/excalidraw/tests/multiPointCreate.test.tsx index 2559ddcaf..df94eb9da 100644 --- a/packages/excalidraw/tests/multiPointCreate.test.tsx +++ b/packages/excalidraw/tests/multiPointCreate.test.tsx @@ -1,10 +1,10 @@ import React from "react"; -import ReactDOM from "react-dom"; import { render, fireEvent, mockBoundingClientRect, restoreOriginalGetBoundingClientRect, + unmountComponent, } from "./test-utils"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; @@ -14,8 +14,7 @@ import type { ExcalidrawLinearElement } from "../element/types"; import { reseed } from "../random"; import { vi } from "vitest"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const renderInteractiveScene = vi.spyOn( InteractiveCanvas, diff --git a/packages/excalidraw/tests/regressionTests.test.tsx b/packages/excalidraw/tests/regressionTests.test.tsx index c7ca33211..a3e45bca6 100644 --- a/packages/excalidraw/tests/regressionTests.test.tsx +++ b/packages/excalidraw/tests/regressionTests.test.tsx @@ -1,5 +1,4 @@ import React from "react"; -import ReactDOM from "react-dom"; import type { ExcalidrawElement } from "../element/types"; import { CODES, KEYS } from "../keys"; import { Excalidraw } from "../index"; @@ -14,6 +13,7 @@ import { render, screen, togglePopover, + unmountComponent, } from "./test-utils"; import { FONT_FAMILY } from "../constants"; import { vi } from "vitest"; @@ -43,8 +43,7 @@ const checkpoint = (name: string) => { ); }; beforeEach(async () => { - // Unmount ReactDOM from root - ReactDOM.unmountComponentAtNode(document.getElementById("root")!); + unmountComponent(); localStorage.clear(); renderStaticScene.mockClear(); diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index 431f695cb..1e2e0f4aa 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -1,6 +1,5 @@ import React from "react"; -import ReactDOM from "react-dom"; -import { render } from "./test-utils"; +import { render, unmountComponent } from "./test-utils"; import { reseed } from "../random"; import { UI, Keyboard, Pointer } from "./helpers/ui"; import type { @@ -21,7 +20,7 @@ import { pointFrom } from "../../math"; import { resizeSingleElement } from "../element/resizeElements"; import { getSizeFromPoints } from "../points"; -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index ed61f9934..a5301cc34 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -1,12 +1,11 @@ import React from "react"; -import ReactDOM from "react-dom"; -import { render } from "./test-utils"; +import { render, unmountComponent } from "./test-utils"; import { reseed } from "../random"; import { UI } from "./helpers/ui"; import { Excalidraw } from "../index"; import { expect } from "vitest"; -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); beforeEach(() => { localStorage.clear(); diff --git a/packages/excalidraw/tests/selection.test.tsx b/packages/excalidraw/tests/selection.test.tsx index bffe375bf..0b1f6e50d 100644 --- a/packages/excalidraw/tests/selection.test.tsx +++ b/packages/excalidraw/tests/selection.test.tsx @@ -1,11 +1,11 @@ import React from "react"; -import ReactDOM from "react-dom"; import { render, fireEvent, mockBoundingClientRect, restoreOriginalGetBoundingClientRect, assertSelectedElements, + unmountComponent, } from "./test-utils"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; @@ -17,8 +17,7 @@ import { Keyboard, Pointer, UI } from "./helpers/ui"; import { SHAPES } from "../shapes"; import { vi } from "vitest"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); const renderInteractiveScene = vi.spyOn( InteractiveCanvas, diff --git a/packages/excalidraw/tests/test-utils.ts b/packages/excalidraw/tests/test-utils.ts index 1c775c221..5e395c1e8 100644 --- a/packages/excalidraw/tests/test-utils.ts +++ b/packages/excalidraw/tests/test-utils.ts @@ -2,7 +2,13 @@ import "pepjs"; import type { RenderResult, RenderOptions } from "@testing-library/react"; import { act } from "@testing-library/react"; -import { render, queries, waitFor, fireEvent } from "@testing-library/react"; +import { + render, + queries, + waitFor, + fireEvent, + cleanup, +} from "@testing-library/react"; import * as toolQueries from "./queries/toolQueries"; import type { ImportedDataState } from "../data/types"; @@ -16,6 +22,8 @@ import { ORIG_ID } from "../constants"; import { arrayToMap } from "../utils"; import type { AllPossibleKeys } from "../utility-types"; +export { cleanup as unmountComponent }; + const customQueries = { ...queries, ...toolQueries, diff --git a/packages/excalidraw/tests/zindex.test.tsx b/packages/excalidraw/tests/zindex.test.tsx index 732644eb3..f15d55931 100644 --- a/packages/excalidraw/tests/zindex.test.tsx +++ b/packages/excalidraw/tests/zindex.test.tsx @@ -1,6 +1,5 @@ import React from "react"; -import ReactDOM from "react-dom"; -import { act, getCloneByOrigId, render } from "./test-utils"; +import { act, getCloneByOrigId, render, unmountComponent } from "./test-utils"; import { Excalidraw } from "../index"; import { reseed } from "../random"; import { @@ -19,8 +18,7 @@ import type { ExcalidrawSelectionElement, } from "../element/types"; -// Unmount ReactDOM from root -ReactDOM.unmountComponentAtNode(document.getElementById("root")!); +unmountComponent(); beforeEach(() => { localStorage.clear(); diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 4974f4214..7dbb2d314 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -1,3 +1,4 @@ +import type { JSX } from "react"; import type React from "react"; import type { PointerType, diff --git a/tsconfig.json b/tsconfig.json index 585fa4cdb..617b3531c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { + "types": ["vitest/globals", "@testing-library/jest-dom"], "target": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], "allowJs": true, diff --git a/yarn.lock b/yarn.lock index d4727368c..5c1197d30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,11 @@ # yarn lockfile v1 +"@adobe/css-tools@^4.4.0": + version "4.4.2" + resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.4.2.tgz#c836b1bd81e6d62cd6cdf3ee4948bcdce8ea79c8" + integrity sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A== + "@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" @@ -26,31 +31,19 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2" - integrity sha512-ZJhac6FkEd1yhG2AHOmfcXG4ceoLltoCVJjN5XsWN9BifBQr+cHJbWi0h68HZuSORq+3WtJ2z0hwF2NG1b5kcA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== dependencies: - "@babel/highlight" "^7.24.6" + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== - dependencies: - "@babel/highlight" "^7.24.7" - picocolors "^1.0.0" - -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.4", "@babel/compat-data@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.6.tgz#b3600217688cabb26e25f8e467019e66d71b7ae2" - integrity sha512-aC2DGhBq5eEdyXWqrDInSqQjO0k8xtPRf5YylULqx8MCd6jBtzqfta/3ETMRpuKIc5hyswfO80ObyA1MvkCcUQ== - -"@babel/compat-data@^7.25.2": - version "7.25.4" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.25.4.tgz#7d2a80ce229890edcf4cc259d4d696cb4dae2fcb" - integrity sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.4", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" + integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== "@babel/core@7.24.5": version "7.24.5" @@ -73,42 +66,21 @@ json5 "^2.2.3" semver "^6.3.1" -"@babel/core@^7.16.0", "@babel/core@^7.20.12", "@babel/core@^7.24.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.6.tgz#8650e0e4b03589ebe886c4e4a60398db0a7ec787" - integrity sha512-qAHSfAdVyFmIvl0VHELib8xar7ONuSHrE2hLnsaWkYNTI68dmi1x8GYDhJjMI/e7XWal9QBlZkwbOnkcw7Z8gQ== +"@babel/core@^7.16.0", "@babel/core@^7.20.12", "@babel/core@^7.21.3", "@babel/core@^7.24.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" + integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helpers" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/traverse" "^7.24.6" - "@babel/types" "^7.24.6" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - -"@babel/core@^7.21.3": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.25.2.tgz#ed8eec275118d7613e77a352894cd12ded8eba77" - integrity sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.25.0" - "@babel/helper-compilation-targets" "^7.25.2" - "@babel/helper-module-transforms" "^7.25.2" - "@babel/helpers" "^7.25.0" - "@babel/parser" "^7.25.0" - "@babel/template" "^7.25.0" - "@babel/traverse" "^7.25.2" - "@babel/types" "^7.25.2" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/helper-compilation-targets" "^7.26.5" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.9" + "@babel/types" "^7.26.9" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -116,98 +88,69 @@ semver "^6.3.1" "@babel/eslint-parser@^7.16.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.6.tgz#7f0ecc0f29307b8696e83ff6a9d8b4f3e0421ad2" - integrity sha512-Q1BfQX42zXHx732PLW0w4+Y3wJjoZKEMaatFUEAmQ7Z+jCXxinzeqX9bvv2Q8xNPes/H6F0I23oGkcgjaItmLw== + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz#55c4f4aae4970ae127f7a12369182ed6250e6f09" + integrity sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.24.5", "@babel/generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.6.tgz#dfac82a228582a9d30c959fe50ad28951d4737a7" - integrity sha512-S7m4eNa6YAPJRHmKsLHIDJhNAGNKoWNiWefz1MBbpnt8g9lvMDl1hir4P9bo/57bQEmuwEhnRU/AMWsD0G/Fbg== +"@babel/generator@^7.24.5", "@babel/generator@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" + integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== dependencies: - "@babel/types" "^7.24.6" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + jsesc "^3.0.2" -"@babel/generator@^7.25.0", "@babel/generator@^7.25.6": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.6.tgz#0df1ad8cb32fe4d2b01d8bf437f153d19342a87c" - integrity sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw== +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" + integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== dependencies: - "@babel/types" "^7.25.6" - "@jridgewell/gen-mapping" "^0.3.5" - "@jridgewell/trace-mapping" "^0.3.25" - jsesc "^2.5.1" + "@babel/types" "^7.25.9" -"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.6.tgz#517af93abc77924f9b2514c407bbef527fb8938d" - integrity sha512-DitEzDfOMnd13kZnDqns1ccmftwJTS9DMkyn9pYTxulS7bZxUxpMly3Nf23QQ6NwA4UB8lAqjbqWtyvElEMAkg== +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" + integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-builder-binary-assignment-operator-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.6.tgz#19e9089ee87b0d0928012c83961a8deef4b0223f" - integrity sha512-+wnfqc5uHiMYtvRX7qu80Toef8BXeh4HHR1SPeonGb1SKPniNEd4a/nlaJJMv/OIEYvIVavvo0yR7u10Gqz0Iw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.6.tgz#4a51d681f7680043d38e212715e2a7b1ad29cb51" - integrity sha512-VZQ57UsDGlX/5fFA7GkVPplZhHsVc+vuErWgdOiysI9Ksnw0Pbbd6pnPiR/mmJyKHgyIW0c7KT32gmhiF+cirg== - dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - browserslist "^4.22.2" + "@babel/compat-data" "^7.26.5" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-compilation-targets@^7.25.2": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz#e1d9410a90974a3a5a66e84ff55ef62e3c02d06c" - integrity sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw== +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.5", "@babel/helper-create-class-features-plugin@^7.25.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" + integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== dependencies: - "@babel/compat-data" "^7.25.2" - "@babel/helper-validator-option" "^7.24.8" - browserslist "^4.23.1" - lru-cache "^5.1.1" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/helper-replace-supers" "^7.26.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/traverse" "^7.26.9" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.5", "@babel/helper-create-class-features-plugin@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.6.tgz#c50b86fa1c4ca9b7a890dc21884f097b6c4b5286" - integrity sha512-djsosdPJVZE6Vsw3kk7IPRWethP94WHGOhQTc67SNXE0ZzMhHgALw8iGmYS0TD1bbMM0VDROy43od7/hN6WYcA== +"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.25.9": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz#5169756ecbe1d95f7866b90bb555b022595302a0" + integrity sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-member-expression-to-functions" "^7.24.6" - "@babel/helper-optimise-call-expression" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.25.9" + regexpu-core "^6.2.0" semver "^6.3.1" -"@babel/helper-create-regexp-features-plugin@^7.18.6", "@babel/helper-create-regexp-features-plugin@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.24.6.tgz#47d382dec0d49e74ca1b6f7f3b81f5968022a3c8" - integrity sha512-C875lFBIWWwyv6MHZUG9HmRrlTDgOsLWZfYR0nW69gaKJNe0/Mpxx5r0EID2ZdHQkdUmQo2t0uNckTL08/1BgA== - dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - regexpu-core "^5.3.1" - semver "^6.3.1" - -"@babel/helper-define-polyfill-provider@^0.6.1", "@babel/helper-define-polyfill-provider@^0.6.2": - version "0.6.2" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz#18594f789c3594acb24cfdb4a7f7b7d2e8bd912d" - integrity sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ== +"@babel/helper-define-polyfill-provider@^0.6.2", "@babel/helper-define-polyfill-provider@^0.6.3": + version "0.6.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz#f4f2792fae2ef382074bc2d713522cf24e6ddb21" + integrity sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -215,246 +158,156 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.6.tgz#ac7ad5517821641550f6698dd5468f8cef78620d" - integrity sha512-Y50Cg3k0LKLMjxdPjIl40SdJgMB85iXn27Vk/qbHZCFx/o5XO3PSnpi675h1KEmmDb6OFArfd5SCQEQ5Q4H88g== - -"@babel/helper-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.6.tgz#cebdd063386fdb95d511d84b117e51fc68fec0c8" - integrity sha512-xpeLqeeRkbxhnYimfr2PC+iA0Q7ljX/d1eZ9/inYbmfG2jpl8Lu3DyXvpOAnrS5kxkfOWJjioIMQsaMBXFI05w== +"@babel/helper-member-expression-to-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz#9dfffe46f727005a5ea29051ac835fb735e4c1a3" + integrity sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ== dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/helper-hoist-variables@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.6.tgz#8a7ece8c26756826b6ffcdd0e3cf65de275af7f9" - integrity sha512-SF/EMrC3OD7dSta1bLJIlrsVxwtd0UpjRJqLno6125epQMJ/kyFmpTT4pbvPbdQHzCHg+biQ7Syo8lnDtbR+uA== +"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3", "@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== dependencies: - "@babel/types" "^7.24.6" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/helper-member-expression-to-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.6.tgz#86084f3e0e4e2169a134754df3870bc7784db71e" - integrity sha512-OTsCufZTxDUsv2/eDXanw/mUZHWOxSbEmC3pP8cgjcy5rgeVPWWMStnv274DV60JtHxTk0adT0QrCzC4M9NWGg== +"@babel/helper-module-transforms@^7.24.5", "@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== dependencies: - "@babel/types" "^7.24.6" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3", "@babel/helper-module-imports@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.6.tgz#65e54ffceed6a268dc4ce11f0433b82cfff57852" - integrity sha512-a26dmxFJBF62rRO9mmpgrfTLsAuyHk4e1hKTUkD/fcMfynt8gvEKwQPQDVxWhca8dHoDck+55DFt42zV0QMw5g== +"@babel/helper-optimise-call-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz#3324ae50bae7e2ab3c33f60c9a877b6a0146b54e" + integrity sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ== dependencies: - "@babel/types" "^7.24.6" + "@babel/types" "^7.25.9" -"@babel/helper-module-imports@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz#f2f980392de5b84c3328fc71d38bd81bbb83042b" - integrity sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA== +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" + integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== + +"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" + integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-wrap-function" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/helper-module-transforms@^7.24.5", "@babel/helper-module-transforms@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.24.6.tgz#22346ed9df44ce84dee850d7433c5b73fab1fe4e" - integrity sha512-Y/YMPm83mV2HJTbX1Qh2sjgjqcacvOlhbzdCCsSlblOKjSYmQqEbO6rUniWQyRo9ncyfjT8hnUjlG06RXDEmcA== +"@babel/helper-replace-supers@^7.25.9", "@babel/helper-replace-supers@^7.26.5": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz#6cb04e82ae291dae8e72335dfe438b0725f14c8d" + integrity sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" + "@babel/helper-member-expression-to-functions" "^7.25.9" + "@babel/helper-optimise-call-expression" "^7.25.9" + "@babel/traverse" "^7.26.5" -"@babel/helper-module-transforms@^7.25.2": - version "7.25.2" - resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.25.2.tgz#ee713c29768100f2776edf04d4eb23b8d27a66e6" - integrity sha512-BjyRAbix6j/wv83ftcVJmBt72QtHI56C7JXZoG2xATiLpmoC7dpd8WnkikExHDVPpi/3qCmO6WY1EaXOluiecQ== +"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz#0b2e1b62d560d6b1954893fd2b705dc17c91f0c9" + integrity sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA== dependencies: - "@babel/helper-module-imports" "^7.24.7" - "@babel/helper-simple-access" "^7.24.7" - "@babel/helper-validator-identifier" "^7.24.7" - "@babel/traverse" "^7.25.2" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/helper-optimise-call-expression@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.6.tgz#f7836e3ccca3dfa02f15d2bc8b794efe75a5256e" - integrity sha512-3SFDJRbx7KuPRl8XDUr8O7GAEB8iGyWPjLKJh/ywP/Iy9WOmEfMrsWbaZpvBu2HSYn4KQygIsz0O7m8y10ncMA== +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.23.5", "@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helper-wrap-function@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz#d99dfd595312e6c894bd7d237470025c85eea9d0" + integrity sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g== dependencies: - "@babel/types" "^7.24.6" + "@babel/template" "^7.25.9" + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.5", "@babel/helper-plugin-utils@^7.24.6", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.6.tgz#fa02a32410a15a6e8f8185bcbf608f10528d2a24" - integrity sha512-MZG/JcWfxybKwsA9N9PmtF2lOSFSEMVCpIRrbxccZFLJPrJciJdG/UhSh5W96GEteJI2ARqm5UAHxISwRDLSNg== - -"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.24.6.tgz#c96ceb9846e877d806ce82a1521230ea7e0fc354" - integrity sha512-1Qursq9ArRZPAMOZf/nuzVW8HgJLkTB9y9LfP4lW2MVp4e9WkLJDovfKBxoDcCk6VuzIxyqWHyBoaCtSRP10yg== +"@babel/helpers@^7.24.5", "@babel/helpers@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" + integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-wrap-function" "^7.24.6" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/helper-replace-supers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.6.tgz#3ea87405a2986a49ab052d10e540fe036d747c71" - integrity sha512-mRhfPwDqDpba8o1F8ESxsEkJMQkUF8ZIWrAc0FtWhxnjfextxMWxr22RtFizxxSYLjVHDeMgVsRq8BBZR2ikJQ== +"@babel/highlight@^7.10.4": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6" + integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-member-expression-to-functions" "^7.24.6" - "@babel/helper-optimise-call-expression" "^7.24.6" - -"@babel/helper-simple-access@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.6.tgz#1d6e04d468bba4fc963b4906f6dac6286cfedff1" - integrity sha512-nZzcMMD4ZhmB35MOOzQuiGO5RzL6tJbsT37Zx8M5L/i9KSrukGXWTjLe1knIbb/RmxoJE9GON9soq0c0VEMM5g== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-simple-access@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz#bcade8da3aec8ed16b9c4953b74e506b51b5edb3" - integrity sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg== - dependencies: - "@babel/traverse" "^7.24.7" - "@babel/types" "^7.24.7" - -"@babel/helper-skip-transparent-expression-wrappers@^7.20.0", "@babel/helper-skip-transparent-expression-wrappers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.6.tgz#c47e9b33b7ea50d1073e125ebc26661717cb7040" - integrity sha512-jhbbkK3IUKc4T43WadP96a27oYti9gEf1LdyGSP2rHGH77kwLwfhO7TgwnWvxxQVmke0ImmCSS47vcuxEMGD3Q== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-split-export-declaration@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.6.tgz#e830068f7ba8861c53b7421c284da30ae656d7a3" - integrity sha512-CvLSkwXGWnYlF9+J3iZUvwgAxKiYzK3BWuo+mLzD/MDGOZDj7Gq8+hqaOkMxmJwmlv0iu86uH5fdADd9Hxkymw== - dependencies: - "@babel/types" "^7.24.6" - -"@babel/helper-string-parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df" - integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q== - -"@babel/helper-string-parser@^7.24.8": - version "7.24.8" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz#5b3329c9a58803d5df425e5785865881a81ca48d" - integrity sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ== - -"@babel/helper-validator-identifier@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e" - integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw== - -"@babel/helper-validator-identifier@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" - integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== - -"@babel/helper-validator-option@^7.23.5", "@babel/helper-validator-option@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.6.tgz#59d8e81c40b7d9109ab7e74457393442177f460a" - integrity sha512-Jktc8KkF3zIkePb48QO+IapbXlSapOW9S+ogZZkcO6bABgYAxtZcjZ/O005111YLf+j4M84uEgwYoidDkXbCkQ== - -"@babel/helper-validator-option@^7.24.8": - version "7.24.8" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" - integrity sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q== - -"@babel/helper-wrap-function@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.24.6.tgz#c27af1006e310683fdc76b668a0a1f6003e36217" - integrity sha512-f1JLrlw/jbiNfxvdrfBgio/gRBk3yTAEJWirpAkiJG2Hb22E7cEYKHWo0dFPTv/niPovzIdPdEDetrv6tC6gPQ== - dependencies: - "@babel/helper-function-name" "^7.24.6" - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helpers@^7.24.5", "@babel/helpers@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.6.tgz#cd124245299e494bd4e00edda0e4ea3545c2c176" - integrity sha512-V2PI+NqnyFu1i0GyTd/O/cTpxzQCYioSkUIRmgo7gFEHKKCg5w46+r/A6WeUR1+P3TeQ49dspGPNd/E3n9AnnA== - dependencies: - "@babel/template" "^7.24.6" - "@babel/types" "^7.24.6" - -"@babel/helpers@^7.25.0": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.25.6.tgz#57ee60141829ba2e102f30711ffe3afab357cc60" - integrity sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q== - dependencies: - "@babel/template" "^7.25.0" - "@babel/types" "^7.25.6" - -"@babel/highlight@^7.10.4", "@babel/highlight@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df" - integrity sha512-2YnuOp4HAk2BsBrJJvYCbItHx0zWscI1C3zgWkz+wDyD9I7GIVrfnLyrR4Y1VR+7p+chAEcrgRQYZAGIKMV7vQ== - dependencies: - "@babel/helper-validator-identifier" "^7.24.6" + "@babel/helper-validator-identifier" "^7.25.9" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== +"@babel/parser@^7.24.5", "@babel/parser@^7.25.4", "@babel/parser@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" + integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== dependencies: - "@babel/helper-validator-identifier" "^7.24.7" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" + "@babel/types" "^7.26.9" -"@babel/parser@^7.24.5", "@babel/parser@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328" - integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q== - -"@babel/parser@^7.25.0", "@babel/parser@^7.25.4", "@babel/parser@^7.25.6": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.6.tgz#85660c5ef388cbbf6e3d2a694ee97a38f18afe2f" - integrity sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q== +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5", "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" + integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== dependencies: - "@babel/types" "^7.25.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5", "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.6.tgz#283a74ef365b1e954cda6b2724c678a978215e88" - integrity sha512-bYndrJ6Ph6Ar+GaB5VAc0JPoP80bQCm4qon6JEzXfRl5QZyQ8Ur1K6k7htxWmPA5z+k7JQvaMUrtXlqclWYzKw== +"@babel/plugin-bugfix-safari-class-field-initializer-scope@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz#af9e4fb63ccb8abcb92375b2fcfe36b60c774d30" + integrity sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.6.tgz#f9f5ae4d6fb72f5950262cb6f0b2482c3bc684ef" - integrity sha512-iVuhb6poq5ikqRq2XWU6OQ+R5o9wF+r/or9CeUyovgptz0UlnK4/seOQ1Istu/XybYjAhQv1FRSSfHHufIku5Q== +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" + integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.6.tgz#ab9be6edfffa127bd5ec4317c76c5af0f8fc7e6c" - integrity sha512-c8TER5xMDYzzFcGqOEp9l4hvB7dcbhcGjcLVwxWfe4P5DOafdwjsBJZKsmv+o3aXh7NhopvayQIovHrh2zSRUQ== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" + integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/plugin-transform-optional-chaining" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.6.tgz#0faf879249ec622d7f1c42eaebf7d11197401b2c" - integrity sha512-z8zEjYmwBUHN/pCF3NuWBhHQjJCrd33qAi8MgANfMrAvn72k2cImT8VjK9LJFu4ysOLJqhfkYYb3MvwANRUNZQ== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" + integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" "@babel/plugin-proposal-class-properties@^7.16.0": version "7.18.6" @@ -465,13 +318,13 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-decorators@^7.16.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.24.6.tgz#20e7ed41c24d3f6a2d94af7b44ddd06d1f8a71a3" - integrity sha512-8DjR0/DzlBhz2SVi9a19/N2U5+C3y3rseXuyoKL9SP8vnbewscj1eHZtL6kpEn4UCuUmqEo0mvqyDYRFoN2gpA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz#8680707f943d1a3da2cd66b948179920f097e254" + integrity sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-decorators" "^7.24.6" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-decorators" "^7.25.9" "@babel/plugin-proposal-nullish-coalescing-operator@^7.16.0": version "7.18.6" @@ -511,7 +364,7 @@ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== -"@babel/plugin-proposal-private-property-in-object@7.21.11": +"@babel/plugin-proposal-private-property-in-object@7.21.11", "@babel/plugin-proposal-private-property-in-object@^7.16.7": version "7.21.11" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== @@ -542,12 +395,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-decorators@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.24.6.tgz#904d53fc158e8fb9f0754c76071e0ce38fe318eb" - integrity sha512-gInH8LEqBp+wkwTVihCd/qf+4s28g81FZyvlIbAurHk9eSiItEKG7E0uNK2UdpgsD79aJVAW3R3c85h0YJ0jsw== +"@babel/plugin-syntax-decorators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz#986b4ca8b7b5df3f67cee889cedeffc2e2bf14b3" + integrity sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-syntax-dynamic-import@^7.8.3": version "7.8.3" @@ -563,26 +416,26 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-flow@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.6.tgz#1102a710771326b8e2f0c85ac2aecb6f52eb601e" - integrity sha512-gNkksSdV8RbsCoHF9sjVYrHfYACMl/8U32UfUhJ9+84/ASXw8dlx+eHyyF0m6ncQJ9IBSxfuCkB36GJqYdXTOA== +"@babel/plugin-syntax-flow@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa" + integrity sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-assertions@^7.24.1", "@babel/plugin-syntax-import-assertions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.6.tgz#52521c1c1698fc2dd9cf88f7a4dd86d4d041b9e1" - integrity sha512-BE6o2BogJKJImTmGpkmOic4V0hlRRxVtzqxiSPa8TIFxyhi4EFjHm08nq1M4STK4RytuLMgnSz0/wfflvGFNOg== +"@babel/plugin-syntax-import-assertions@^7.24.1", "@babel/plugin-syntax-import-assertions@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" + integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-attributes@^7.24.1", "@babel/plugin-syntax-import-attributes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.6.tgz#12aba325534129584672920274fefa4dc2d5f68e" - integrity sha512-D+CfsVZousPXIdudSII7RGy52+dYRtbyKAZcvtQKq/NpsivyMVduepzcLqG5pMBugtMdedxdC8Ramdpcne9ZWQ== +"@babel/plugin-syntax-import-attributes@^7.24.1", "@babel/plugin-syntax-import-attributes@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" + integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-syntax-import-meta@^7.10.4": version "7.10.4" @@ -598,12 +451,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.24.1", "@babel/plugin-syntax-jsx@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.6.tgz#bcca2964150437f88f65e3679e3d68762287b9c8" - integrity sha512-lWfvAIFNWMlCsU0DRUun2GpFwZdGTukLaHJqRh1JRb80NdAP5Sb1HDHB5X9P9OtgZHQl089UzQkpYlBq2VTPRw== +"@babel/plugin-syntax-jsx@^7.24.1", "@babel/plugin-syntax-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" + integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-syntax-logical-assignment-operators@^7.10.4": version "7.10.4" @@ -661,12 +514,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.6.tgz#769daf2982d60308bc83d8936eaecb7582463c87" - integrity sha512-TzCtxGgVTEJWWwcYwQhCIQ6WaKlo80/B+Onsk4RRCcYqpYGFcG9etPW94VToGte5AAcxRrhjPUFvUS3Y2qKi4A== +"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" + integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-syntax-unicode-sets-regex@^7.18.6": version "7.18.6" @@ -683,22 +536,21 @@ dependencies: "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-arrow-functions@^7.24.1", "@babel/plugin-transform-arrow-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.6.tgz#93607d1ef5b81c70af174aff3532d57216367492" - integrity sha512-jSSSDt4ZidNMggcLx8SaKsbGNEfIl0PHx/4mFEulorE7bpYLbN0d3pDW3eJ7Y5Z3yPhy3L3NaPCYyTUY7TuugQ== +"@babel/plugin-transform-arrow-functions@^7.24.1", "@babel/plugin-transform-arrow-functions@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" + integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-async-generator-functions@^7.24.3", "@babel/plugin-transform-async-generator-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.6.tgz#fa4a9e5c3a7f60f697ba36587b6c41b04f507d84" - integrity sha512-VEP2o4iR2DqQU6KPgizTW2mnMx6BG5b5O9iQdrW9HesLkv8GIA8x2daXBQxw1MrsIkFQGA/iJ204CKoQ8UcnAA== +"@babel/plugin-transform-async-generator-functions@^7.24.3", "@babel/plugin-transform-async-generator-functions@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" + integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== dependencies: - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-remap-async-to-generator" "^7.24.6" - "@babel/plugin-syntax-async-generators" "^7.8.4" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-remap-async-to-generator" "^7.25.9" + "@babel/traverse" "^7.26.8" "@babel/plugin-transform-async-to-generator@7.24.1": version "7.24.1" @@ -709,363 +561,364 @@ "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-remap-async-to-generator" "^7.22.20" -"@babel/plugin-transform-async-to-generator@^7.24.1", "@babel/plugin-transform-async-to-generator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.6.tgz#eb11434b11d73d8c0cf9f71a6f4f1e6ba441df35" - integrity sha512-NTBA2SioI3OsHeIn6sQmhvXleSl9T70YY/hostQLveWs0ic+qvbA3fa0kwAwQ0OA/XGaAerNZRQGJyRfhbJK4g== +"@babel/plugin-transform-async-to-generator@^7.24.1", "@babel/plugin-transform-async-to-generator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" + integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== dependencies: - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-remap-async-to-generator" "^7.24.6" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-remap-async-to-generator" "^7.25.9" -"@babel/plugin-transform-block-scoped-functions@^7.24.1", "@babel/plugin-transform-block-scoped-functions@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.6.tgz#975555b5bfa9870b1218da536d1528735f1f8c56" - integrity sha512-XNW7jolYHW9CwORrZgA/97tL/k05qe/HL0z/qqJq1mdWhwwCM6D4BJBV7wAz9HgFziN5dTOG31znkVIzwxv+vw== +"@babel/plugin-transform-block-scoped-functions@^7.24.1", "@babel/plugin-transform-block-scoped-functions@^7.26.5": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" + integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-block-scoping@^7.24.5", "@babel/plugin-transform-block-scoping@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.6.tgz#a03ec8a4591c2b43cf7798bc633e698293fda179" - integrity sha512-S/t1Xh4ehW7sGA7c1j/hiOBLnEYCp/c2sEG4ZkL8kI1xX9tW2pqJTCHKtdhe/jHKt8nG0pFCrDHUXd4DvjHS9w== +"@babel/plugin-transform-block-scoping@^7.24.5", "@babel/plugin-transform-block-scoping@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" + integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-class-properties@^7.24.1", "@babel/plugin-transform-class-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.6.tgz#d9f394e97e88ef905d5a1e5e7a16238621b7982e" - integrity sha512-j6dZ0Z2Z2slWLR3kt9aOmSIrBvnntWjMDN/TVcMPxhXMLmJVqX605CBRlcGI4b32GMbfifTEsdEjGjiE+j/c3A== +"@babel/plugin-transform-class-properties@^7.24.1", "@babel/plugin-transform-class-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" + integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-class-static-block@^7.24.4", "@babel/plugin-transform-class-static-block@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.6.tgz#f43f29286f6f0dca33d18fd5033b817d6c3fa816" - integrity sha512-1QSRfoPI9RoLRa8Mnakc6v3e0gJxiZQTYrMfLn+mD0sz5+ndSzwymp2hDcYJTyT0MOn0yuWzj8phlIvO72gTHA== +"@babel/plugin-transform-class-static-block@^7.24.4", "@babel/plugin-transform-class-static-block@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" + integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-class-static-block" "^7.14.5" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-classes@^7.24.5", "@babel/plugin-transform-classes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.6.tgz#0cc198c02720d4eeb091004843477659c6b37977" - integrity sha512-+fN+NO2gh8JtRmDSOB6gaCVo36ha8kfCW1nMq2Gc0DABln0VcHN4PrALDvF5/diLzIRKptC7z/d7Lp64zk92Fg== +"@babel/plugin-transform-classes@^7.24.5", "@babel/plugin-transform-classes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" + integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" + "@babel/traverse" "^7.25.9" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.24.1", "@babel/plugin-transform-computed-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.6.tgz#7a1765c01cdfe59c320d2d0f37a4dc4aecd14df1" - integrity sha512-cRzPobcfRP0ZtuIEkA8QzghoUpSB3X3qSH5W2+FzG+VjWbJXExtx0nbRqwumdBN1x/ot2SlTNQLfBCnPdzp6kg== +"@babel/plugin-transform-computed-properties@^7.24.1", "@babel/plugin-transform-computed-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" + integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/template" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/template" "^7.25.9" -"@babel/plugin-transform-destructuring@^7.24.5", "@babel/plugin-transform-destructuring@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.6.tgz#bdd1a6c90ffb2bfd13b6007b13316eeafc97cb53" - integrity sha512-YLW6AE5LQpk5npNXL7i/O+U9CE4XsBCuRPgyjl1EICZYKmcitV+ayuuUGMJm2lC1WWjXYszeTnIxF/dq/GhIZQ== +"@babel/plugin-transform-destructuring@^7.24.5", "@babel/plugin-transform-destructuring@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" + integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-dotall-regex@^7.24.1", "@babel/plugin-transform-dotall-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.6.tgz#5a6b3148ec5f4f274ff48cebea90565087cad126" - integrity sha512-rCXPnSEKvkm/EjzOtLoGvKseK+dS4kZwx1HexO3BtRtgL0fQ34awHn34aeSHuXtZY2F8a1X8xqBBPRtOxDVmcA== +"@babel/plugin-transform-dotall-regex@^7.24.1", "@babel/plugin-transform-dotall-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" + integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-duplicate-keys@^7.24.1", "@babel/plugin-transform-duplicate-keys@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.6.tgz#2716301227cf7cd4fdadcbe4353ce191f8b3dc8a" - integrity sha512-/8Odwp/aVkZwPFJMllSbawhDAO3UJi65foB00HYnK/uXvvCPm0TAXSByjz1mpRmp0q6oX2SIxpkUOpPFHk7FLA== +"@babel/plugin-transform-duplicate-keys@^7.24.1", "@babel/plugin-transform-duplicate-keys@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" + integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-dynamic-import@^7.24.1", "@babel/plugin-transform-dynamic-import@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.6.tgz#b477177761d56b15a4ba42a83be31cf72d757acf" - integrity sha512-vpq8SSLRTBLOHUZHSnBqVo0AKX3PBaoPs2vVzYVWslXDTDIpwAcCDtfhUcHSQQoYoUvcFPTdC8TZYXu9ZnLT/w== +"@babel/plugin-transform-duplicate-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz#6f7259b4de127721a08f1e5165b852fcaa696d31" + integrity sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-exponentiation-operator@^7.24.1", "@babel/plugin-transform-exponentiation-operator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.6.tgz#011e9e1a429f91b024af572530873ca571f9ef06" - integrity sha512-EemYpHtmz0lHE7hxxxYEuTYOOBZ43WkDgZ4arQ4r+VX9QHuNZC+WH3wUWmRNvR8ECpTRne29aZV6XO22qpOtdA== +"@babel/plugin-transform-dynamic-import@^7.24.1", "@babel/plugin-transform-dynamic-import@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" + integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== dependencies: - "@babel/helper-builder-binary-assignment-operator-visitor" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-export-namespace-from@^7.24.1", "@babel/plugin-transform-export-namespace-from@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.6.tgz#b64ded74d9afb3db5d47d93996c4df69f15ac97c" - integrity sha512-inXaTM1SVrIxCkIJ5gqWiozHfFMStuGbGJAxZFBoHcRRdDP0ySLb3jH6JOwmfiinPwyMZqMBX+7NBDCO4z0NSA== +"@babel/plugin-transform-exponentiation-operator@^7.24.1", "@babel/plugin-transform-exponentiation-operator@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" + integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-export-namespace-from@^7.24.1", "@babel/plugin-transform-export-namespace-from@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" + integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-flow-strip-types@^7.16.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.6.tgz#dfd9d1c90e74335bc68d82f41ad9224960a4de84" - integrity sha512-1l8b24NoCpaQ13Vi6FtLG1nv6kNoi8PWvQb1AYO7GHZDpFfBYc3lbXArx1lP2KRt8b4pej1eWc/zrRmsQTfOdQ== + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz#2904c85a814e7abb1f4850b8baf4f07d0a2389d4" + integrity sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-flow" "^7.24.6" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/plugin-syntax-flow" "^7.26.0" -"@babel/plugin-transform-for-of@^7.24.1", "@babel/plugin-transform-for-of@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.6.tgz#7f31780bd0c582b546372c0c0da9d9d56731e0a2" - integrity sha512-n3Sf72TnqK4nw/jziSqEl1qaWPbCRw2CziHH+jdRYvw4J6yeCzsj4jdw8hIntOEeDGTmHVe2w4MVL44PN0GMzg== +"@babel/plugin-transform-for-of@^7.24.1", "@babel/plugin-transform-for-of@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" + integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-function-name@^7.24.1", "@babel/plugin-transform-function-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.6.tgz#60d1de3f6fd816a3e3bf9538578a64527e1b9c97" - integrity sha512-sOajCu6V0P1KPljWHKiDq6ymgqB+vfo3isUS4McqW1DZtvSVU2v/wuMhmRmkg3sFoq6GMaUUf8W4WtoSLkOV/Q== +"@babel/plugin-transform-function-name@^7.24.1", "@babel/plugin-transform-function-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" + integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== dependencies: - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/plugin-transform-json-strings@^7.24.1", "@babel/plugin-transform-json-strings@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.6.tgz#a84639180ea1f9001bb5e6dc01921235ab05ad8b" - integrity sha512-Uvgd9p2gUnzYJxVdBLcU0KurF8aVhkmVyMKW4MIY1/BByvs3EBpv45q01o7pRTVmTvtQq5zDlytP3dcUgm7v9w== +"@babel/plugin-transform-json-strings@^7.24.1", "@babel/plugin-transform-json-strings@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" + integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-json-strings" "^7.8.3" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-literals@^7.24.1", "@babel/plugin-transform-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.6.tgz#7f44f2871d7a4456030b0540858046f0b7bc6b18" - integrity sha512-f2wHfR2HF6yMj+y+/y07+SLqnOSwRp8KYLpQKOzS58XLVlULhXbiYcygfXQxJlMbhII9+yXDwOUFLf60/TL5tw== +"@babel/plugin-transform-literals@^7.24.1", "@babel/plugin-transform-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" + integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-logical-assignment-operators@^7.24.1", "@babel/plugin-transform-logical-assignment-operators@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.6.tgz#9cc7baa5629866566562c159dc1eae7569810f33" - integrity sha512-EKaWvnezBCMkRIHxMJSIIylzhqK09YpiJtDbr2wsXTwnO0TxyjMUkaw4RlFIZMIS0iDj0KyIg7H7XCguHu/YDA== +"@babel/plugin-transform-logical-assignment-operators@^7.24.1", "@babel/plugin-transform-logical-assignment-operators@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" + integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-member-expression-literals@^7.24.1", "@babel/plugin-transform-member-expression-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.6.tgz#5d3681ca201ac6909419cc51ac082a6ba4c5c756" - integrity sha512-9g8iV146szUo5GWgXpRbq/GALTnY+WnNuRTuRHWWFfWGbP9ukRL0aO/jpu9dmOPikclkxnNsjY8/gsWl6bmZJQ== +"@babel/plugin-transform-member-expression-literals@^7.24.1", "@babel/plugin-transform-member-expression-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" + integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-amd@^7.24.1", "@babel/plugin-transform-modules-amd@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.6.tgz#09aeac7acb7913496aaaafdc64f40683e0db7e41" - integrity sha512-eAGogjZgcwqAxhyFgqghvoHRr+EYRQPFjUXrTYKBRb5qPnAVxOOglaxc4/byHqjvq/bqO2F3/CGwTHsgKJYHhQ== +"@babel/plugin-transform-modules-amd@^7.24.1", "@babel/plugin-transform-modules-amd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" + integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-commonjs@^7.24.1", "@babel/plugin-transform-modules-commonjs@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.6.tgz#1b8269902f25bd91ca6427230d4735ddd1e1283e" - integrity sha512-JEV8l3MHdmmdb7S7Cmx6rbNEjRCgTQMZxllveHO0mx6uiclB0NflCawlQQ6+o5ZrwjUBYPzHm2XoK4wqGVUFuw== +"@babel/plugin-transform-modules-commonjs@^7.24.1", "@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3": + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" + integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-simple-access" "^7.24.6" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-systemjs@^7.24.1", "@babel/plugin-transform-modules-systemjs@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.6.tgz#c54eb53fe16f9b82d320abd76762d0320e3f9393" - integrity sha512-xg1Z0J5JVYxtpX954XqaaAT6NpAY6LtZXvYFCJmGFJWwtlz2EmJoR8LycFRGNE8dBKizGWkGQZGegtkV8y8s+w== +"@babel/plugin-transform-modules-systemjs@^7.24.1", "@babel/plugin-transform-modules-systemjs@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" + integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== dependencies: - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" -"@babel/plugin-transform-modules-umd@^7.24.1", "@babel/plugin-transform-modules-umd@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.6.tgz#c4ef8b6d4da230b8dc87e81cd66986728952f89b" - integrity sha512-esRCC/KsSEUvrSjv5rFYnjZI6qv4R1e/iHQrqwbZIoRJqk7xCvEUiN7L1XrmW5QSmQe3n1XD88wbgDTWLbVSyg== +"@babel/plugin-transform-modules-umd@^7.24.1", "@babel/plugin-transform-modules-umd@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" + integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== dependencies: - "@babel/helper-module-transforms" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-module-transforms" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.6.tgz#352ee2861ab8705320029f80238cf26a92ba65d5" - integrity sha512-6DneiCiu91wm3YiNIGDWZsl6GfTTbspuj/toTEqLh9d4cx50UIzSdg+T96p8DuT7aJOBRhFyaE9ZvTHkXrXr6Q== +"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" + integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-new-target@^7.24.1", "@babel/plugin-transform-new-target@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.6.tgz#fc024294714705113720d5e3dc0f9ad7abdbc289" - integrity sha512-f8liz9JG2Va8A4J5ZBuaSdwfPqN6axfWRK+y66fjKYbwf9VBLuq4WxtinhJhvp1w6lamKUwLG0slK2RxqFgvHA== +"@babel/plugin-transform-new-target@^7.24.1", "@babel/plugin-transform-new-target@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" + integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1", "@babel/plugin-transform-nullish-coalescing-operator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.6.tgz#12b83b3cdfd1cd2066350e36e4fb912ab194545e" - integrity sha512-+QlAiZBMsBK5NqrBWFXCYeXyiU1y7BQ/OYaiPAcQJMomn5Tyg+r5WuVtyEuvTbpV7L25ZSLfE+2E9ywj4FD48A== +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1", "@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": + version "7.26.6" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" + integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" + "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-numeric-separator@^7.24.1", "@babel/plugin-transform-numeric-separator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.6.tgz#d9115669cc85aa91fbfb15f88f2226332cf4946a" - integrity sha512-6voawq8T25Jvvnc4/rXcWZQKKxUNZcKMS8ZNrjxQqoRFernJJKjE3s18Qo6VFaatG5aiX5JV1oPD7DbJhn0a4Q== +"@babel/plugin-transform-numeric-separator@^7.24.1", "@babel/plugin-transform-numeric-separator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" + integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-object-rest-spread@^7.24.5", "@babel/plugin-transform-object-rest-spread@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.6.tgz#68d763f69955f9e599c405c6c876f5be46b47d8a" - integrity sha512-OKmi5wiMoRW5Smttne7BwHM8s/fb5JFs+bVGNSeHWzwZkWXWValR1M30jyXo1s/RaqgwwhEC62u4rFH/FBcBPg== +"@babel/plugin-transform-object-rest-spread@^7.24.5", "@babel/plugin-transform-object-rest-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" + integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== dependencies: - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.24.6" + "@babel/helper-compilation-targets" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" -"@babel/plugin-transform-object-super@^7.24.1", "@babel/plugin-transform-object-super@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.6.tgz#9cbe6f995bed343a7ab8daf0416dac057a9c3e27" - integrity sha512-N/C76ihFKlZgKfdkEYKtaRUtXZAgK7sOY4h2qrbVbVTXPrKGIi8aww5WGe/+Wmg8onn8sr2ut6FXlsbu/j6JHg== +"@babel/plugin-transform-object-super@^7.24.1", "@babel/plugin-transform-object-super@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" + integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-replace-supers" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-replace-supers" "^7.25.9" -"@babel/plugin-transform-optional-catch-binding@^7.24.1", "@babel/plugin-transform-optional-catch-binding@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.6.tgz#c81e90a971aad898e56f2b75a358e6c4855aeba3" - integrity sha512-L5pZ+b3O1mSzJ71HmxSCmTVd03VOT2GXOigug6vDYJzE5awLI7P1g0wFcdmGuwSDSrQ0L2rDOe/hHws8J1rv3w== +"@babel/plugin-transform-optional-catch-binding@^7.24.1", "@babel/plugin-transform-optional-catch-binding@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" + integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-optional-chaining@^7.24.5", "@babel/plugin-transform-optional-chaining@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.6.tgz#3d636b3ed8b5a506f93e4d4675fc95754d7594f5" - integrity sha512-cHbqF6l1QP11OkYTYQ+hhVx1E017O5ZcSPXk9oODpqhcAD1htsWG2NpHrrhthEO2qZomLK0FXS+u7NfrkF5aOQ== +"@babel/plugin-transform-optional-chaining@^7.24.5", "@babel/plugin-transform-optional-chaining@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" + integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-parameters@^7.24.5", "@babel/plugin-transform-parameters@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.6.tgz#7aee86dfedd2fc0136fecbe6f7649fc02d86ab22" - integrity sha512-ST7guE8vLV+vI70wmAxuZpIKzVjvFX9Qs8bl5w6tN/6gOypPWUmMQL2p7LJz5E63vEGrDhAiYetniJFyBH1RkA== +"@babel/plugin-transform-parameters@^7.24.5", "@babel/plugin-transform-parameters@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" + integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-methods@^7.24.1", "@babel/plugin-transform-private-methods@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.6.tgz#258e1f859a52ff7b30ad556598224c192defcda7" - integrity sha512-T9LtDI0BgwXOzyXrvgLTT8DFjCC/XgWLjflczTLXyvxbnSR/gpv0hbmzlHE/kmh9nOvlygbamLKRo6Op4yB6aw== +"@babel/plugin-transform-private-methods@^7.24.1", "@babel/plugin-transform-private-methods@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" + integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-property-in-object@^7.24.5", "@babel/plugin-transform-private-property-in-object@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.6.tgz#59ff09a099f62213112cf348e96b6b11957d1f28" - integrity sha512-Qu/ypFxCY5NkAnEhCF86Mvg3NSabKsh/TPpBVswEdkGl7+FbsYHy1ziRqJpwGH4thBdQHh8zx+z7vMYmcJ7iaQ== +"@babel/plugin-transform-private-property-in-object@^7.24.5", "@babel/plugin-transform-private-property-in-object@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" + integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-property-literals@^7.24.1", "@babel/plugin-transform-property-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.6.tgz#243c4faabe811c405e9443059a58e834bf95dfd1" - integrity sha512-oARaglxhRsN18OYsnPTpb8TcKQWDYNsPNmTnx5++WOAsUJ0cSC/FZVlIJCKvPbU4yn/UXsS0551CFKJhN0CaMw== +"@babel/plugin-transform-property-literals@^7.24.1", "@babel/plugin-transform-property-literals@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" + integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.24.1", "@babel/plugin-transform-react-display-name@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.6.tgz#2a10c732c2c87a8f06e4413fb4a14e76e6c67a99" - integrity sha512-/3iiEEHDsJuj9QU09gbyWGSUxDboFcD7Nj6dnHIlboWSodxXAoaY/zlNMHeYAC0WsERMqgO9a7UaM77CsYgWcg== +"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.24.1", "@babel/plugin-transform-react-display-name@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" + integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx-development@^7.22.5", "@babel/plugin-transform-react-jsx-development@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.24.6.tgz#e662058e8795b5fccd24c5bdd2b328728aef3305" - integrity sha512-F7EsNp5StNDouSSdYyDSxh4J+xvj/JqG+Cb6s2fA+jCyHOzigG5vTwgH8tU2U8Voyiu5zCG9bAK49wTr/wPH0w== +"@babel/plugin-transform-react-jsx-development@^7.22.5", "@babel/plugin-transform-react-jsx-development@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz#8fd220a77dd139c07e25225a903b8be8c829e0d7" + integrity sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw== dependencies: - "@babel/plugin-transform-react-jsx" "^7.24.6" + "@babel/plugin-transform-react-jsx" "^7.25.9" "@babel/plugin-transform-react-jsx-self@^7.18.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.24.6.tgz#4fa4870d594d6840d724d2006d0f98b19be6f502" - integrity sha512-FfZfHXtQ5jYPQsCRyLpOv2GeLIIJhs8aydpNh39vRDjhD411XcfWDni5i7OjP/Rs8GAtTn7sWFFELJSHqkIxYg== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" + integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-react-jsx-source@^7.19.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.24.6.tgz#4e1503f24ca5fccb1fc7f20c57426899d5ce5c1f" - integrity sha512-BQTBCXmFRreU3oTUXcGKuPOfXAGb1liNY4AvvFKsOBAJ89RKcTsIrSsnMYkj59fNa66OFKnSa4AJZfy5Y4B9WA== + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" + integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx@^7.23.4", "@babel/plugin-transform-react-jsx@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.6.tgz#4ca3660ca663d20095455571615d6263986cdfe4" - integrity sha512-pCtPHhpRZHfwdA5G1Gpk5mIzMA99hv0R8S/Ket50Rw+S+8hkt3wBWqdqHaPw0CuUYxdshUgsPiLQ5fAs4ASMhw== +"@babel/plugin-transform-react-jsx@^7.23.4", "@babel/plugin-transform-react-jsx@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" + integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-jsx" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/types" "^7.25.9" -"@babel/plugin-transform-react-pure-annotations@^7.24.1", "@babel/plugin-transform-react-pure-annotations@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.6.tgz#d2bad8d70c3635cb63a69ee66c9c891f9392435c" - integrity sha512-0HoDQlFJJkXRyV2N+xOpUETbKHcouSwijRQbKWVtxsPoq5bbB30qZag9/pSc5xcWVYjTHlLsBsY+hZDnzQTPNw== +"@babel/plugin-transform-react-pure-annotations@^7.24.1", "@babel/plugin-transform-react-pure-annotations@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz#ea1c11b2f9dbb8e2d97025f43a3b5bc47e18ae62" + integrity sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-regenerator@^7.24.1", "@babel/plugin-transform-regenerator@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.6.tgz#ed10cf0c13619365e15459f88d1b915ac57ffc24" - integrity sha512-SMDxO95I8WXRtXhTAc8t/NFQUT7VYbIWwJCJgEli9ml4MhqUMh4S6hxgH6SmAC3eAQNWCDJFxcFeEt9w2sDdXg== +"@babel/plugin-transform-regenerator@^7.24.1", "@babel/plugin-transform-regenerator@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" + integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.24.1", "@babel/plugin-transform-reserved-words@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.6.tgz#9eb16cbf339fcea0a46677716c775afb5ef14245" - integrity sha512-DcrgFXRRlK64dGE0ZFBPD5egM2uM8mgfrvTMOSB2yKzOtjpGegVYkzh3s1zZg1bBck3nkXiaOamJUqK3Syk+4A== +"@babel/plugin-transform-regexp-modifiers@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz#2f5837a5b5cd3842a919d8147e9903cc7455b850" + integrity sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-reserved-words@^7.24.1", "@babel/plugin-transform-reserved-words@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" + integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-runtime@7.24.3": version "7.24.3" @@ -1080,52 +933,52 @@ semver "^6.3.1" "@babel/plugin-transform-runtime@^7.16.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.6.tgz#1e3256246004c3724b8e07c7cb25e35913c4e373" - integrity sha512-W3gQydMb0SY99y/2lV0Okx2xg/8KzmZLQsLaiCmwNRl1kKomz14VurEm+2TossUb+sRvBCnGe+wx8KtIgDtBbQ== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" + integrity sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ== dependencies: - "@babel/helper-module-imports" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-corejs3 "^0.10.6" babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.24.1", "@babel/plugin-transform-shorthand-properties@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.6.tgz#ef734ebccc428d2174c7bb36015d0800faf5381e" - integrity sha512-xnEUvHSMr9eOWS5Al2YPfc32ten7CXdH7Zwyyk7IqITg4nX61oHj+GxpNvl+y5JHjfN3KXE2IV55wAWowBYMVw== +"@babel/plugin-transform-shorthand-properties@^7.24.1", "@babel/plugin-transform-shorthand-properties@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" + integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-spread@^7.24.1", "@babel/plugin-transform-spread@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.6.tgz#a56cecbd8617675531d1b79f5b755b7613aa0822" - integrity sha512-h/2j7oIUDjS+ULsIrNZ6/TKG97FgmEk1PXryk/HQq6op4XUUUwif2f69fJrzK0wza2zjCS1xhXmouACaWV5uPA== +"@babel/plugin-transform-spread@^7.24.1", "@babel/plugin-transform-spread@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" + integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-skip-transparent-expression-wrappers" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-sticky-regex@^7.24.1", "@babel/plugin-transform-sticky-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.6.tgz#1a78127731fea87d954bed193840986a38f04327" - integrity sha512-fN8OcTLfGmYv7FnDrsjodYBo1DhPL3Pze/9mIIE2MGCT1KgADYIOD7rEglpLHZj8PZlC/JFX5WcD+85FLAQusw== +"@babel/plugin-transform-sticky-regex@^7.24.1", "@babel/plugin-transform-sticky-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" + integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-template-literals@^7.24.1", "@babel/plugin-transform-template-literals@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.6.tgz#aaf2ae157acd0e5c9265dba8ac0a439f8d2a6303" - integrity sha512-BJbEqJIcKwrqUP+KfUIkxz3q8VzXe2R8Wv8TaNgO1cx+nNavxn/2+H8kp9tgFSOL6wYPPEgFvU6IKS4qoGqhmg== +"@babel/plugin-transform-template-literals@^7.24.1", "@babel/plugin-transform-template-literals@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" + integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-typeof-symbol@^7.24.5", "@babel/plugin-transform-typeof-symbol@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.6.tgz#3d02da23ebcc8f1982ddcd1f2581cf3ee4e58762" - integrity sha512-IshCXQ+G9JIFJI7bUpxTE/oA2lgVLAIK8q1KdJNoPXOpvRaNjMySGuvLfBw/Xi2/1lLo953uE8hyYSDW3TSYig== +"@babel/plugin-transform-typeof-symbol@^7.24.5", "@babel/plugin-transform-typeof-symbol@^7.26.7": + version "7.26.7" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz#d0e33acd9223744c1e857dbd6fa17bd0a3786937" + integrity sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-transform-typescript@7.24.5": version "7.24.5" @@ -1137,46 +990,47 @@ "@babel/helper-plugin-utils" "^7.24.5" "@babel/plugin-syntax-typescript" "^7.24.1" -"@babel/plugin-transform-typescript@^7.24.1", "@babel/plugin-transform-typescript@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.6.tgz#339c6127a783c32e28a5b591e6c666f899b57db0" - integrity sha512-H0i+hDLmaYYSt6KU9cZE0gb3Cbssa/oxWis7PX4ofQzbvsfix9Lbh8SRk7LCPDlLWJHUiFeHU0qRRpF/4Zv7mQ== +"@babel/plugin-transform-typescript@^7.24.1", "@babel/plugin-transform-typescript@^7.25.9": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" + integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== dependencies: - "@babel/helper-annotate-as-pure" "^7.24.6" - "@babel/helper-create-class-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/plugin-syntax-typescript" "^7.24.6" + "@babel/helper-annotate-as-pure" "^7.25.9" + "@babel/helper-create-class-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" + "@babel/plugin-syntax-typescript" "^7.25.9" -"@babel/plugin-transform-unicode-escapes@^7.24.1", "@babel/plugin-transform-unicode-escapes@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.6.tgz#c8ddca8fd5bacece837a4e27bd3b7ed64580d1a8" - integrity sha512-bKl3xxcPbkQQo5eX9LjjDpU2xYHeEeNQbOhj0iPvetSzA+Tu9q/o5lujF4Sek60CM6MgYvOS/DJuwGbiEYAnLw== +"@babel/plugin-transform-unicode-escapes@^7.24.1", "@babel/plugin-transform-unicode-escapes@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" + integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-property-regex@^7.24.1", "@babel/plugin-transform-unicode-property-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.6.tgz#e66297d5d452db0b0be56515e3d0e10b7d33fb32" - integrity sha512-8EIgImzVUxy15cZiPii9GvLZwsy7Vxc+8meSlR3cXFmBIl5W5Tn9LGBf7CDKkHj4uVfNXCJB8RsVfnmY61iedA== +"@babel/plugin-transform-unicode-property-regex@^7.24.1", "@babel/plugin-transform-unicode-property-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" + integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-regex@^7.24.1", "@babel/plugin-transform-unicode-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.6.tgz#2001e7d87ed709eea145e0b65fb5f93c3c0e225b" - integrity sha512-pssN6ExsvxaKU638qcWb81RrvvgZom3jDgU/r5xFZ7TONkZGFf4MhI2ltMb8OcQWhHyxgIavEU+hgqtbKOmsPA== +"@babel/plugin-transform-unicode-regex@^7.24.1", "@babel/plugin-transform-unicode-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" + integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-sets-regex@^7.24.1", "@babel/plugin-transform-unicode-sets-regex@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.6.tgz#f18b7292222aee85c155258ceb345a146a070a46" - integrity sha512-quiMsb28oXWIDK0gXLALOJRXLgICLiulqdZGOaPPd0vRT7fQp74NtdADAVu+D8s00C+0Xs0MxVP0VKF/sZEUgw== +"@babel/plugin-transform-unicode-sets-regex@^7.24.1", "@babel/plugin-transform-unicode-sets-regex@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" + integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== dependencies: - "@babel/helper-create-regexp-features-plugin" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" + "@babel/helper-create-regexp-features-plugin" "^7.25.9" + "@babel/helper-plugin-utils" "^7.25.9" "@babel/preset-env@7.24.5": version "7.24.5" @@ -1266,90 +1120,78 @@ semver "^6.3.1" "@babel/preset-env@^7.11.0", "@babel/preset-env@^7.16.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.6.tgz#a5a55bc70e5ff1ed7f872067e2a9d65ff917ad6f" - integrity sha512-CrxEAvN7VxfjOG8JNF2Y/eMqMJbZPZ185amwGUBp8D9USK90xQmv7dLdFSa+VbD7fdIqcy/Mfv7WtzG8+/qxKg== + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.9.tgz#2ec64e903d0efe743699f77a10bdf7955c2123c3" + integrity sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ== dependencies: - "@babel/compat-data" "^7.24.6" - "@babel/helper-compilation-targets" "^7.24.6" - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.6" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.6" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.6" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.6" + "@babel/compat-data" "^7.26.8" + "@babel/helper-compilation-targets" "^7.26.5" + "@babel/helper-plugin-utils" "^7.26.5" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.25.9" + "@babel/plugin-bugfix-safari-class-field-initializer-scope" "^7.25.9" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.25.9" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.25.9" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.25.9" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.6" - "@babel/plugin-syntax-import-attributes" "^7.24.6" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" + "@babel/plugin-syntax-import-assertions" "^7.26.0" + "@babel/plugin-syntax-import-attributes" "^7.26.0" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.6" - "@babel/plugin-transform-async-generator-functions" "^7.24.6" - "@babel/plugin-transform-async-to-generator" "^7.24.6" - "@babel/plugin-transform-block-scoped-functions" "^7.24.6" - "@babel/plugin-transform-block-scoping" "^7.24.6" - "@babel/plugin-transform-class-properties" "^7.24.6" - "@babel/plugin-transform-class-static-block" "^7.24.6" - "@babel/plugin-transform-classes" "^7.24.6" - "@babel/plugin-transform-computed-properties" "^7.24.6" - "@babel/plugin-transform-destructuring" "^7.24.6" - "@babel/plugin-transform-dotall-regex" "^7.24.6" - "@babel/plugin-transform-duplicate-keys" "^7.24.6" - "@babel/plugin-transform-dynamic-import" "^7.24.6" - "@babel/plugin-transform-exponentiation-operator" "^7.24.6" - "@babel/plugin-transform-export-namespace-from" "^7.24.6" - "@babel/plugin-transform-for-of" "^7.24.6" - "@babel/plugin-transform-function-name" "^7.24.6" - "@babel/plugin-transform-json-strings" "^7.24.6" - "@babel/plugin-transform-literals" "^7.24.6" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.6" - "@babel/plugin-transform-member-expression-literals" "^7.24.6" - "@babel/plugin-transform-modules-amd" "^7.24.6" - "@babel/plugin-transform-modules-commonjs" "^7.24.6" - "@babel/plugin-transform-modules-systemjs" "^7.24.6" - "@babel/plugin-transform-modules-umd" "^7.24.6" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.24.6" - "@babel/plugin-transform-new-target" "^7.24.6" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.6" - "@babel/plugin-transform-numeric-separator" "^7.24.6" - "@babel/plugin-transform-object-rest-spread" "^7.24.6" - "@babel/plugin-transform-object-super" "^7.24.6" - "@babel/plugin-transform-optional-catch-binding" "^7.24.6" - "@babel/plugin-transform-optional-chaining" "^7.24.6" - "@babel/plugin-transform-parameters" "^7.24.6" - "@babel/plugin-transform-private-methods" "^7.24.6" - "@babel/plugin-transform-private-property-in-object" "^7.24.6" - "@babel/plugin-transform-property-literals" "^7.24.6" - "@babel/plugin-transform-regenerator" "^7.24.6" - "@babel/plugin-transform-reserved-words" "^7.24.6" - "@babel/plugin-transform-shorthand-properties" "^7.24.6" - "@babel/plugin-transform-spread" "^7.24.6" - "@babel/plugin-transform-sticky-regex" "^7.24.6" - "@babel/plugin-transform-template-literals" "^7.24.6" - "@babel/plugin-transform-typeof-symbol" "^7.24.6" - "@babel/plugin-transform-unicode-escapes" "^7.24.6" - "@babel/plugin-transform-unicode-property-regex" "^7.24.6" - "@babel/plugin-transform-unicode-regex" "^7.24.6" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.6" + "@babel/plugin-transform-arrow-functions" "^7.25.9" + "@babel/plugin-transform-async-generator-functions" "^7.26.8" + "@babel/plugin-transform-async-to-generator" "^7.25.9" + "@babel/plugin-transform-block-scoped-functions" "^7.26.5" + "@babel/plugin-transform-block-scoping" "^7.25.9" + "@babel/plugin-transform-class-properties" "^7.25.9" + "@babel/plugin-transform-class-static-block" "^7.26.0" + "@babel/plugin-transform-classes" "^7.25.9" + "@babel/plugin-transform-computed-properties" "^7.25.9" + "@babel/plugin-transform-destructuring" "^7.25.9" + "@babel/plugin-transform-dotall-regex" "^7.25.9" + "@babel/plugin-transform-duplicate-keys" "^7.25.9" + "@babel/plugin-transform-duplicate-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-dynamic-import" "^7.25.9" + "@babel/plugin-transform-exponentiation-operator" "^7.26.3" + "@babel/plugin-transform-export-namespace-from" "^7.25.9" + "@babel/plugin-transform-for-of" "^7.26.9" + "@babel/plugin-transform-function-name" "^7.25.9" + "@babel/plugin-transform-json-strings" "^7.25.9" + "@babel/plugin-transform-literals" "^7.25.9" + "@babel/plugin-transform-logical-assignment-operators" "^7.25.9" + "@babel/plugin-transform-member-expression-literals" "^7.25.9" + "@babel/plugin-transform-modules-amd" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.26.3" + "@babel/plugin-transform-modules-systemjs" "^7.25.9" + "@babel/plugin-transform-modules-umd" "^7.25.9" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.25.9" + "@babel/plugin-transform-new-target" "^7.25.9" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.26.6" + "@babel/plugin-transform-numeric-separator" "^7.25.9" + "@babel/plugin-transform-object-rest-spread" "^7.25.9" + "@babel/plugin-transform-object-super" "^7.25.9" + "@babel/plugin-transform-optional-catch-binding" "^7.25.9" + "@babel/plugin-transform-optional-chaining" "^7.25.9" + "@babel/plugin-transform-parameters" "^7.25.9" + "@babel/plugin-transform-private-methods" "^7.25.9" + "@babel/plugin-transform-private-property-in-object" "^7.25.9" + "@babel/plugin-transform-property-literals" "^7.25.9" + "@babel/plugin-transform-regenerator" "^7.25.9" + "@babel/plugin-transform-regexp-modifiers" "^7.26.0" + "@babel/plugin-transform-reserved-words" "^7.25.9" + "@babel/plugin-transform-shorthand-properties" "^7.25.9" + "@babel/plugin-transform-spread" "^7.25.9" + "@babel/plugin-transform-sticky-regex" "^7.25.9" + "@babel/plugin-transform-template-literals" "^7.26.8" + "@babel/plugin-transform-typeof-symbol" "^7.26.7" + "@babel/plugin-transform-unicode-escapes" "^7.25.9" + "@babel/plugin-transform-unicode-property-regex" "^7.25.9" + "@babel/plugin-transform-unicode-regex" "^7.25.9" + "@babel/plugin-transform-unicode-sets-regex" "^7.25.9" "@babel/preset-modules" "0.1.6-no-external-plugins" babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-corejs3 "^0.11.0" babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" + core-js-compat "^3.40.0" semver "^6.3.1" "@babel/preset-modules@0.1.6-no-external-plugins": @@ -1374,16 +1216,16 @@ "@babel/plugin-transform-react-pure-annotations" "^7.24.1" "@babel/preset-react@^7.16.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.6.tgz#92eace66dce577e5263113eb82235a0d45096cae" - integrity sha512-8mpzh1bWvmINmwM3xpz6ahu57mNaWavMm+wBNjQ4AFu1nghKBiIRET7l/Wmj4drXany/BBGjJZngICcD98F1iw== + version "7.26.3" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.26.3.tgz#7c5e028d623b4683c1f83a0bd4713b9100560caa" + integrity sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-transform-react-display-name" "^7.24.6" - "@babel/plugin-transform-react-jsx" "^7.24.6" - "@babel/plugin-transform-react-jsx-development" "^7.24.6" - "@babel/plugin-transform-react-pure-annotations" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-transform-react-display-name" "^7.25.9" + "@babel/plugin-transform-react-jsx" "^7.25.9" + "@babel/plugin-transform-react-jsx-development" "^7.25.9" + "@babel/plugin-transform-react-pure-annotations" "^7.25.9" "@babel/preset-typescript@7.24.1": version "7.24.1" @@ -1397,97 +1239,57 @@ "@babel/plugin-transform-typescript" "^7.24.1" "@babel/preset-typescript@^7.16.0": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.6.tgz#27057470fb981c31338bdb897fc3d9aa0cb7dab2" - integrity sha512-U10aHPDnokCFRXgyT/MaIRTivUu2K/mu0vJlwRS9LxJmJet+PFQNKpggPyFCUtC6zWSBPjvxjnpNkAn3Uw2m5w== + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" + integrity sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg== dependencies: - "@babel/helper-plugin-utils" "^7.24.6" - "@babel/helper-validator-option" "^7.24.6" - "@babel/plugin-syntax-jsx" "^7.24.6" - "@babel/plugin-transform-modules-commonjs" "^7.24.6" - "@babel/plugin-transform-typescript" "^7.24.6" + "@babel/helper-plugin-utils" "^7.25.9" + "@babel/helper-validator-option" "^7.25.9" + "@babel/plugin-syntax-jsx" "^7.25.9" + "@babel/plugin-transform-modules-commonjs" "^7.25.9" + "@babel/plugin-transform-typescript" "^7.25.9" -"@babel/regjsgen@^0.8.0": - version "0.8.0" - resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" - integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== - -"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.23.2", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== +"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.8.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" + integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.24.0", "@babel/template@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.6.tgz#048c347b2787a6072b24c723664c8d02b67a44f9" - integrity sha512-3vgazJlLwNXi9jhrR1ef8qiB65L1RK90+lEQwv4OxveHnqC3BfmnHdgySwRLzf6akhlOYenT+b7AfWq+a//AHw== +"@babel/template@^7.24.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" + integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.26.9" + "@babel/types" "^7.26.9" -"@babel/template@^7.25.0": - version "7.25.0" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.0.tgz#e733dc3134b4fede528c15bc95e89cb98c52592a" - integrity sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q== +"@babel/traverse@^7.24.5", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" + integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/parser" "^7.25.0" - "@babel/types" "^7.25.0" - -"@babel/traverse@^7.24.5", "@babel/traverse@^7.24.6": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.6.tgz#0941ec50cdeaeacad0911eb67ae227a4f8424edc" - integrity sha512-OsNjaJwT9Zn8ozxcfoBc+RaHdj3gFmCmYoQLUII1o6ZrUwku0BMg80FoOTPx+Gi6XhcQxAYE4xyjPTo4SxEQqw== - dependencies: - "@babel/code-frame" "^7.24.6" - "@babel/generator" "^7.24.6" - "@babel/helper-environment-visitor" "^7.24.6" - "@babel/helper-function-name" "^7.24.6" - "@babel/helper-hoist-variables" "^7.24.6" - "@babel/helper-split-export-declaration" "^7.24.6" - "@babel/parser" "^7.24.6" - "@babel/types" "^7.24.6" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.9" + "@babel/parser" "^7.26.9" + "@babel/template" "^7.26.9" + "@babel/types" "^7.26.9" debug "^4.3.1" globals "^11.1.0" -"@babel/traverse@^7.24.7", "@babel/traverse@^7.25.2": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.6.tgz#04fad980e444f182ecf1520504941940a90fea41" - integrity sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ== +"@babel/types@^7.21.3", "@babel/types@^7.24.5", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" + integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== dependencies: - "@babel/code-frame" "^7.24.7" - "@babel/generator" "^7.25.6" - "@babel/parser" "^7.25.6" - "@babel/template" "^7.25.0" - "@babel/types" "^7.25.6" - debug "^4.3.1" - globals "^11.1.0" + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" -"@babel/types@^7.21.3", "@babel/types@^7.24.7", "@babel/types@^7.25.0", "@babel/types@^7.25.2", "@babel/types@^7.25.4", "@babel/types@^7.25.6": - version "7.25.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.6.tgz#893942ddb858f32ae7a004ec9d3a76b3463ef8e6" - integrity sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw== - dependencies: - "@babel/helper-string-parser" "^7.24.8" - "@babel/helper-validator-identifier" "^7.24.7" - to-fast-properties "^2.0.0" - -"@babel/types@^7.24.5", "@babel/types@^7.24.6", "@babel/types@^7.4.4": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912" - integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ== - dependencies: - "@babel/helper-string-parser" "^7.24.6" - "@babel/helper-validator-identifier" "^7.24.6" - to-fast-properties "^2.0.0" - -"@bcoe/v8-coverage@^0.2.3": - version "0.2.3" - resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" - integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== +"@bcoe/v8-coverage@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz#bbe12dca5b4ef983a0d0af4b07b9bc90ea0ababa" + integrity sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA== "@braintree/sanitize-url@6.0.2": version "6.0.2" @@ -1514,10 +1316,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== -"@esbuild/aix-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537" - integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g== +"@esbuild/aix-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" + integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== "@esbuild/android-arm64@0.19.10": version "0.19.10" @@ -1529,10 +1331,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== -"@esbuild/android-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9" - integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg== +"@esbuild/android-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" + integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== "@esbuild/android-arm@0.19.10": version "0.19.10" @@ -1544,10 +1346,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== -"@esbuild/android-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995" - integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w== +"@esbuild/android-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" + integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== "@esbuild/android-x64@0.19.10": version "0.19.10" @@ -1559,10 +1361,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== -"@esbuild/android-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98" - integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg== +"@esbuild/android-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" + integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== "@esbuild/darwin-arm64@0.19.10": version "0.19.10" @@ -1574,10 +1376,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== -"@esbuild/darwin-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb" - integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA== +"@esbuild/darwin-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" + integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== "@esbuild/darwin-x64@0.19.10": version "0.19.10" @@ -1589,10 +1391,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== -"@esbuild/darwin-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0" - integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA== +"@esbuild/darwin-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" + integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== "@esbuild/freebsd-arm64@0.19.10": version "0.19.10" @@ -1604,10 +1406,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== -"@esbuild/freebsd-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911" - integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw== +"@esbuild/freebsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" + integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== "@esbuild/freebsd-x64@0.19.10": version "0.19.10" @@ -1619,10 +1421,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== -"@esbuild/freebsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c" - integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw== +"@esbuild/freebsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" + integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== "@esbuild/linux-arm64@0.19.10": version "0.19.10" @@ -1634,10 +1436,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== -"@esbuild/linux-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5" - integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A== +"@esbuild/linux-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" + integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== "@esbuild/linux-arm@0.19.10": version "0.19.10" @@ -1649,10 +1451,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== -"@esbuild/linux-arm@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c" - integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg== +"@esbuild/linux-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" + integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== "@esbuild/linux-ia32@0.19.10": version "0.19.10" @@ -1664,10 +1466,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== -"@esbuild/linux-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa" - integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig== +"@esbuild/linux-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" + integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== "@esbuild/linux-loong64@0.19.10": version "0.19.10" @@ -1679,10 +1481,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== -"@esbuild/linux-loong64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5" - integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ== +"@esbuild/linux-loong64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" + integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== "@esbuild/linux-mips64el@0.19.10": version "0.19.10" @@ -1694,10 +1496,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== -"@esbuild/linux-mips64el@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa" - integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA== +"@esbuild/linux-mips64el@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" + integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== "@esbuild/linux-ppc64@0.19.10": version "0.19.10" @@ -1709,10 +1511,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== -"@esbuild/linux-ppc64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20" - integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg== +"@esbuild/linux-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" + integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== "@esbuild/linux-riscv64@0.19.10": version "0.19.10" @@ -1724,10 +1526,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== -"@esbuild/linux-riscv64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300" - integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg== +"@esbuild/linux-riscv64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" + integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== "@esbuild/linux-s390x@0.19.10": version "0.19.10" @@ -1739,10 +1541,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== -"@esbuild/linux-s390x@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685" - integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ== +"@esbuild/linux-s390x@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" + integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== "@esbuild/linux-x64@0.19.10": version "0.19.10" @@ -1754,10 +1556,15 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== -"@esbuild/linux-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff" - integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw== +"@esbuild/linux-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" + integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== + +"@esbuild/netbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" + integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== "@esbuild/netbsd-x64@0.19.10": version "0.19.10" @@ -1769,10 +1576,15 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== -"@esbuild/netbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6" - integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ== +"@esbuild/netbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" + integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw== + +"@esbuild/openbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" + integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== "@esbuild/openbsd-x64@0.19.10": version "0.19.10" @@ -1784,10 +1596,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== -"@esbuild/openbsd-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf" - integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ== +"@esbuild/openbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" + integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== "@esbuild/sunos-x64@0.19.10": version "0.19.10" @@ -1799,10 +1611,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== -"@esbuild/sunos-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f" - integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w== +"@esbuild/sunos-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" + integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== "@esbuild/win32-arm64@0.19.10": version "0.19.10" @@ -1814,10 +1626,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== -"@esbuild/win32-arm64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90" - integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ== +"@esbuild/win32-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" + integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== "@esbuild/win32-ia32@0.19.10": version "0.19.10" @@ -1829,10 +1641,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== -"@esbuild/win32-ia32@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23" - integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ== +"@esbuild/win32-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" + integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== "@esbuild/win32-x64@0.19.10": version "0.19.10" @@ -1844,22 +1656,22 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== -"@esbuild/win32-x64@0.20.2": - version "0.20.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc" - integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ== +"@esbuild/win32-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" + integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== "@eslint-community/eslint-utils@^4.2.0": - version "4.4.0" - resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" - integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + version "4.4.1" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56" + integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA== dependencies: - eslint-visitor-keys "^3.3.0" + eslint-visitor-keys "^3.4.3" "@eslint-community/regexpp@^4.4.0": - version "4.10.0" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" - integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + version "4.12.1" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0" + integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ== "@eslint/eslintrc@^0.4.3": version "0.4.3" @@ -2375,13 +2187,6 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== -"@jest/expect-utils@^29.7.0": - version "29.7.0" - resolved "https://registry.yarnpkg.com/@jest/expect-utils/-/expect-utils-29.7.0.tgz#023efe5d26a8a70f21677d0a1afc0f0a44e3a1c6" - integrity sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA== - dependencies: - jest-get-type "^29.6.3" - "@jest/schemas@^29.6.3": version "29.6.3" resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" @@ -2389,22 +2194,10 @@ dependencies: "@sinclair/typebox" "^0.27.8" -"@jest/types@^29.6.3": - version "29.6.3" - resolved "https://registry.yarnpkg.com/@jest/types/-/types-29.6.3.tgz#1131f8cf634e7e84c5e77bab12f052af585fba59" - integrity sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw== - dependencies: - "@jest/schemas" "^29.6.3" - "@types/istanbul-lib-coverage" "^2.0.0" - "@types/istanbul-reports" "^3.0.0" - "@types/node" "*" - "@types/yargs" "^17.0.8" - chalk "^4.0.0" - "@jridgewell/gen-mapping@^0.3.5": - version "0.3.5" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" - integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== dependencies: "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" @@ -2428,17 +2221,12 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14": - version "1.4.15" - resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" - integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== - -"@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== -"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": +"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": version "0.3.25" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== @@ -2524,15 +2312,104 @@ "@nodelib/fs.scandir" "2.1.5" fastq "^1.6.0" +"@parcel/watcher-android-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1" + integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA== + +"@parcel/watcher-darwin-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67" + integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw== + +"@parcel/watcher-darwin-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8" + integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg== + +"@parcel/watcher-freebsd-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b" + integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ== + +"@parcel/watcher-linux-arm-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1" + integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA== + +"@parcel/watcher-linux-arm-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e" + integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q== + +"@parcel/watcher-linux-arm64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30" + integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w== + +"@parcel/watcher-linux-arm64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2" + integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg== + +"@parcel/watcher-linux-x64-glibc@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e" + integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A== + +"@parcel/watcher-linux-x64-musl@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee" + integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg== + +"@parcel/watcher-win32-arm64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243" + integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw== + +"@parcel/watcher-win32-ia32@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6" + integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ== + +"@parcel/watcher-win32-x64@2.5.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947" + integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA== + +"@parcel/watcher@^2.4.1": + version "2.5.1" + resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200" + integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg== + dependencies: + detect-libc "^1.0.3" + is-glob "^4.0.3" + micromatch "^4.0.5" + node-addon-api "^7.0.0" + optionalDependencies: + "@parcel/watcher-android-arm64" "2.5.1" + "@parcel/watcher-darwin-arm64" "2.5.1" + "@parcel/watcher-darwin-x64" "2.5.1" + "@parcel/watcher-freebsd-x64" "2.5.1" + "@parcel/watcher-linux-arm-glibc" "2.5.1" + "@parcel/watcher-linux-arm-musl" "2.5.1" + "@parcel/watcher-linux-arm64-glibc" "2.5.1" + "@parcel/watcher-linux-arm64-musl" "2.5.1" + "@parcel/watcher-linux-x64-glibc" "2.5.1" + "@parcel/watcher-linux-x64-musl" "2.5.1" + "@parcel/watcher-win32-arm64" "2.5.1" + "@parcel/watcher-win32-ia32" "2.5.1" + "@parcel/watcher-win32-x64" "2.5.1" + "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@polka/url@^1.0.0-next.20", "@polka/url@^1.0.0-next.24": - version "1.0.0-next.25" - resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.25.tgz#f077fdc0b5d0078d30893396ff4827a13f99e817" - integrity sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ== + version "1.0.0-next.28" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73" + integrity sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw== "@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2": version "1.1.2" @@ -2836,14 +2713,13 @@ "@rollup/pluginutils" "^3.1.0" "@rollup/plugin-node-resolve@^15.2.3": - version "15.2.3" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.3.tgz#e5e0b059bd85ca57489492f295ce88c2d4b0daf9" - integrity sha512-j/lym8nf5E21LwBT4Df1VD6hRO2L2iwUeUmP7litikRsVp1H6NWx20NEp0Y7su+7XGc476GnXXc4kFeZNGmaSQ== + version "15.3.1" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz#66008953c2524be786aa319d49e32f2128296a78" + integrity sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA== dependencies: "@rollup/pluginutils" "^5.0.1" "@types/resolve" "1.20.2" deepmerge "^4.2.2" - is-builtin-module "^3.2.1" is-module "^1.0.0" resolve "^1.22.1" @@ -2882,98 +2758,118 @@ picomatch "^2.2.2" "@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.5": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0" - integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g== + version "5.1.4" + resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" + integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== dependencies: "@types/estree" "^1.0.0" estree-walker "^2.0.2" - picomatch "^2.3.1" + picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27" - integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ== +"@rollup/rollup-android-arm-eabi@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" + integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== -"@rollup/rollup-android-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203" - integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA== +"@rollup/rollup-android-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" + integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== -"@rollup/rollup-darwin-arm64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096" - integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w== +"@rollup/rollup-darwin-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" + integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== -"@rollup/rollup-darwin-x64@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c" - integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA== +"@rollup/rollup-darwin-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" + integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== -"@rollup/rollup-linux-arm-gnueabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8" - integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA== +"@rollup/rollup-freebsd-arm64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" + integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== -"@rollup/rollup-linux-arm-musleabihf@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549" - integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A== +"@rollup/rollup-freebsd-x64@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" + integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== -"@rollup/rollup-linux-arm64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577" - integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw== +"@rollup/rollup-linux-arm-gnueabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" + integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== -"@rollup/rollup-linux-arm64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c" - integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ== +"@rollup/rollup-linux-arm-musleabihf@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" + integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== -"@rollup/rollup-linux-powerpc64le-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf" - integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA== +"@rollup/rollup-linux-arm64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" + integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== -"@rollup/rollup-linux-riscv64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9" - integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg== +"@rollup/rollup-linux-arm64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" + integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== -"@rollup/rollup-linux-s390x-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec" - integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg== +"@rollup/rollup-linux-loongarch64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" + integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== -"@rollup/rollup-linux-x64-gnu@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942" - integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w== +"@rollup/rollup-linux-powerpc64le-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" + integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== -"@rollup/rollup-linux-x64-musl@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d" - integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg== +"@rollup/rollup-linux-riscv64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" + integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== -"@rollup/rollup-win32-arm64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf" - integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA== +"@rollup/rollup-linux-s390x-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" + integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== -"@rollup/rollup-win32-ia32-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54" - integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg== +"@rollup/rollup-linux-x64-gnu@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" + integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== -"@rollup/rollup-win32-x64-msvc@4.18.0": - version "4.18.0" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" - integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== +"@rollup/rollup-linux-x64-musl@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678" + integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== + +"@rollup/rollup-win32-arm64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" + integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== + +"@rollup/rollup-win32-ia32-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" + integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== + +"@rollup/rollup-win32-x64-msvc@4.34.8": + version "4.34.8" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" + integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== + +"@rtsao/scc@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" + integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== "@rushstack/eslint-patch@^1.1.0": - version "1.10.3" - resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.3.tgz#391d528054f758f81e53210f1a1eebcf1a8b1d20" - integrity sha512-qC/xYId4NMebE6w/V33Fh9gWxLgURiNYgVNObbJl2LZv0GUUItCcCqC5axQSwRaAgaxl2mELq1rMzlswaQ0Zxg== + version "1.10.5" + resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.10.5.tgz#3a1c12c959010a55c17d46b395ed3047b545c246" + integrity sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A== "@sentry-internal/browser-utils@9.0.1": version "9.0.1" @@ -3184,25 +3080,23 @@ lz-string "^1.5.0" pretty-format "^27.0.2" -"@testing-library/jest-dom@5.16.2": - version "5.16.2" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.16.2.tgz#f329b36b44aa6149cd6ced9adf567f8b6aa1c959" - integrity sha512-6ewxs1MXWwsBFZXIk4nKKskWANelkdUehchEOokHsN8X7c2eKXGw+77aRV63UU8f/DTSVUPLaGxdrj4lN7D/ug== +"@testing-library/jest-dom@6.6.3": + version "6.6.3" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz#26ba906cf928c0f8172e182c6fe214eb4f9f2bd2" + integrity sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA== dependencies: - "@babel/runtime" "^7.9.2" - "@types/testing-library__jest-dom" "^5.9.1" + "@adobe/css-tools" "^4.4.0" aria-query "^5.0.0" chalk "^3.0.0" - css "^3.0.0" css.escape "^1.5.1" - dom-accessibility-api "^0.5.6" - lodash "^4.17.15" + dom-accessibility-api "^0.6.3" + lodash "^4.17.21" redent "^3.0.0" -"@testing-library/react@16.0.0": - version "16.0.0" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.0.0.tgz#0a1e0c7a3de25841c3591b8cb7fb0cf0c0a27321" - integrity sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ== +"@testing-library/react@16.2.0": + version "16.2.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-16.2.0.tgz#c96126ee01a49cdb47175721911b4a9432afc601" + integrity sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ== dependencies: "@babel/runtime" "^7.12.5" @@ -3222,21 +3116,21 @@ integrity sha512-/ceqdqeRraGolFTcfoXNiqjyQhZzbINDngeoAq9GoHa8PPK1yNzTaxWjA6BFWp5Ua9JpXEMSS4s5i9tS0hOJtw== "@types/d3-scale-chromatic@^3.0.0": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz#fc0db9c10e789c351f4c42d96f31f2e4df8f5644" - integrity sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" + integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== "@types/d3-scale@^4.0.3": - version "4.0.8" - resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.8.tgz#d409b5f9dcf63074464bf8ddfb8ee5a1f95945bb" - integrity sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ== + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" + integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== dependencies: "@types/d3-time" "*" "@types/d3-time@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.3.tgz#3c186bbd9d12b9d84253b6be6487ca56b54f88be" - integrity sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw== + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== "@types/debug@^4.0.0": version "4.1.12" @@ -3245,7 +3139,7 @@ dependencies: "@types/ms" "*" -"@types/eslint-scope@^3.7.3": +"@types/eslint-scope@^3.7.3", "@types/eslint-scope@^3.7.7": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== @@ -3254,17 +3148,17 @@ "@types/estree" "*" "@types/eslint@*": - version "8.56.10" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.10.tgz#eb2370a73bf04a901eeba8f22595c7ee0f7eb58d" - integrity sha512-Shavhk87gCtY2fhXDctcfS3e6FdxWkCx1iUZ9eEUbh7rTqlZT0/IzOkCOVt0fCjcFuZ9FPYfuezTBImfHCDBGQ== + version "9.6.1" + resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-9.6.1.tgz#d5795ad732ce81715f27f75da913004a56751584" + integrity sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag== dependencies: "@types/estree" "*" "@types/json-schema" "*" -"@types/estree@*", "@types/estree@1.0.5", "@types/estree@^1.0.0", "@types/estree@^1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/estree@*", "@types/estree@1.0.6", "@types/estree@^1.0.0", "@types/estree@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50" + integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw== "@types/estree@0.0.39": version "0.0.39" @@ -3276,33 +3170,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== -"@types/istanbul-lib-coverage@*", "@types/istanbul-lib-coverage@^2.0.0": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz#7739c232a1fee9b4d3ce8985f314c0c6d33549d7" - integrity sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w== - -"@types/istanbul-lib-report@*": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz#53047614ae72e19fc0401d872de3ae2b4ce350bf" - integrity sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA== - dependencies: - "@types/istanbul-lib-coverage" "*" - -"@types/istanbul-reports@^3.0.0": - version "3.0.4" - resolved "https://registry.yarnpkg.com/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz#0f03e3d2f670fbdac586e34b433783070cc16f54" - integrity sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ== - dependencies: - "@types/istanbul-lib-report" "*" - -"@types/jest@*": - version "29.5.12" - resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.12.tgz#7f7dc6eb4cf246d2474ed78744b05d06ce025544" - integrity sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw== - dependencies: - expect "^29.0.0" - pretty-format "^29.0.0" - "@types/jest@27.4.0": version "27.4.0" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" @@ -3329,9 +3196,9 @@ "@types/lodash" "*" "@types/lodash@*": - version "4.17.4" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.4.tgz#0303b64958ee070059e3a7184048a55159fe20b7" - integrity sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ== + version "4.17.15" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.15.tgz#12d4af0ed17cc7600ce1f9980cec48fc17ad1e89" + integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw== "@types/mdast@^3.0.0": version "3.0.15" @@ -3341,24 +3208,24 @@ "@types/unist" "^2" "@types/ms@*": - version "0.7.34" - resolved "https://registry.yarnpkg.com/@types/ms/-/ms-0.7.34.tgz#10964ba0dee6ac4cd462e2795b6bebd407303433" - integrity sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g== + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node@*", "@types/node@>=13.7.0", "@types/node@^20": - version "20.12.12" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.12.tgz#7cbecdf902085cec634fdb362172dfe12b8f2050" - integrity sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw== - dependencies: - undici-types "~5.26.4" - -"@types/node@>=12.12.47": - version "22.13.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.2.tgz#6f401c5ccadac75354f5652128e9fcc3b0cf23b7" - integrity sha512-Z+r8y3XL9ZpI2EY52YYygAFmo2/oWfNSj4BCpAXE2McAexDk8VcnBMGC9Djn9gTKt4d2T/hhXqmPzo4hfIXtTg== +"@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": + version "22.13.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511" + integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg== dependencies: undici-types "~6.20.0" +"@types/node@^20": + version "20.17.19" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.19.tgz#0f2869555719bef266ca6e1827fcdca903c1a697" + integrity sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A== + dependencies: + undici-types "~6.19.2" + "@types/pako@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/pako/-/pako-1.0.3.tgz#2e61c2b02020b5f44e2e5e946dfac74f4ec33c58" @@ -3374,25 +3241,16 @@ resolved "https://registry.yarnpkg.com/@types/pica/-/pica-5.1.3.tgz#5ef64529a1f83f7d6586a8bf75a8a00be32aca02" integrity sha512-13SEyETRE5psd9bE0AmN+0M1tannde2fwHfLVaVIljkbL9V0OfFvKwCicyeDvVYLkmjQWEydbAlsDsmjrdyTOg== -"@types/prop-types@*": - version "15.7.12" - resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6" - integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q== +"@types/react-dom@19.0.4": + version "19.0.4" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.0.4.tgz#bedba97f9346bd4c0fe5d39e689713804ec9ac89" + integrity sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg== -"@types/react-dom@18.2.0": - version "18.2.0" - resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.0.tgz#374f28074bb117f56f58c4f3f71753bebb545156" - integrity sha512-8yQrvS6sMpSwIovhPOwfyNf2Wz6v/B62LFSVYQ85+Rq3tLsBIG7rP5geMxaijTUxSkrO6RzN/IRuIAADYQsleA== +"@types/react@19.0.10": + version "19.0.10" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.0.10.tgz#d0c66dafd862474190fe95ce11a68de69ed2b0eb" + integrity sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g== dependencies: - "@types/react" "*" - -"@types/react@*", "@types/react@18.2.0": - version "18.2.0" - resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.0.tgz#15cda145354accfc09a18d2f2305f9fc099ada21" - integrity sha512-0FLj93y5USLHdnhIhABk83rm8XEGA7kH3cr+YUlvxoUGp1xNt/DINUMvqPxLyOQMzLmZe8i4RTHbvb8MC7NmrA== - dependencies: - "@types/prop-types" "*" - "@types/scheduler" "*" csstype "^3.0.2" "@types/resize-observer-browser@0.1.7": @@ -3405,11 +3263,6 @@ resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.20.2.tgz#97d26e00cd4a0423b4af620abecf3e6f442b7975" integrity sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q== -"@types/scheduler@*": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@types/scheduler/-/scheduler-0.23.0.tgz#0a6655b3e2708eaabca00b7372fafd7a792a7b09" - integrity sha512-YIoDCTH3Af6XM5VuwGG/QL/CJqga1Zm3NkU3HZ4ZHK2fRMPYP1VczsTUqtsf43PH/iJNVlPHAo2oWX7BSdB2Hw== - "@types/semver@^7.3.12": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" @@ -3422,39 +3275,15 @@ dependencies: socket.io-client "*" -"@types/stack-utils@^2.0.0": - version "2.0.3" - resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" - integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== - -"@types/testing-library__jest-dom@^5.9.1": - version "5.14.9" - resolved "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.9.tgz#0fb1e6a0278d87b6737db55af5967570b67cb466" - integrity sha512-FSYhIjFlfOpGSRyVoMBMuS3ws5ehFQODymf3vlI7U1K8c7PHwWwFY7VREfmsuzHSOnoKs/9/Y983ayOs7eRzqw== - dependencies: - "@types/jest" "*" - "@types/trusted-types@^2.0.2": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" integrity sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw== "@types/unist@^2", "@types/unist@^2.0.0": - version "2.0.10" - resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc" - integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA== - -"@types/yargs-parser@*": - version "21.0.3" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" - integrity sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ== - -"@types/yargs@^17.0.8": - version "17.0.32" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.32.tgz#030774723a2f7faafebf645f4e5a48371dca6229" - integrity sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog== - dependencies: - "@types/yargs-parser" "*" + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== "@types/yauzl@^2.9.1": version "2.10.3" @@ -3565,64 +3394,80 @@ magic-string "^0.27.0" react-refresh "^0.14.0" -"@vitest/coverage-v8@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-2.0.5.tgz#411961ce4fd1177a32b4dd74ab576ed3b859155e" - integrity sha512-qeFcySCg5FLO2bHHSa0tAZAOnAUbp4L6/A5JDuj9+bt53JREl8hpLjLHEWF0e/gWc8INVpJaqA7+Ene2rclpZg== +"@vitest/coverage-v8@3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-3.0.7.tgz#44768ff9f6c541c5ea66ce8a3ed56a79a0e7f518" + integrity sha512-Av8WgBJLTrfLOer0uy3CxjlVuWK4CzcLBndW1Nm2vI+3hZ2ozHututkfc7Blu1u6waeQ7J8gzPK/AsBRnWA5mQ== dependencies: "@ampproject/remapping" "^2.3.0" - "@bcoe/v8-coverage" "^0.2.3" - debug "^4.3.5" + "@bcoe/v8-coverage" "^1.0.2" + debug "^4.4.0" istanbul-lib-coverage "^3.2.2" istanbul-lib-report "^3.0.1" istanbul-lib-source-maps "^5.0.6" istanbul-reports "^3.1.7" - magic-string "^0.30.10" - magicast "^0.3.4" - std-env "^3.7.0" + magic-string "^0.30.17" + magicast "^0.3.5" + std-env "^3.8.0" test-exclude "^7.0.1" - tinyrainbow "^1.2.0" + tinyrainbow "^2.0.0" -"@vitest/expect@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.0.5.tgz#f3745a6a2c18acbea4d39f5935e913f40d26fa86" - integrity sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA== +"@vitest/expect@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-3.0.6.tgz#30993c0841203d2243826ee04fb25463eb86e20d" + integrity sha512-zBduHf/ja7/QRX4HdP1DSq5XrPgdN+jzLOwaTq/0qZjYfgETNFCKf9nOAp2j3hmom3oTbczuUzrzg9Hafh7hNg== dependencies: - "@vitest/spy" "2.0.5" - "@vitest/utils" "2.0.5" - chai "^5.1.1" - tinyrainbow "^1.2.0" + "@vitest/spy" "3.0.6" + "@vitest/utils" "3.0.6" + chai "^5.2.0" + tinyrainbow "^2.0.0" -"@vitest/pretty-format@2.0.5", "@vitest/pretty-format@^2.0.5": +"@vitest/mocker@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-3.0.6.tgz#28287cfdc06a8b0318344e5c240d774e43014cd0" + integrity sha512-KPztr4/tn7qDGZfqlSPQoF2VgJcKxnDNhmfR3VgZ6Fy1bO8T9Fc1stUiTXtqz0yG24VpD00pZP5f8EOFknjNuQ== + dependencies: + "@vitest/spy" "3.0.6" + estree-walker "^3.0.3" + magic-string "^0.30.17" + +"@vitest/pretty-format@2.0.5": version "2.0.5" resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.0.5.tgz#91d2e6d3a7235c742e1a6cc50e7786e2f2979b1e" integrity sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ== dependencies: tinyrainbow "^1.2.0" -"@vitest/runner@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.0.5.tgz#89197e712bb93513537d6876995a4843392b2a84" - integrity sha512-TfRfZa6Bkk9ky4tW0z20WKXFEwwvWhRY+84CnSEtq4+3ZvDlJyY32oNTJtM7AW9ihW90tX/1Q78cb6FjoAs+ig== +"@vitest/pretty-format@3.0.6", "@vitest/pretty-format@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.0.6.tgz#a828569818b666a6e955c9af8129e6b0d2968ee6" + integrity sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg== dependencies: - "@vitest/utils" "2.0.5" - pathe "^1.1.2" + tinyrainbow "^2.0.0" -"@vitest/snapshot@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.0.5.tgz#a2346bc5013b73c44670c277c430e0334690a162" - integrity sha512-SgCPUeDFLaM0mIUHfaArq8fD2WbaXG/zVXjRupthYfYGzc8ztbFbu6dUNOblBG7XLMR1kEhS/DNnfCZ2IhdDew== +"@vitest/runner@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.0.6.tgz#a07b54674b1a495424f2ea959a28a6096c17c33b" + integrity sha512-JopP4m/jGoaG1+CBqubV/5VMbi7L+NQCJTu1J1Pf6YaUbk7bZtaq5CX7p+8sY64Sjn1UQ1XJparHfcvTTdu9cA== dependencies: - "@vitest/pretty-format" "2.0.5" - magic-string "^0.30.10" - pathe "^1.1.2" + "@vitest/utils" "3.0.6" + pathe "^2.0.3" -"@vitest/spy@2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.0.5.tgz#590fc07df84a78b8e9dd976ec2090920084a2b9f" - integrity sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA== +"@vitest/snapshot@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-3.0.6.tgz#e962319e487b2e8da7ad39322b5e0b39ea639d7a" + integrity sha512-qKSmxNQwT60kNwwJHMVwavvZsMGXWmngD023OHSgn873pV0lylK7dwBTfYP7e4URy5NiBCHHiQGA9DHkYkqRqg== dependencies: - tinyspy "^3.0.0" + "@vitest/pretty-format" "3.0.6" + magic-string "^0.30.17" + pathe "^2.0.3" + +"@vitest/spy@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-3.0.6.tgz#3a50ec0ab11e8f729cdaa938a6d271b12547cea1" + integrity sha512-HfOGx/bXtjy24fDlTOpgiAEJbRfFxoX3zIGagCqACkFKKZ/TTOE6gYMKXlqecvxEndKFuNHcHqP081ggZ2yM0Q== + dependencies: + tinyspy "^3.0.2" "@vitest/ui@2.0.5": version "2.0.5" @@ -3647,6 +3492,15 @@ loupe "^3.1.1" tinyrainbow "^1.2.0" +"@vitest/utils@3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-3.0.6.tgz#be4246ab46a076db1e49b9e0479bdd9a7f65782f" + integrity sha512-18ktZpf4GQFTbf9jK543uspU03Q2qya7ZGya5yiZ0Gx0nnnalBvd5ZBislbl2EhLjM8A8rt4OilqKG7QwcGkvQ== + dependencies: + "@vitest/pretty-format" "3.0.6" + loupe "^3.1.3" + tinyrainbow "^2.0.0" + "@webassemblyjs/ast@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" @@ -3655,43 +3509,43 @@ "@webassemblyjs/helper-numbers" "1.11.1" "@webassemblyjs/helper-wasm-bytecode" "1.11.1" -"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" - integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== +"@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" + integrity sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ== dependencies: - "@webassemblyjs/helper-numbers" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-numbers" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" "@webassemblyjs/floating-point-hex-parser@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== -"@webassemblyjs/floating-point-hex-parser@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" - integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== +"@webassemblyjs/floating-point-hex-parser@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" + integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== "@webassemblyjs/helper-api-error@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== -"@webassemblyjs/helper-api-error@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" - integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== +"@webassemblyjs/helper-api-error@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" + integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== "@webassemblyjs/helper-buffer@1.11.1": version "1.11.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== -"@webassemblyjs/helper-buffer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" - integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== +"@webassemblyjs/helper-buffer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" + integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== "@webassemblyjs/helper-numbers@1.11.1": version "1.11.1" @@ -3702,13 +3556,13 @@ "@webassemblyjs/helper-api-error" "1.11.1" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-numbers@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" - integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== +"@webassemblyjs/helper-numbers@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" + integrity sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.6" - "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/floating-point-hex-parser" "1.13.2" + "@webassemblyjs/helper-api-error" "1.13.2" "@xtuc/long" "4.2.2" "@webassemblyjs/helper-wasm-bytecode@1.11.1": @@ -3716,10 +3570,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== -"@webassemblyjs/helper-wasm-bytecode@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" - integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== +"@webassemblyjs/helper-wasm-bytecode@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" + integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== "@webassemblyjs/helper-wasm-section@1.11.1": version "1.11.1" @@ -3731,15 +3585,15 @@ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" "@webassemblyjs/wasm-gen" "1.11.1" -"@webassemblyjs/helper-wasm-section@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" - integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== +"@webassemblyjs/helper-wasm-section@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" + integrity sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/ieee754@1.11.1": version "1.11.1" @@ -3748,10 +3602,10 @@ dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/ieee754@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" - integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== +"@webassemblyjs/ieee754@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" + integrity sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw== dependencies: "@xtuc/ieee754" "^1.2.0" @@ -3762,10 +3616,10 @@ dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/leb128@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" - integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== +"@webassemblyjs/leb128@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" + integrity sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw== dependencies: "@xtuc/long" "4.2.2" @@ -3774,10 +3628,10 @@ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== -"@webassemblyjs/utf8@1.11.6": - version "1.11.6" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" - integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== +"@webassemblyjs/utf8@1.13.2": + version "1.13.2" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" + integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== "@webassemblyjs/wasm-edit@1.11.1": version "1.11.1" @@ -3793,19 +3647,19 @@ "@webassemblyjs/wasm-parser" "1.11.1" "@webassemblyjs/wast-printer" "1.11.1" -"@webassemblyjs/wasm-edit@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" - integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== +"@webassemblyjs/wasm-edit@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" + integrity sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/helper-wasm-section" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-opt" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" - "@webassemblyjs/wast-printer" "1.12.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/helper-wasm-section" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-opt" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" + "@webassemblyjs/wast-printer" "1.14.1" "@webassemblyjs/wasm-gen@1.11.1": version "1.11.1" @@ -3818,16 +3672,16 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" -"@webassemblyjs/wasm-gen@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" - integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== +"@webassemblyjs/wasm-gen@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" + integrity sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" "@webassemblyjs/wasm-opt@1.11.1": version "1.11.1" @@ -3839,15 +3693,15 @@ "@webassemblyjs/wasm-gen" "1.11.1" "@webassemblyjs/wasm-parser" "1.11.1" -"@webassemblyjs/wasm-opt@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" - integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== +"@webassemblyjs/wasm-opt@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" + integrity sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-buffer" "1.12.1" - "@webassemblyjs/wasm-gen" "1.12.1" - "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-buffer" "1.14.1" + "@webassemblyjs/wasm-gen" "1.14.1" + "@webassemblyjs/wasm-parser" "1.14.1" "@webassemblyjs/wasm-parser@1.11.1": version "1.11.1" @@ -3861,17 +3715,17 @@ "@webassemblyjs/leb128" "1.11.1" "@webassemblyjs/utf8" "1.11.1" -"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" - integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== +"@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" + integrity sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ== dependencies: - "@webassemblyjs/ast" "1.12.1" - "@webassemblyjs/helper-api-error" "1.11.6" - "@webassemblyjs/helper-wasm-bytecode" "1.11.6" - "@webassemblyjs/ieee754" "1.11.6" - "@webassemblyjs/leb128" "1.11.6" - "@webassemblyjs/utf8" "1.11.6" + "@webassemblyjs/ast" "1.14.1" + "@webassemblyjs/helper-api-error" "1.13.2" + "@webassemblyjs/helper-wasm-bytecode" "1.13.2" + "@webassemblyjs/ieee754" "1.13.2" + "@webassemblyjs/leb128" "1.13.2" + "@webassemblyjs/utf8" "1.13.2" "@webassemblyjs/wast-printer@1.11.1": version "1.11.1" @@ -3881,12 +3735,12 @@ "@webassemblyjs/ast" "1.11.1" "@xtuc/long" "4.2.2" -"@webassemblyjs/wast-printer@1.12.1": - version "1.12.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" - integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== +"@webassemblyjs/wast-printer@1.14.1": + version "1.14.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" + integrity sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw== dependencies: - "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.2.0": @@ -3926,7 +3780,7 @@ abab@^2.0.6: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -acorn-import-assertions@^1.7.6, acorn-import-assertions@^1.9.0: +acorn-import-assertions@^1.7.6: version "1.9.0" resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== @@ -3937,19 +3791,21 @@ acorn-jsx@^5.3.1: integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== acorn-walk@^8.0.0: - version "8.3.2" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" - integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.7.1, acorn@^8.8.2: - version "8.11.3" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" - integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +acorn@^8.0.4, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.7.1, acorn@^8.8.2: + version "8.14.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" + integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== agent-base@6: version "6.0.2" @@ -3996,14 +3852,14 @@ ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: uri-js "^4.2.2" ajv@^8.0.0, ajv@^8.0.1, ajv@^8.6.0, ajv@^8.9.0: - version "8.14.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.14.0.tgz#f514ddfd4756abb200e1704414963620a625ebbb" - integrity sha512-oYs1UUtO97ZO2lJ4bwnWeQW8/zvOIQLGKcvPTsWmvc2SYgBb+upuNS5NxoLaMU4h8Ju3Nbj6Cq8mD2LQoqVKFA== + version "8.17.1" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.17.1.tgz#37d9a5c776af6bc92d7f4f9510eba4c0a60d11a6" + integrity sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g== dependencies: fast-deep-equal "^3.1.3" + fast-uri "^3.0.1" json-schema-traverse "^1.0.0" require-from-string "^2.0.2" - uri-js "^4.4.1" ansi-colors@^4.1.1: version "4.1.3" @@ -4088,22 +3944,27 @@ aria-hidden@^1.1.1: dependencies: tslib "^2.0.0" -aria-query@5.3.0, aria-query@^5.0.0, aria-query@^5.3.0: +aria-query@5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== dependencies: dequal "^2.0.3" -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== - dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" +aria-query@^5.0.0, aria-query@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== -array-includes@^3.1.6, array-includes@^3.1.7: +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== + dependencies: + call-bound "^1.0.3" + is-array-buffer "^3.0.5" + +array-includes@^3.1.6, array-includes@^3.1.8: version "3.1.8" resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d" integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ== @@ -4120,7 +3981,7 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array.prototype.findlast@^1.2.4: +array.prototype.findlast@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== @@ -4132,7 +3993,7 @@ array.prototype.findlast@^1.2.4: es-object-atoms "^1.0.0" es-shim-unscopables "^1.0.2" -array.prototype.findlastindex@^1.2.3: +array.prototype.findlastindex@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d" integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ== @@ -4145,59 +4006,48 @@ array.prototype.findlastindex@^1.2.3: es-shim-unscopables "^1.0.2" array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" - integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" - integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.toreversed@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" - integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== - dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - es-shim-unscopables "^1.0.0" - -array.prototype.tosorted@^1.1.1, array.prototype.tosorted@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" - integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== - dependencies: - call-bind "^1.0.5" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.1.0" + es-abstract "^1.23.5" es-shim-unscopables "^1.0.2" -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== +array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2, array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.tosorted@^1.1.1, array.prototype.tosorted@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" + integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.3" + es-errors "^1.3.0" + es-shim-unscopables "^1.0.2" + +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" assertion-error@^1.1.0: version "1.1.0" @@ -4219,6 +4069,11 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== +async-function@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/async-function/-/async-function-1.0.0.tgz#509c9fca60eaf85034c6829838188e4e4c8ffb2b" + integrity sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA== + async@^2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -4227,9 +4082,9 @@ async@^2.6.4: lodash "^4.17.14" async@^3.2.3: - version "3.2.5" - resolved "https://registry.yarnpkg.com/async/-/async-3.2.5.tgz#ebd52a8fdaf7a2289a24df399f8d8485c8a46b66" - integrity sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg== + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== asynckit@^0.4.0: version "0.4.0" @@ -4241,11 +4096,6 @@ at-least-node@^1.0.0: resolved "https://registry.yarnpkg.com/at-least-node/-/at-least-node-1.0.0.tgz#602cd4b46e844ad4effc92a8011a3c46e0238dc2" integrity sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg== -atob@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" - integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== - autoprefixer@10.4.7: version "10.4.7" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.7.tgz#1db8d195f41a52ca5069b7593be167618edbbedf" @@ -4265,17 +4115,15 @@ available-typed-arrays@^1.0.7: dependencies: possible-typed-array-names "^1.0.0" -axe-core@=4.7.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" - integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== +axe-core@^4.10.0: + version "4.10.2" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.10.2.tgz#85228e3e1d8b8532a27659b332e39b7fa0e022df" + integrity sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w== -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== - dependencies: - dequal "^2.0.3" +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== babel-code-frame@^6.26.0: version "6.26.0" @@ -4332,28 +4180,36 @@ babel-plugin-macros@^3.1.0: resolve "^1.19.0" babel-plugin-polyfill-corejs2@^0.4.10: - version "0.4.11" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33" - integrity sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q== + version "0.4.12" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz#ca55bbec8ab0edeeef3d7b8ffd75322e210879a9" + integrity sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og== dependencies: "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.6.2" + "@babel/helper-define-polyfill-provider" "^0.6.3" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: - version "0.10.4" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" - integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== - dependencies: - "@babel/helper-define-polyfill-provider" "^0.6.1" - core-js-compat "^3.36.1" - -babel-plugin-polyfill-regenerator@^0.6.1: - version "0.6.2" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz#addc47e240edd1da1058ebda03021f382bba785e" - integrity sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg== +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4, babel-plugin-polyfill-corejs3@^0.10.6: + version "0.10.6" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" + integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== dependencies: "@babel/helper-define-polyfill-provider" "^0.6.2" + core-js-compat "^3.38.0" + +babel-plugin-polyfill-corejs3@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz#4e4e182f1bb37c7ba62e2af81d8dd09df31344f6" + integrity sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.3" + core-js-compat "^3.40.0" + +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.3" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz#abeb1f3f1c762eace37587f42548b08b57789bc8" + integrity sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q== + dependencies: + "@babel/helper-define-polyfill-provider" "^0.6.3" babel-plugin-syntax-class-properties@^6.8.0: version "6.13.0" @@ -4376,9 +4232,9 @@ babel-plugin-transform-react-remove-prop-types@^0.4.24: integrity sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA== babel-preset-react-app@^10.0.1: - version "10.0.1" - resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.0.1.tgz#ed6005a20a24f2c88521809fa9aea99903751584" - integrity sha512-b0D9IZ1WhhCWkrTXyFuIIgqGzSkRIH5D5AmB0bXbzYAB1OBAwHcUeyWW2LorutLWF5btNo/N7r/cIdmvvKJlYg== + version "10.1.0" + resolved "https://registry.yarnpkg.com/babel-preset-react-app/-/babel-preset-react-app-10.1.0.tgz#e367f223f6c27878e6cc28471d0d506a9ab9f96c" + integrity sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg== dependencies: "@babel/core" "^7.16.0" "@babel/plugin-proposal-class-properties" "^7.16.0" @@ -4387,6 +4243,7 @@ babel-preset-react-app@^10.0.1: "@babel/plugin-proposal-numeric-separator" "^7.16.0" "@babel/plugin-proposal-optional-chaining" "^7.16.0" "@babel/plugin-proposal-private-methods" "^7.16.0" + "@babel/plugin-proposal-private-property-in-object" "^7.16.7" "@babel/plugin-transform-flow-strip-types" "^7.16.0" "@babel/plugin-transform-react-display-name" "^7.16.0" "@babel/plugin-transform-runtime" "^7.16.4" @@ -4519,25 +4376,15 @@ browser-fs-access@0.29.1: resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.29.1.tgz#8a9794c73cf86b9aec74201829999c597128379c" integrity sha512-LSvVX5e21LRrXqVMhqtAwj5xPgDb+fXAIH80NsnCQ9xuZPs2xWsOREi24RKgZa1XOiQRbcmVrv87+ulOKsgjxw== -browserslist@^4.14.5, browserslist@^4.20.3, browserslist@^4.21.10, browserslist@^4.22.2, browserslist@^4.23.0: - version "4.23.0" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" - integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== +browserslist@^4.14.5, browserslist@^4.20.3, browserslist@^4.24.0, browserslist@^4.24.3: + version "4.24.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" + integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== dependencies: - caniuse-lite "^1.0.30001587" - electron-to-chromium "^1.4.668" - node-releases "^2.0.14" - update-browserslist-db "^1.0.13" - -browserslist@^4.23.1: - version "4.23.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" - integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== - dependencies: - caniuse-lite "^1.0.30001646" - electron-to-chromium "^1.5.4" - node-releases "^2.0.18" - update-browserslist-db "^1.1.0" + caniuse-lite "^1.0.30001688" + electron-to-chromium "^1.5.73" + node-releases "^2.0.19" + update-browserslist-db "^1.1.1" buffer-crc32@~0.2.3: version "0.2.13" @@ -4557,11 +4404,6 @@ buffer@^5.2.1, buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -builtin-modules@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" - integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== - busboy@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" @@ -4579,16 +4421,31 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1, call-bind-apply-helpers@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz#4b5428c222be985d79c3d82657479dbe0b59b2d6" + integrity sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ== dependencies: - es-define-property "^1.0.0" es-errors "^1.3.0" function-bind "^1.1.2" + +call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" get-intrinsic "^1.2.4" - set-function-length "^1.2.1" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" callsites@4.2.0: version "4.2.0" @@ -4613,15 +4470,10 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001587: - version "1.0.30001621" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001621.tgz#4adcb443c8b9c8303e04498318f987616b8fea2e" - integrity sha512-+NLXZiviFFKX0fk8Piwv3PfLPGtRqJeq2TiNoUff/qB5KJgwecJTvCXDpmlyP/eCI/GUEmp/h/y5j0yckiiZrA== - -caniuse-lite@^1.0.30001646: - version "1.0.30001655" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz#0ce881f5a19a2dcfda2ecd927df4d5c1684b982f" - integrity sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg== +caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001688: + version "1.0.30001700" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" + integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== canvas-roundrect-polyfill@0.0.1: version "0.0.1" @@ -4641,10 +4493,10 @@ chai@4.3.6: pathval "^1.1.1" type-detect "^4.0.5" -chai@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/chai/-/chai-5.1.1.tgz#f035d9792a22b481ead1c65908d14bb62ec1c82c" - integrity sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA== +chai@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" + integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== dependencies: assertion-error "^2.0.1" check-error "^2.1.1" @@ -4720,20 +4572,22 @@ check-error@^2.1.1: optionalDependencies: fsevents "~2.3.2" +chokidar@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + chownr@^1.1.1: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== chrome-trace-event@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" - integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== - -ci-info@^3.2.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" - integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== + version "1.0.4" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz#05bffd7ff928465093314708c93bdfa9bd1f0f5b" + integrity sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ== clean-css@^5.2.2: version "5.3.3" @@ -4889,12 +4743,12 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.31.0, core-js-compat@^3.36.1: - version "3.37.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.37.1.tgz#c844310c7852f4bdf49b8d339730b97e17ff09ee" - integrity sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg== +core-js-compat@^3.31.0, core-js-compat@^3.38.0, core-js-compat@^3.40.0: + version "3.40.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" + integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== dependencies: - browserslist "^4.23.0" + browserslist "^4.24.3" core-js@^2.4.0: version "2.6.12" @@ -4902,9 +4756,9 @@ core-js@^2.4.0: integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== core-js@^3.4: - version "3.37.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.37.1.tgz#d21751ddb756518ac5a00e4d66499df981a62db9" - integrity sha512-Xn6qmxrQZyB0FFY8E3bgRXei3lWDJHhvI+u0q9TKIYM49G8pAr0FgnnrFRAmsbptZL1yxRADVXn+x5AGsbBfyw== + version "3.40.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" + integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== corser@^2.0.1: version "2.0.1" @@ -5007,15 +4861,6 @@ css.escape@^1.5.1: resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== -css@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/css/-/css-3.0.0.tgz#4447a4d58fdd03367c516ca9f64ae365cee4aa5d" - integrity sha512-DG9pFfwOrzc+hawpmqX/dHYHJG+Bsdb0klhyi1sDneOgGOXy9wQIC8hzyVp1e4NRYDBdxcylvywPkkXCHAzTyQ== - dependencies: - inherits "^2.0.4" - source-map "^0.6.1" - source-map-resolve "^0.6.0" - cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -5046,9 +4891,9 @@ cytoscape-cose-bilkent@^4.1.0: cose-base "^1.0.0" cytoscape@^3.28.1: - version "3.29.2" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.29.2.tgz#c99f42513c80a75e2e94858add32896c860202ac" - integrity sha512-2G1ycU28Nh7OHT9rkXRLpCDP30MKH1dXJORZuBhtEhEW7pKwgPi77ImqlCWinouyE1PNepIOGZBOrE84DG7LyQ== + version "3.31.0" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.0.tgz#cffbbb8ca51db01cbf360e0cf59088db6d429837" + integrity sha512-zDGn1K/tfZwEnoGOcHc0H4XazqAAXAuDpcYw9mUnUjATjqljyCNGJv8uEvbvxGaGHaVshxMecyl6oc6uKzRfbw== "d3-array@1 - 2": version "2.12.1" @@ -5343,39 +5188,46 @@ data-urls@^4.0.0: whatwg-mimetype "^3.0.0" whatwg-url "^12.0.0" -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.2" es-errors "^1.3.0" is-data-view "^1.0.1" dayjs@^1.11.7: - version "1.11.11" - resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.11.tgz#dfe0e9d54c5f8b68ccf8ca5f72ac603e7e5ed59e" - integrity sha512-okzr3f11N6WuqYtZSvm+F776mB41wRZMhKP+hc34YdW+KmtYYK9iqvHSwo2k9FEH3fhGXvOPV6yz2IcSrfRUDg== + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== -debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@~4.3.1, debug@~4.3.2: +debug@4, debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.3, debug@^4.3.4, debug@^4.3.6, debug@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +debug@4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -5396,17 +5248,17 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.3.5: - version "4.3.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b" - integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg== +debug@~4.3.1, debug@~4.3.2: + version "4.3.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52" + integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ== dependencies: - ms "2.1.2" + ms "^2.1.3" decimal.js@^10.4.3: - version "10.4.3" - resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" - integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA== + version "10.5.0" + resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.5.0.tgz#0f371c7cf6c4898ce0afb09836db73cd82010f22" + integrity sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw== decode-named-character-reference@^1.0.0: version "1.0.2" @@ -5415,11 +5267,6 @@ decode-named-character-reference@^1.0.0: dependencies: character-entities "^2.0.0" -decode-uri-component@^0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.2.tgz#e69dbe25d37941171dd540e024c444cd5188e1e9" - integrity sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ== - deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -5451,7 +5298,7 @@ define-data-property@^1.0.1, define-data-property@^1.1.4: es-errors "^1.3.0" gopd "^1.0.1" -define-properties@^1.2.0, define-properties@^1.2.1: +define-properties@^1.1.3, define-properties@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c" integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg== @@ -5477,6 +5324,11 @@ dequal@^2.0.0, dequal@^2.0.3: resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg== + detect-node-es@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" @@ -5523,11 +5375,16 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dom-accessibility-api@^0.5.6, dom-accessibility-api@^0.5.9: +dom-accessibility-api@^0.5.9: version "0.5.16" resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz#5a7429e6066eb3664d911e33fb0e45de8eb08453" integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg== +dom-accessibility-api@^0.6.3: + version "0.6.3" + resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8" + integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w== + dom-serializer@^1.0.1: version "1.4.1" resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" @@ -5596,9 +5453,18 @@ dotenv@16.0.1: integrity sha512-1K6hR6wtk2FviQ4kEiSjFiH5rpzEVi8WW0x96aztHVMhEspNpc4DVOUTEHtEva5VThQ8IaBX1Pe4gSzpVVUsKQ== dotenv@^16.0.0: - version "16.4.5" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.5.tgz#cdd3b3b604cb327e286b4762e13502f717cb099f" - integrity sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg== + version "16.4.7" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" + integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== + +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" duplexer@^0.1.2: version "0.1.2" @@ -5617,15 +5483,10 @@ ejs@^3.1.6, ejs@^3.1.9: dependencies: jake "^10.8.5" -electron-to-chromium@^1.4.668: - version "1.4.783" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.783.tgz#933887165b8b6025a81663d2d97cf4b85cde27b2" - integrity sha512-bT0jEz/Xz1fahQpbZ1D7LgmPYZ3iHVY39NcWWro1+hA2IvjiPeaXtfSqrQ+nXjApMvQRE2ASt1itSLRrebHMRQ== - -electron-to-chromium@^1.5.4: - version "1.5.13" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" - integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== +electron-to-chromium@^1.5.73: + version "1.5.103" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz#3d02025bc16e96e5edb3ed3ffa2538a11ae682dc" + integrity sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA== elkjs@^0.9.0: version "0.9.3" @@ -5655,25 +5516,36 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: once "^1.4.0" engine.io-client@~6.5.2: - version "6.5.3" - resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.3.tgz#4cf6fa24845029b238f83c628916d9149c399bc5" - integrity sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q== + version "6.5.4" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.5.4.tgz#b8bc71ed3f25d0d51d587729262486b4b33bd0d0" + integrity sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" engine.io-parser "~5.2.1" - ws "~8.11.0" + ws "~8.17.1" xmlhttprequest-ssl "~2.0.0" -engine.io-parser@~5.2.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.2.tgz#37b48e2d23116919a3453738c5720455e64e1c49" - integrity sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw== +engine.io-client@~6.6.1: + version "6.6.3" + resolved "https://registry.yarnpkg.com/engine.io-client/-/engine.io-client-6.6.3.tgz#815393fa24f30b8e6afa8f77ccca2f28146be6de" + integrity sha512-T0iLjnyNWahNyv/lcjS2y4oE358tVS/SYQNxYXGAJ9/GLgH4VCvOQ/mhTjqU88mLZCQgiG8RIegFHYCdVC+j5w== + dependencies: + "@socket.io/component-emitter" "~3.1.0" + debug "~4.3.1" + engine.io-parser "~5.2.1" + ws "~8.17.1" + xmlhttprequest-ssl "~2.1.1" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0, enhanced-resolve@^5.16.0: - version "5.16.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz#e8bc63d51b826d6f1cbc0a150ecb5a8b0c62e567" - integrity sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw== +engine.io-parser@~5.2.1: + version "5.2.3" + resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" + integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== + +enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0, enhanced-resolve@^5.17.1: + version "5.18.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf" + integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -5691,15 +5563,15 @@ entities@^2.0.0: resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== -entities@^4.4.0: +entities@^4.4.0, entities@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== envinfo@^7.7.3: - version "7.13.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.13.0.tgz#81fbb81e5da35d74e814941aeab7c325a606fb31" - integrity sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q== + version "7.14.0" + resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" + integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== error-ex@^1.3.1: version "1.3.2" @@ -5708,131 +5580,137 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== +es-abstract@^1.17.5, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: + version "1.23.9" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" + integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" + call-bind "^1.0.8" + call-bound "^1.0.3" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" es-errors "^1.3.0" es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.2.7" + get-proto "^1.0.0" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" + has-proto "^1.2.0" + has-symbols "^1.1.0" hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" + is-data-view "^1.0.2" + is-regex "^1.2.1" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.0" + math-intrinsics "^1.1.0" + object-inspect "^1.13.3" object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.18" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== -es-errors@^1.1.0, es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-iterator-helpers@^1.0.15, es-iterator-helpers@^1.0.17: - version "1.0.19" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" - integrity sha512-zoMwbCcH5hwUkKJkT8kDIBZSz9I6mVG//+lDCinLCGov4+r7NIy0ld8o03M0cJxl2spVf6ESYVS6/gpIfq1FFw== +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - es-abstract "^1.23.3" + es-abstract "^1.23.6" es-errors "^1.3.0" es-set-tostringtag "^2.0.3" function-bind "^1.1.2" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" + get-intrinsic "^1.2.6" + globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.2" - safe-array-concat "^1.1.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" es-module-lexer@^0.9.0: version "0.9.3" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== -es-module-lexer@^1.2.1: - version "1.5.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.3.tgz#25969419de9c0b1fbe54279789023e8a9a788412" - integrity sha512-i1gCgmR9dCl6Vil6UKPI/trA69s08g/syhiDK9TG0Nf1RJjjFI+AzoWW7sPufzkgYAn861skuCwJa0pIIHYxvg== +es-module-lexer@^1.2.1, es-module-lexer@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21" + integrity sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ== -es-object-atoms@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" - integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== +es-object-atoms@^1.0.0, es-object-atoms@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.1.1.tgz#1c4f2c4837327597ce69d2ca190a7fdd172338c1" + integrity sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA== dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== dependencies: - get-intrinsic "^1.2.4" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" has-tostringtag "^1.0.2" - hasown "^2.0.1" + hasown "^2.0.2" -es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" - integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== +es-shim-unscopables@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz#438df35520dac5d105f3943d927549ea3b00f4b5" + integrity sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" es6-promise-pool@2.5.0: version "2.5.0" @@ -5910,50 +5788,47 @@ esbuild@^0.19.3: "@esbuild/win32-ia32" "0.19.12" "@esbuild/win32-x64" "0.19.12" -esbuild@^0.20.1: - version "0.20.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1" - integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g== +esbuild@^0.24.2: + version "0.24.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d" + integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== optionalDependencies: - "@esbuild/aix-ppc64" "0.20.2" - "@esbuild/android-arm" "0.20.2" - "@esbuild/android-arm64" "0.20.2" - "@esbuild/android-x64" "0.20.2" - "@esbuild/darwin-arm64" "0.20.2" - "@esbuild/darwin-x64" "0.20.2" - "@esbuild/freebsd-arm64" "0.20.2" - "@esbuild/freebsd-x64" "0.20.2" - "@esbuild/linux-arm" "0.20.2" - "@esbuild/linux-arm64" "0.20.2" - "@esbuild/linux-ia32" "0.20.2" - "@esbuild/linux-loong64" "0.20.2" - "@esbuild/linux-mips64el" "0.20.2" - "@esbuild/linux-ppc64" "0.20.2" - "@esbuild/linux-riscv64" "0.20.2" - "@esbuild/linux-s390x" "0.20.2" - "@esbuild/linux-x64" "0.20.2" - "@esbuild/netbsd-x64" "0.20.2" - "@esbuild/openbsd-x64" "0.20.2" - "@esbuild/sunos-x64" "0.20.2" - "@esbuild/win32-arm64" "0.20.2" - "@esbuild/win32-ia32" "0.20.2" - "@esbuild/win32-x64" "0.20.2" + "@esbuild/aix-ppc64" "0.24.2" + "@esbuild/android-arm" "0.24.2" + "@esbuild/android-arm64" "0.24.2" + "@esbuild/android-x64" "0.24.2" + "@esbuild/darwin-arm64" "0.24.2" + "@esbuild/darwin-x64" "0.24.2" + "@esbuild/freebsd-arm64" "0.24.2" + "@esbuild/freebsd-x64" "0.24.2" + "@esbuild/linux-arm" "0.24.2" + "@esbuild/linux-arm64" "0.24.2" + "@esbuild/linux-ia32" "0.24.2" + "@esbuild/linux-loong64" "0.24.2" + "@esbuild/linux-mips64el" "0.24.2" + "@esbuild/linux-ppc64" "0.24.2" + "@esbuild/linux-riscv64" "0.24.2" + "@esbuild/linux-s390x" "0.24.2" + "@esbuild/linux-x64" "0.24.2" + "@esbuild/netbsd-arm64" "0.24.2" + "@esbuild/netbsd-x64" "0.24.2" + "@esbuild/openbsd-arm64" "0.24.2" + "@esbuild/openbsd-x64" "0.24.2" + "@esbuild/sunos-x64" "0.24.2" + "@esbuild/win32-arm64" "0.24.2" + "@esbuild/win32-ia32" "0.24.2" + "@esbuild/win32-x64" "0.24.2" -escalade@^3.1.1, escalade@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" - integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== -escape-string-regexp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" - integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== - escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" @@ -5993,10 +5868,10 @@ eslint-import-resolver-node@^0.3.9: is-core-module "^2.13.0" resolve "^1.22.4" -eslint-module-utils@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz#52f2404300c3bd33deece9d7372fb337cc1d7c34" - integrity sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q== +eslint-module-utils@^2.12.0: + version "2.12.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b" + integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg== dependencies: debug "^3.2.7" @@ -6009,26 +5884,28 @@ eslint-plugin-flowtype@^8.0.3: string-natural-compare "^3.0.1" eslint-plugin-import@^2.25.3: - version "2.29.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" - integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + version "2.31.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" + integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== dependencies: - array-includes "^3.1.7" - array.prototype.findlastindex "^1.2.3" + "@rtsao/scc" "^1.1.0" + array-includes "^3.1.8" + array.prototype.findlastindex "^1.2.5" array.prototype.flat "^1.3.2" array.prototype.flatmap "^1.3.2" debug "^3.2.7" doctrine "^2.1.0" eslint-import-resolver-node "^0.3.9" - eslint-module-utils "^2.8.0" - hasown "^2.0.0" - is-core-module "^2.13.1" + eslint-module-utils "^2.12.0" + hasown "^2.0.2" + is-core-module "^2.15.1" is-glob "^4.0.3" minimatch "^3.1.2" - object.fromentries "^2.0.7" - object.groupby "^1.0.1" - object.values "^1.1.7" + object.fromentries "^2.0.8" + object.groupby "^1.0.3" + object.values "^1.2.0" semver "^6.3.1" + string.prototype.trimend "^1.0.8" tsconfig-paths "^3.15.0" eslint-plugin-jest@^25.3.0: @@ -6039,26 +5916,25 @@ eslint-plugin-jest@^25.3.0: "@typescript-eslint/experimental-utils" "^5.0.0" eslint-plugin-jsx-a11y@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== + version "6.10.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz#d2812bb23bf1ab4665f1718ea442e8372e638483" + integrity sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q== dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" + aria-query "^5.3.2" + array-includes "^3.1.8" array.prototype.flatmap "^1.3.2" ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" + axe-core "^4.10.0" + axobject-query "^4.1.0" damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" + hasown "^2.0.2" jsx-ast-utils "^3.3.5" language-tags "^1.0.9" minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.1" eslint-plugin-prettier@3.3.1: version "3.3.1" @@ -6094,28 +5970,28 @@ eslint-plugin-react@7.32.2: string.prototype.matchall "^4.0.8" eslint-plugin-react@^7.27.1: - version "7.34.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" - integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== + version "7.37.4" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz#1b6c80b6175b6ae4b26055ae4d55d04c414c7181" + integrity sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ== dependencies: - array-includes "^3.1.7" - array.prototype.findlast "^1.2.4" - array.prototype.flatmap "^1.3.2" - array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" + array-includes "^3.1.8" + array.prototype.findlast "^1.2.5" + array.prototype.flatmap "^1.3.3" + array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" - es-iterator-helpers "^1.0.17" + es-iterator-helpers "^1.2.1" estraverse "^5.3.0" + hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" - object.hasown "^1.1.3" - object.values "^1.1.7" + object.entries "^1.1.8" + object.fromentries "^2.0.8" + object.values "^1.2.1" prop-types "^15.8.1" resolve "^2.0.0-next.5" semver "^6.3.1" - string.prototype.matchall "^4.0.10" + string.prototype.matchall "^4.0.12" + string.prototype.repeat "^1.0.0" eslint-plugin-testing-library@^5.0.1: version "5.11.1" @@ -6149,7 +6025,7 @@ eslint-visitor-keys@^2.0.0, eslint-visitor-keys@^2.1.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.3: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== @@ -6215,9 +6091,9 @@ esprima@^4.0.0: integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== esquery@^1.4.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" - integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + version "1.6.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7" + integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg== dependencies: estraverse "^5.1.0" @@ -6296,31 +6172,10 @@ execa@^5.1.1: signal-exit "^3.0.3" strip-final-newline "^2.0.0" -execa@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" - integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== - dependencies: - cross-spawn "^7.0.3" - get-stream "^8.0.1" - human-signals "^5.0.0" - is-stream "^3.0.0" - merge-stream "^2.0.0" - npm-run-path "^5.1.0" - onetime "^6.0.0" - signal-exit "^4.1.0" - strip-final-newline "^3.0.0" - -expect@^29.0.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/expect/-/expect-29.7.0.tgz#578874590dcb3214514084c08115d8aee61e11bc" - integrity sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw== - dependencies: - "@jest/expect-utils" "^29.7.0" - jest-get-type "^29.6.3" - jest-matcher-utils "^29.7.0" - jest-message-util "^29.7.0" - jest-util "^29.7.0" +expect-type@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" + integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== extract-zip@2.0.1: version "2.0.1" @@ -6351,15 +6206,15 @@ fast-diff@^1.1.2: integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw== fast-glob@^3.2.11, fast-glob@^3.2.7, fast-glob@^3.2.9, fast-glob@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" - integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== dependencies: "@nodelib/fs.stat" "^2.0.2" "@nodelib/fs.walk" "^1.2.3" glob-parent "^5.1.2" merge2 "^1.3.0" - micromatch "^4.0.4" + micromatch "^4.0.8" fast-json-stable-stringify@^2.0.0, fast-json-stable-stringify@^2.1.0: version "2.1.0" @@ -6371,15 +6226,20 @@ fast-levenshtein@^2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== +fast-uri@^3.0.1: + version "3.0.6" + resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" + integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== + fastest-levenshtein@^1.0.12: version "1.0.16" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + version "1.19.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" + integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== dependencies: reusify "^1.0.4" @@ -6397,6 +6257,11 @@ fd-slicer@~1.1.0: dependencies: pend "~1.2.0" +fdir@^6.4.3: + version "6.4.3" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" + integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== + fflate@^0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" @@ -6502,14 +6367,14 @@ flat@^5.0.2: integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.2.9, flatted@^3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" - integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== + version "3.3.3" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" + integrity sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg== follow-redirects@^1.0.0: - version "1.15.6" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b" - integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA== + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== fonteditor-core@2.4.0: version "2.4.0" @@ -6526,11 +6391,11 @@ fonteditor-core@2.4.1: "@xmldom/xmldom" "^0.8.3" for-each@^0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + version "0.3.5" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.5.tgz#d650688027826920feeb0af747ee7b9421a41d47" + integrity sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg== dependencies: - is-callable "^1.1.3" + is-callable "^1.2.7" foreground-child@^3.1.0: version "3.3.0" @@ -6541,12 +6406,13 @@ foreground-child@^3.1.0: signal-exit "^4.0.1" form-data@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" - integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + version "4.0.2" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.2.tgz#35cabbdd30c3ce73deb2c42d3c8d3ed9ca51794c" + integrity sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w== dependencies: asynckit "^0.4.0" combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" mime-types "^2.1.12" fraction.js@^4.2.0: @@ -6574,9 +6440,9 @@ fs-extra@^10.0.1: universalify "^2.0.0" fs-extra@^11.1.0: - version "11.2.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" - integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== + version "11.3.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.3.0.tgz#0daced136bbaf65a555a326719af931adc7a314d" + integrity sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew== dependencies: graceful-fs "^4.2.0" jsonfile "^6.0.1" @@ -6607,15 +6473,17 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.5, function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" functional-red-black-tree@^1.0.1: version "1.0.1" @@ -6647,16 +6515,21 @@ get-func-name@^2.0.0, get-func-name@^2.0.1, get-func-name@^2.0.2: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7: + version "1.3.0" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.3.0.tgz#743f0e3b6964a93a5491ed1bffaae054d7f98d01" + integrity sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ== dependencies: + call-bind-apply-helpers "^1.0.2" + es-define-property "^1.0.1" es-errors "^1.3.0" + es-object-atoms "^1.1.1" function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" + get-proto "^1.0.1" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" get-nonce@^1.0.0: version "1.0.1" @@ -6668,6 +6541,14 @@ get-own-enumerable-property-symbols@^3.0.0: resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== + dependencies: + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + get-stream@^5.1.0: version "5.2.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3" @@ -6680,19 +6561,14 @@ get-stream@^6.0.0: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-stream@^8.0.1: - version "8.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" - integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== - -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== dependencies: - call-bind "^1.0.5" + call-bound "^1.0.3" es-errors "^1.3.0" - get-intrinsic "^1.2.4" + get-intrinsic "^1.2.6" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -6747,7 +6623,7 @@ globals@^9.18.0: resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== -globalthis@^1.0.3: +globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -6772,12 +6648,10 @@ glur@^1.1.2: resolved "https://registry.yarnpkg.com/glur/-/glur-1.1.2.tgz#f20ea36db103bfc292343921f1f91e83c3467689" integrity sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA== -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: version "4.2.11" @@ -6813,10 +6687,10 @@ has-ansi@^2.0.0: dependencies: ansi-regex "^2.0.0" -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== has-flag@^3.0.0: version "3.0.0" @@ -6835,24 +6709,26 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: +has-tostringtag@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: +hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== @@ -6890,9 +6766,9 @@ html-minifier-terser@^6.1.0: terser "^5.10.0" http-parser-js@>=0.5.1: - version "0.5.8" - resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.8.tgz#af23090d9ac4e24573de6f6aecc9d84a48bf20e3" - integrity sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q== + version "0.5.9" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.9.tgz#b817b3ca0edea6236225000d795378707c169cec" + integrity sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw== http-proxy-agent@^5.0.0: version "5.0.0" @@ -6944,11 +6820,6 @@ human-signals@^2.1.0: resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== -human-signals@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" - integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== - husky@7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/husky/-/husky-7.0.4.tgz#242048245dc49c8fb1bf0cc7cfb98dd722531535" @@ -6996,9 +6867,9 @@ ignore@^4.0.6: integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== ignore@^5.2.0: - version "5.3.1" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" - integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== + version "5.3.2" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5" + integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g== image-blob-reduce@3.0.1: version "3.0.1" @@ -7008,22 +6879,27 @@ image-blob-reduce@3.0.1: pica "^7.1.0" immutable@^4.0.0: - version "4.3.6" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.6.tgz#6a05f7858213238e587fb83586ffa3b4b27f0447" - integrity sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ== + version "4.3.7" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.7.tgz#c70145fc90d89fb02021e65c84eb0226e4e5a381" + integrity sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw== + +immutable@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.0.3.tgz#aa037e2313ea7b5d400cd9298fa14e404c933db1" + integrity sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw== import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" - integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + version "3.3.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf" + integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ== dependencies: parent-module "^1.0.0" resolve-from "^4.0.0" import-local@^3.0.2: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" - integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== + version "3.2.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" + integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== dependencies: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" @@ -7056,14 +6932,14 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== dependencies: es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" + hasown "^2.0.2" + side-channel "^1.1.0" "internmap@1 - 2": version "2.0.3" @@ -7080,20 +6956,21 @@ interpret@^2.2.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== -invariant@^2.2.2, invariant@^2.2.4: +invariant@^2.2.2: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== dependencies: loose-envify "^1.0.0" -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-arrayish@^0.2.1: version "0.2.1" @@ -7101,18 +6978,22 @@ is-arrayish@^0.2.1: integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.1.tgz#3e69018c8e04e73b738793d020bfe884b9fd3523" + integrity sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ== dependencies: - has-tostringtag "^1.0.0" + async-function "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== dependencies: - has-bigints "^1.0.1" + has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" @@ -7121,58 +7002,54 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== +is-boolean-object@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.2.tgz#7067f47709809a393c71ff5bb3e135d8a9215d9e" + integrity sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" -is-builtin-module@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-3.2.1.tgz#f03271717d8654cfcaf07ab0463faa3571581169" - integrity sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A== - dependencies: - builtin-modules "^3.3.0" - -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.13.1: - version "2.13.1" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" - integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== +is-core-module@^2.13.0, is-core-module@^2.15.1, is-core-module@^2.16.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== dependencies: - hasown "^2.0.0" + hasown "^2.0.2" -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" is-typed-array "^1.1.13" -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -7185,11 +7062,14 @@ is-fullwidth-code-point@^4.0.0: integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" @@ -7208,17 +7088,13 @@ is-module@^1.0.0: resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g== -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-number@^7.0.0: version "7.0.0" @@ -7242,13 +7118,15 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" is-regexp@^1.0.0: version "1.0.0" @@ -7260,63 +7138,61 @@ is-set@^2.0.3: resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" - integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== - -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: - has-symbols "^1.0.2" + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - which-typed-array "^1.1.14" + which-typed-array "^1.1.16" is-weakmap@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.1.tgz#eea430182be8d64174bd96bffbc46f21bf3f9293" + integrity sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" isarray@^2.0.5: version "2.0.5" @@ -7369,16 +7245,17 @@ istanbul-reports@^3.1.7: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterator.prototype@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.2.tgz#5e29c8924f01916cb9335f1ff80619dcff22b0c0" - integrity sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w== +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + get-proto "^1.0.0" + has-symbols "^1.1.0" + set-function-name "^2.0.2" jackspeak@^3.1.2: version "3.4.3" @@ -7390,9 +7267,9 @@ jackspeak@^3.1.2: "@pkgjs/parseargs" "^0.11.0" jake@^10.8.5: - version "10.9.1" - resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.1.tgz#8dc96b7fcc41cb19aa502af506da4e1d56f5e62b" - integrity sha512-61btcOHNnLnsOdtLgA5efqQWjnSi/vow5HbI7HMdKKWqvrKR1bLK3BPlJn9gcSaP2ewuamUSMB5XEy76KUIS2w== + version "10.9.2" + resolved "https://registry.yarnpkg.com/jake/-/jake-10.9.2.tgz#6ae487e6a69afec3a5e167628996b59f35ae2b7f" + integrity sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA== dependencies: async "^3.2.3" chalk "^4.0.2" @@ -7407,7 +7284,7 @@ jest-canvas-mock@~2.5.2: cssfontparser "^1.2.1" moo-color "^1.0.2" -jest-diff@29.7.0, jest-diff@^29.7.0: +jest-diff@29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" integrity sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw== @@ -7437,43 +7314,6 @@ jest-get-type@^29.6.3: resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-29.6.3.tgz#36f499fdcea197c1045a127319c0481723908fd1" integrity sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw== -jest-matcher-utils@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz#ae8fec79ff249fd592ce80e3ee474e83a6c44f12" - integrity sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g== - dependencies: - chalk "^4.0.0" - jest-diff "^29.7.0" - jest-get-type "^29.6.3" - pretty-format "^29.7.0" - -jest-message-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-message-util/-/jest-message-util-29.7.0.tgz#8bc392e204e95dfe7564abbe72a404e28e51f7f3" - integrity sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w== - dependencies: - "@babel/code-frame" "^7.12.13" - "@jest/types" "^29.6.3" - "@types/stack-utils" "^2.0.0" - chalk "^4.0.0" - graceful-fs "^4.2.9" - micromatch "^4.0.4" - pretty-format "^29.7.0" - slash "^3.0.0" - stack-utils "^2.0.3" - -jest-util@^29.7.0: - version "29.7.0" - resolved "https://registry.yarnpkg.com/jest-util/-/jest-util-29.7.0.tgz#23c2b62bfb22be82b44de98055802ff3710fc0bc" - integrity sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA== - dependencies: - "@jest/types" "^29.6.3" - "@types/node" "*" - chalk "^4.0.0" - ci-info "^3.2.0" - graceful-fs "^4.2.9" - picomatch "^2.2.3" - jest-worker@^27.4.5: version "27.5.1" resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" @@ -7547,15 +7387,15 @@ jsdom@22.1.0: ws "^8.13.0" xml-name-validator "^4.0.0" -jsesc@^2.5.1: - version "2.5.2" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" - integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - integrity sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA== +jsesc@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e" + integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g== json-buffer@3.0.1: version "3.0.1" @@ -7624,9 +7464,9 @@ jsonpointer@^5.0.0: object.values "^1.1.6" katex@^0.16.9: - version "0.16.10" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" - integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== + version "0.16.21" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.21.tgz#8f63c659e931b210139691f2cc7bb35166b792a3" + integrity sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A== dependencies: commander "^8.3.0" @@ -7792,7 +7632,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== -lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7808,11 +7648,11 @@ log-update@^4.0.0: wrap-ansi "^6.2.0" long@^5.0.0: - version "5.2.3" - resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" - integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== + version "5.3.1" + resolved "https://registry.yarnpkg.com/long/-/long-5.3.1.tgz#9d4222d3213f38a5ec809674834e0f0ab21abe96" + integrity sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng== -loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: +loose-envify@^1.0.0, loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7826,12 +7666,10 @@ loupe@^2.3.1: dependencies: get-func-name "^2.0.1" -loupe@^3.1.0, loupe@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.1.tgz#71d038d59007d890e3247c5db97c1ec5a92edc54" - integrity sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw== - dependencies: - get-func-name "^2.0.1" +loupe@^3.1.0, loupe@^3.1.1, loupe@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2" + integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== lower-case@^2.0.2: version "2.0.2" @@ -7878,14 +7716,14 @@ magic-string@^0.27.0: dependencies: "@jridgewell/sourcemap-codec" "^1.4.13" -magic-string@^0.30.10: - version "0.30.11" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.11.tgz#301a6f93b3e8c2cb13ac1a7a673492c0dfd12954" - integrity sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A== +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== dependencies: "@jridgewell/sourcemap-codec" "^1.5.0" -magicast@^0.3.4: +magicast@^0.3.5: version "0.3.5" resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.5.tgz#8301c3c7d66704a0771eb1bad74274f0ec036739" integrity sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ== @@ -7908,6 +7746,11 @@ make-dir@^4.0.0: dependencies: semver "^7.5.3" +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + mdast-util-from-markdown@^1.3.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" @@ -8163,7 +8006,7 @@ micromark@^3.0.0: micromark-util-types "^1.0.1" uvu "^0.5.0" -micromatch@^4.0.0, micromatch@^4.0.4: +micromatch@^4.0.0, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -8193,11 +8036,6 @@ mimic-fn@^2.1.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== -mimic-fn@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" - integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== - min-indent@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" @@ -8271,9 +8109,9 @@ mrmime@^1.0.0: integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== mrmime@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4" - integrity sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw== + version "2.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.1.tgz#bc3e87f7987853a54c9850eeb1f1078cd44adddc" + integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== ms@2.0.0: version "2.0.0" @@ -8285,7 +8123,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.1.1, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -8308,17 +8146,17 @@ nanoid@4.0.2: resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e" integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw== -nanoid@^3.3.2, nanoid@^3.3.6, nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== +nanoid@^3.3.2, nanoid@^3.3.6, nanoid@^3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== nanospinner@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/nanospinner/-/nanospinner-1.1.0.tgz#d17ff621cb1784b0a206b400da88a0ef6db39b97" - integrity sha512-yFvNYMig4AthKYfHFl1sLj7B2nkHL4lzdig4osvl9/LdGbXwrdFRoqBS98gsEsOakr0yH+r5NZ/1Y9gdVB8trA== + version "1.2.2" + resolved "https://registry.yarnpkg.com/nanospinner/-/nanospinner-1.2.2.tgz#5a38f4410b5bf7a41585964bee74d32eab3e040b" + integrity sha512-Zt/AmG6qRU3e+WnzGGLuMCEAO/dAu45stNbHY223tUxldaDAeE+FxSPsd9Q+j+paejmm0ZbrNVs5Sraqy3dRxA== dependencies: - picocolors "^1.0.0" + picocolors "^1.1.1" natural-compare-lite@^1.4.0: version "1.4.0" @@ -8366,6 +8204,11 @@ no-case@^3.0.4: lower-case "^2.0.2" tslib "^2.0.3" +node-addon-api@^7.0.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558" + integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ== + node-fetch@2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -8381,15 +8224,10 @@ node-html-parser@^5.3.3: css-select "^4.2.1" he "1.2.0" -node-releases@^2.0.14: - version "2.0.14" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b" - integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw== - -node-releases@^2.0.18: - version "2.0.18" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" - integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== non-layered-tidy-tree-layout@^2.0.2: version "2.0.2" @@ -8413,13 +8251,6 @@ npm-run-path@^4.0.1: dependencies: path-key "^3.0.0" -npm-run-path@^5.1.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f" - integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ== - dependencies: - path-key "^4.0.0" - nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -8428,36 +8259,38 @@ nth-check@^2.0.1: boolbase "^1.0.0" nwsapi@^2.2.4: - version "2.2.10" - resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8" - integrity sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ== + version "2.2.16" + resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.16.tgz#177760bba02c351df1d2644e220c31dfec8cdb43" + integrity sha512-F1I/bimDpj3ncaNDhfyMWuFqmQDBwDB0Fogc2qpL3BWvkQteFD/8BzWuIRl83rq0DXfm8SGt/HFhLXZyljTXcQ== object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.12.0, object-inspect@^1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" - integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.12.0, object-inspect@^1.13.3: + version "1.13.4" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.4.tgz#8375265e21bc20d0fa582c22e1b13485d6e00213" + integrity sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew== object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - call-bind "^1.0.5" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - has-symbols "^1.0.3" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" object-keys "^1.1.1" -object.entries@^1.1.6, object.entries@^1.1.7: +object.entries@^1.1.6, object.entries@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== @@ -8466,7 +8299,7 @@ object.entries@^1.1.6, object.entries@^1.1.7: define-properties "^1.2.1" es-object-atoms "^1.0.0" -object.fromentries@^2.0.6, object.fromentries@^2.0.7: +object.fromentries@^2.0.6, object.fromentries@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== @@ -8476,7 +8309,7 @@ object.fromentries@^2.0.6, object.fromentries@^2.0.7: es-abstract "^1.23.2" es-object-atoms "^1.0.0" -object.groupby@^1.0.1: +object.groupby@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e" integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ== @@ -8485,7 +8318,7 @@ object.groupby@^1.0.1: define-properties "^1.2.1" es-abstract "^1.23.2" -object.hasown@^1.1.2, object.hasown@^1.1.3: +object.hasown@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.4.tgz#e270ae377e4c120cdcb7656ce66884a6218283dc" integrity sha512-FZ9LZt9/RHzGySlBARE3VF+gE26TxR38SdmqOqliuTnl9wrKulaQs+4dee1V+Io8VfxqzAfHu6YuRgUy8OHoTg== @@ -8494,12 +8327,13 @@ object.hasown@^1.1.2, object.hasown@^1.1.3: es-abstract "^1.23.2" es-object-atoms "^1.0.0" -object.values@^1.1.6, object.values@^1.1.7: - version "1.2.0" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" - integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== +object.values@^1.1.6, object.values@^1.2.0, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -8517,13 +8351,6 @@ onetime@^5.1.0, onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" -onetime@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" - integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== - dependencies: - mimic-fn "^4.0.0" - open-color@1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/open-color/-/open-color-1.9.1.tgz#a6e6328f60eff7aa60e3e8fcfa50f53ff3eece35" @@ -8546,6 +8373,15 @@ optionator@^0.9.1: type-check "^0.4.0" word-wrap "^1.2.5" +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -8573,9 +8409,9 @@ p-try@^2.0.0: integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== package-json-from-dist@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" - integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== pako@1.0.11: version "1.0.11" @@ -8608,11 +8444,11 @@ parse-json@^5.0.0, parse-json@^5.2.0: lines-and-columns "^1.1.6" parse5@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" - integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + version "7.2.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" + integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== dependencies: - entities "^4.4.0" + entities "^4.5.0" pascal-case@^3.1.2: version "3.1.2" @@ -8642,11 +8478,6 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-key@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" - integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== - path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" @@ -8680,6 +8511,11 @@ pathe@^1.1.2: resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec" integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ== +pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" @@ -8716,16 +8552,21 @@ pica@7.1.1, pica@^7.1.0: object-assign "^4.1.1" webworkify "^1.5.0" -picocolors@^1.0.0, picocolors@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1" - integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew== +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.2.3, picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + pidtree@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1" @@ -8786,9 +8627,9 @@ portfinder@^1.0.28: mkdirp "^0.5.6" possible-typed-array-names@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f" - integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q== + version "1.1.0" + resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" + integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== postcss-loader@7.0.1: version "7.0.1" @@ -8805,20 +8646,20 @@ postcss-modules-extract-imports@^3.0.0: integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== postcss-modules-local-by-default@^4.0.0: - version "4.0.5" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz#f1b9bd757a8edf4d8556e8d0f4f894260e3df78f" - integrity sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw== + version "4.2.0" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" + integrity sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw== dependencies: icss-utils "^5.0.0" - postcss-selector-parser "^6.0.2" + postcss-selector-parser "^7.0.0" postcss-value-parser "^4.1.0" postcss-modules-scope@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz#a43d28289a169ce2c15c00c4e64c0858e43457d5" - integrity sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ== + version "3.2.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" + integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== dependencies: - postcss-selector-parser "^6.0.4" + postcss-selector-parser "^7.0.0" postcss-modules-values@^4.0.0: version "4.0.0" @@ -8827,10 +8668,10 @@ postcss-modules-values@^4.0.0: dependencies: icss-utils "^5.0.0" -postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.4: - version "6.1.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" - integrity sha512-UMz42UD0UY0EApS0ZL9o1XnLhSTtvvvLe5Dc2H2O56fvRZi+KulDyf5ctDhhtYJBGKStV2FL1fy6253cmLgqVQ== +postcss-selector-parser@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" + integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -8849,14 +8690,14 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.32, postcss@^8.4.38, postcss@^8.4.7: - version "8.4.38" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" - integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== +postcss@^8.4.32, postcss@^8.4.7, postcss@^8.5.2: + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.2.0" + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" prelude-ls@^1.2.1: version "1.2.1" @@ -8894,7 +8735,7 @@ pretty-format@^27.0.0, pretty-format@^27.0.2, pretty-format@^27.5.1: ansi-styles "^5.0.0" react-is "^17.0.1" -pretty-format@^29.0.0, pretty-format@^29.7.0: +pretty-format@^29.7.0: version "29.7.0" resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== @@ -8918,9 +8759,9 @@ prop-types@^15.8.1: react-is "^16.13.1" protobufjs@^7.2.5: - version "7.3.0" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.3.0.tgz#a32ec0422c039798c41a0700306a6e305b9cb32c" - integrity sha512-YWD03n3shzV9ImZRX3ccbjqLxj7NokGN0V/ESiBV5xWqrommYHYiihuIyavq03pWSGqlyvYUFmfoMKd+1rPA/g== + version "7.4.0" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.4.0.tgz#7efe324ce9b3b61c82aae5de810d287bc08a248a" + integrity sha512-mRUWCc3KUU4w1jU8sGxICXH/gNS94DvI1gxqDvBzhj1JpcsimQkYiOJfwsPUykUI5ZaspFbSgmBLER8IrQ3tqw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -8941,19 +8782,21 @@ proxy-from-env@1.1.0: integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== psl@^1.1.33: - version "1.9.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" - integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag== + version "1.15.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.15.0.tgz#bdace31896f1d97cec6a79e8224898ce93d974c6" + integrity sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w== + dependencies: + punycode "^2.3.1" pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + version "3.0.2" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8" + integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw== dependencies: end-of-stream "^1.1.0" once "^1.3.1" -punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0: +punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.0, punycode@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== @@ -8982,11 +8825,11 @@ pwacompat@2.0.17: integrity sha512-6Du7IZdIy7cHiv7AhtDy4X2QRM8IAD5DII69mt5qWibC2d15ZU8DmBG1WdZKekG11cChSu4zkSUGPF9sweOl6w== qs@^6.4.0: - version "6.12.1" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.1.tgz#39422111ca7cbdb70425541cba20c7d7b216599a" - integrity sha512-zWmv4RSuB9r2mYQw3zxQuHWeU+42aKi1wWig/j4ele4ygELZ7PEO6MM7rim9oAQH2A5MWfsAVf/jPvTPgCbvUQ== + version "6.14.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.14.0.tgz#c63fa40680d2c5c941412a0e899c89af60c0a930" + integrity sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w== dependencies: - side-channel "^1.0.6" + side-channel "^1.1.0" querystringify@^2.1.1: version "2.2.0" @@ -9005,13 +8848,12 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" -react-dom@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== +react-dom@19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.0.0.tgz#43446f1f01c65a4cd7f7588083e686a6726cfb57" + integrity sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ== dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" + scheduler "^0.25.0" react-is@^16.13.1: version "16.13.1" @@ -9034,11 +8876,11 @@ react-refresh@^0.14.0: integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== react-remove-scroll-bar@^2.3.3: - version "2.3.6" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" - integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== dependencies: - react-style-singleton "^2.2.1" + react-style-singleton "^2.2.2" tslib "^2.0.0" react-remove-scroll@2.5.5: @@ -9052,21 +8894,18 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-style-singleton@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.1.tgz#f99e420492b2d8f34d38308ff660b60d0b1205b4" - integrity sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g== +react-style-singleton@^2.2.1, react-style-singleton@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== dependencies: get-nonce "^1.0.0" - invariant "^2.2.4" tslib "^2.0.0" -react@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" +react@19.0.0: + version "19.0.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.0.0.tgz#6e1969251b9f108870aa4bff37a0ce9ddfaaabdd" + integrity sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ== readable-stream@^3.1.1, readable-stream@^3.4.0: version "3.6.2" @@ -9077,6 +8916,11 @@ readable-stream@^3.1.1, readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -9109,23 +8953,24 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.23.1" + es-abstract "^1.23.9" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" -regenerate-unicode-properties@^10.1.0: - version "10.1.1" - resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.1.1.tgz#6b0e05489d9076b04c436f318d9b067bba459480" - integrity sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q== +regenerate-unicode-properties@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz#626e39df8c372338ea9b8028d1f99dc3fd9c3db0" + integrity sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA== dependencies: regenerate "^1.4.2" @@ -9151,39 +8996,46 @@ regenerator-transform@^0.15.2: dependencies: "@babel/runtime" "^7.8.4" -regexp.prototype.flags@^1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" - integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== +regexp.prototype.flags@^1.5.3: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== dependencies: - call-bind "^1.0.6" + call-bind "^1.0.8" define-properties "^1.2.1" es-errors "^1.3.0" - set-function-name "^2.0.1" + get-proto "^1.0.1" + gopd "^1.2.0" + set-function-name "^2.0.2" regexpp@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== -regexpu-core@^5.3.1: - version "5.3.2" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-5.3.2.tgz#11a2b06884f3527aec3e93dbbf4a3b958a95546b" - integrity sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ== +regexpu-core@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-6.2.0.tgz#0e5190d79e542bf294955dccabae04d3c7d53826" + integrity sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA== dependencies: - "@babel/regjsgen" "^0.8.0" regenerate "^1.4.2" - regenerate-unicode-properties "^10.1.0" - regjsparser "^0.9.1" + regenerate-unicode-properties "^10.2.0" + regjsgen "^0.8.0" + regjsparser "^0.12.0" unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" -regjsparser@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.9.1.tgz#272d05aa10c7c1f67095b1ff0addae8442fc5709" - integrity sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ== +regjsgen@^0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" + integrity sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q== + +regjsparser@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.12.0.tgz#0e846df6c6530586429377de56e0475583b088dc" + integrity sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ== dependencies: - jsesc "~0.5.0" + jsesc "~3.0.2" relateurl@^0.2.7: version "0.2.7" @@ -9223,11 +9075,11 @@ resolve-from@^5.0.0: integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.6, resolve@^1.9.0: - version "1.22.8" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" - integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + version "1.22.10" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" + integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== dependencies: - is-core-module "^2.13.0" + is-core-module "^2.16.0" path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" @@ -9261,9 +9113,9 @@ rewire@6.0.0: eslint "^7.32.0" rfdc@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f" - integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg== + version "1.4.1" + resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.4.1.tgz#778f76c4fb731d93414e8f925fbecf64cce7f6ca" + integrity sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA== rimraf@3.0.2, rimraf@^3.0.2: version "3.0.2" @@ -9278,35 +9130,38 @@ robust-predicates@^3.0.2: integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== rollup@^2.43.1: - version "2.79.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7" - integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw== + version "2.79.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.2.tgz#f150e4a5db4b121a21a747d762f701e5e9f49090" + integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ== optionalDependencies: fsevents "~2.3.2" -rollup@^4.13.0, rollup@^4.2.0: - version "4.18.0" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda" - integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg== +rollup@^4.2.0, rollup@^4.30.1: + version "4.34.8" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.8.tgz#e859c1a51d899aba9bcf451d4eed1d11fb8e2a6e" + integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== dependencies: - "@types/estree" "1.0.5" + "@types/estree" "1.0.6" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.18.0" - "@rollup/rollup-android-arm64" "4.18.0" - "@rollup/rollup-darwin-arm64" "4.18.0" - "@rollup/rollup-darwin-x64" "4.18.0" - "@rollup/rollup-linux-arm-gnueabihf" "4.18.0" - "@rollup/rollup-linux-arm-musleabihf" "4.18.0" - "@rollup/rollup-linux-arm64-gnu" "4.18.0" - "@rollup/rollup-linux-arm64-musl" "4.18.0" - "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0" - "@rollup/rollup-linux-riscv64-gnu" "4.18.0" - "@rollup/rollup-linux-s390x-gnu" "4.18.0" - "@rollup/rollup-linux-x64-gnu" "4.18.0" - "@rollup/rollup-linux-x64-musl" "4.18.0" - "@rollup/rollup-win32-arm64-msvc" "4.18.0" - "@rollup/rollup-win32-ia32-msvc" "4.18.0" - "@rollup/rollup-win32-x64-msvc" "4.18.0" + "@rollup/rollup-android-arm-eabi" "4.34.8" + "@rollup/rollup-android-arm64" "4.34.8" + "@rollup/rollup-darwin-arm64" "4.34.8" + "@rollup/rollup-darwin-x64" "4.34.8" + "@rollup/rollup-freebsd-arm64" "4.34.8" + "@rollup/rollup-freebsd-x64" "4.34.8" + "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" + "@rollup/rollup-linux-arm-musleabihf" "4.34.8" + "@rollup/rollup-linux-arm64-gnu" "4.34.8" + "@rollup/rollup-linux-arm64-musl" "4.34.8" + "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" + "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" + "@rollup/rollup-linux-riscv64-gnu" "4.34.8" + "@rollup/rollup-linux-s390x-gnu" "4.34.8" + "@rollup/rollup-linux-x64-gnu" "4.34.8" + "@rollup/rollup-linux-x64-musl" "4.34.8" + "@rollup/rollup-win32-arm64-msvc" "4.34.8" + "@rollup/rollup-win32-ia32-msvc" "4.34.8" + "@rollup/rollup-win32-x64-msvc" "4.34.8" fsevents "~2.3.2" roughjs@4.6.4: @@ -9337,9 +9192,9 @@ rw@1: integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== rxjs@^7.5.5: - version "7.8.1" - resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543" - integrity sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg== + version "7.8.2" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.2.tgz#955bc473ed8af11a002a2be52071bf475638607b" + integrity sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA== dependencies: tslib "^2.1.0" @@ -9355,14 +9210,15 @@ safari-14-idb-fix@^3.0.0: resolved "https://registry.yarnpkg.com/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz#450fc049b996ec7f3fd9ca2f89d32e0761583440" integrity sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog== -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" isarray "^2.0.5" safe-buffer@5.1.2: @@ -9375,14 +9231,22 @@ safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== dependencies: - call-bind "^1.0.6" es-errors "^1.3.0" - is-regex "^1.1.4" + isarray "^2.0.5" + +safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" @@ -9407,13 +9271,15 @@ sass@1.51.0: source-map-js ">=0.6.2 <2.0.0" sass@^1.7.3: - version "1.77.2" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.77.2.tgz#18d4ed2eefc260cdc8099c5439ec1303fd5863aa" - integrity sha512-eb4GZt1C3avsX3heBNlrc7I09nyT00IUuo4eFhAbeXWU2fvA7oXI53SxODVAA+zgZCk9aunAZgO+losjR3fAwA== + version "1.85.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.85.1.tgz#18ab0bb48110ae99163778f06445b406148ca0d5" + integrity sha512-Uk8WpxM5v+0cMR0XjX9KfRIacmSG86RH4DCCZjLU2rFh5tyutt9siAXJ7G+YfxQ99Q6wrRMbMlVl6KqUms71ag== dependencies: - chokidar ">=3.0.0 <4.0.0" - immutable "^4.0.0" + chokidar "^4.0.0" + immutable "^5.0.2" source-map-js ">=0.6.2 <2.0.0" + optionalDependencies: + "@parcel/watcher" "^2.4.1" saxes@^6.0.0: version "6.0.0" @@ -9422,12 +9288,10 @@ saxes@^6.0.0: dependencies: xmlchars "^2.2.0" -scheduler@^0.23.0: - version "0.23.2" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3" - integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ== - dependencies: - loose-envify "^1.1.0" +scheduler@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" + integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== schema-utils@^2.6.5: version "2.7.1" @@ -9438,7 +9302,7 @@ schema-utils@^2.6.5: ajv "^6.12.4" ajv-keywords "^3.5.2" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1, schema-utils@^3.2.0: +schema-utils@^3.0.0, schema-utils@^3.1.0: version "3.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== @@ -9447,10 +9311,10 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1, schema-utils@^3.2 ajv "^6.12.5" ajv-keywords "^3.5.2" -schema-utils@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.2.0.tgz#70d7c93e153a273a805801882ebd3bff20d89c8b" - integrity sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw== +schema-utils@^4.0.0, schema-utils@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0" + integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g== dependencies: "@types/json-schema" "^7.0.9" ajv "^8.9.0" @@ -9475,18 +9339,18 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== -serialize-javascript@^6.0.1: +serialize-javascript@^6.0.1, serialize-javascript@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" -set-function-length@^1.2.1: +set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -9498,7 +9362,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1, set-function-name@^2.0.2: +set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -9508,6 +9372,15 @@ set-function-name@^2.0.1, set-function-name@^2.0.2: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -9527,15 +9400,45 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: - call-bind "^1.0.7" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" siginfo@^2.0.0: version "2.0.0" @@ -9547,7 +9450,7 @@ signal-exit@^3.0.2, signal-exit@^3.0.3: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== -signal-exit@^4.0.1, signal-exit@^4.1.0: +signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== @@ -9632,13 +9535,13 @@ snake-case@^3.0.4: tslib "^2.0.3" socket.io-client@*: - version "4.7.5" - resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.7.5.tgz#919be76916989758bdc20eec63f7ee0ae45c05b7" - integrity sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ== + version "4.8.1" + resolved "https://registry.yarnpkg.com/socket.io-client/-/socket.io-client-4.8.1.tgz#1941eca135a5490b94281d0323fe2a35f6f291cb" + integrity sha512-hJVXfu3E28NmzGk8o1sHhN3om52tRvwYeidbj7xKy2eIIse5IoKX3USlS6Tqt3BHAtflLIkCQBkzVrEEfWUyYQ== dependencies: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.2" - engine.io-client "~6.5.2" + engine.io-client "~6.6.1" socket.io-parser "~4.2.4" socket.io-client@4.7.2: @@ -9659,18 +9562,10 @@ socket.io-parser@~4.2.4: "@socket.io/component-emitter" "~3.1.0" debug "~4.3.1" -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" - integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== - -source-map-resolve@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.6.0.tgz#3d9df87e236b53f16d01e58150fc7711138e5ed2" - integrity sha512-KXBr9d/fO/bWo97NXsPIAW1bFSBOuCnjbNTBMO7N59hsv5i9yzRDfcYwwt0l04+VqnKC+EwzvJZIP/qkuMgR/w== - dependencies: - atob "^2.1.2" - decode-uri-component "^0.2.0" +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2, source-map-js@^1.2.0, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== source-map-support@~0.5.20: version "0.5.21" @@ -9680,7 +9575,7 @@ source-map-support@~0.5.20: buffer-from "^1.0.0" source-map "^0.6.0" -source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0: +source-map@^0.6.0, source-map@~0.6.0: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== @@ -9702,22 +9597,15 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -stack-utils@^2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" - integrity sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ== - dependencies: - escape-string-regexp "^2.0.0" - stackback@0.0.2: version "0.0.2" resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== -std-env@^3.7.0: - version "3.7.0" - resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" - integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== +std-env@^3.8.0: + version "3.8.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.8.0.tgz#b56ffc1baf1a29dcc80a3bdf11d7fca7c315e7d5" + integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w== streamsearch@^1.1.0: version "1.1.0" @@ -9743,16 +9631,7 @@ string-natural-compare@^3.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^4.1.0, string-width@^4.2.0: - version "4.2.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.2.tgz#dafd4f9559a7585cfba529c6a0a4f73488ebd4c5" - integrity sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.0" - -string-width@^4.2.3: +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9770,40 +9649,62 @@ string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.matchall@^4.0.10, string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== +string.prototype.includes@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz#eceef21283640761a81dbe16d6c7171a4edf7d92" + integrity sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg== dependencies: call-bind "^1.0.7" define-properties "^1.2.1" - es-abstract "^1.23.2" + es-abstract "^1.23.3" + +string.prototype.matchall@^4.0.12, string.prototype.matchall@^4.0.6, string.prototype.matchall@^4.0.8: + version "4.0.12" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-abstract "^1.23.6" es-errors "^1.3.0" es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" set-function-name "^2.0.2" - side-channel "^1.0.6" + side-channel "^1.1.0" -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== +string.prototype.repeat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz#e90872ee0308b29435aa26275f6e1b762daee01a" + integrity sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w== dependencies: - call-bind "^1.0.7" + define-properties "^1.1.3" + es-abstract "^1.17.5" + +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" define-properties "^1.2.1" - es-abstract "^1.23.0" + es-abstract "^1.23.5" es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== +string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -9861,11 +9762,6 @@ strip-final-newline@^2.0.0: resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== -strip-final-newline@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" - integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== - strip-indent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001" @@ -9891,9 +9787,9 @@ styled-jsx@5.1.1: client-only "0.0.1" stylis@^4.1.3: - version "4.3.2" - resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.2.tgz#8f76b70777dd53eb669c6f58c997bf0a9972e444" - integrity sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg== + version "4.3.6" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" + integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== supports-color@^2.0.0: version "2.0.0" @@ -9942,9 +9838,9 @@ symbol-tree@^3.2.4: integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== table@^6.0.9: - version "6.8.2" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" - integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== + version "6.9.0" + resolved "https://registry.yarnpkg.com/table/-/table-6.9.0.tgz#50040afa6264141c7566b3b81d4d82c47a8668f5" + integrity sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -9993,21 +9889,21 @@ tempy@^0.6.0: type-fest "^0.16.0" unique-string "^2.0.0" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.10: - version "5.3.10" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" - integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== +terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.11: + version "5.3.11" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz#93c21f44ca86634257cac176f884f942b7ba3832" + integrity sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ== dependencies: - "@jridgewell/trace-mapping" "^0.3.20" + "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" - schema-utils "^3.1.1" - serialize-javascript "^6.0.1" - terser "^5.26.0" + schema-utils "^4.3.0" + serialize-javascript "^6.0.2" + terser "^5.31.1" -terser@^5.10.0, terser@^5.17.4, terser@^5.26.0: - version "5.31.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.0.tgz#06eef86f17007dbad4593f11a574c7f5eb02c6a1" - integrity sha512-Q1JFAoUKE5IMfI4Z/lkE/E6+SwgzO+x4tq4v1AyBLRj8VSYvRO6A/rQrPg1yud4g0En9EKI1TvFRF2tQFcoUkg== +terser@^5.10.0, terser@^5.17.4, terser@^5.31.1: + version "5.39.0" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.39.0.tgz#0e82033ed57b3ddf1f96708d123cca717d86ca3a" + integrity sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw== dependencies: "@jridgewell/source-map" "^0.3.3" acorn "^8.8.2" @@ -10038,36 +9934,49 @@ tiny-invariant@^1.1.0: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.3.tgz#46680b7a873a0d5d10005995eb90a70d74d60127" integrity sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg== -tinybench@^2.8.0: +tinybench@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg== -tinypool@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.1.tgz#c64233c4fac4304e109a64340178760116dbe1fe" - integrity sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA== +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.10: + version "0.2.12" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.12.tgz#ac941a42e0c5773bd0b5d08f32de82e74a1a61b5" + integrity sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww== + dependencies: + fdir "^6.4.3" + picomatch "^4.0.2" + +tinypool@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-1.0.2.tgz#706193cc532f4c100f66aa00b01c42173d9051b2" + integrity sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA== tinyrainbow@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-1.2.0.tgz#5c57d2fc0fb3d1afd78465c33ca885d04f02abb5" integrity sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ== -tinyspy@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.0.tgz#cb61644f2713cd84dee184863f4642e06ddf0585" - integrity sha512-q5nmENpTHgiPVd1cJDDc9cVoYN5x4vCvwT3FMilvKPKneCBZAxn2YWQjDF0UMcE9k0Cay1gBiDfTMU0g+mPMQA== +tinyrainbow@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-2.0.0.tgz#9509b2162436315e80e3eee0fcce4474d2444294" + integrity sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw== + +tinyspy@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" + integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -10152,9 +10061,9 @@ tslib@^1.8.1: integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: - version "2.6.2" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" - integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== tsutils@^3.21.0: version "3.21.0" @@ -10178,9 +10087,9 @@ type-check@^0.4.0, type-check@~0.4.0: prelude-ls "^1.2.1" type-detect@^4.0.0, type-detect@^4.0.5: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + version "4.1.0" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c" + integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw== type-fest@^0.16.0: version "0.16.0" @@ -10197,49 +10106,50 @@ type-fest@^0.21.3: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-typed-array "^1.1.13" + is-typed-array "^1.1.14" -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-proto "^1.0.3" is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" typescript@4.9.4: version "4.9.4" @@ -10247,9 +10157,9 @@ typescript@4.9.4: integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== typescript@^5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== + version "5.7.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" + integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== typeson-registry@^1.0.0-alpha.20: version "1.0.0-alpha.39" @@ -10265,15 +10175,15 @@ typeson@^6.0.0, typeson@^6.1.0: resolved "https://registry.yarnpkg.com/typeson/-/typeson-6.1.0.tgz#5b2a53705a5f58ff4d6f82f965917cabd0d7448b" integrity sha512-6FTtyGr8ldU0pfbvW/eOZrEtEkczHRUtduBnA90Jh9kMPCiFNnXIon3vF41N0S4tV1HHQt4Hk1j4srpESziCaA== -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" unbzip2-stream@1.4.3: version "1.4.3" @@ -10283,10 +10193,10 @@ unbzip2-stream@1.4.3: buffer "^5.2.1" through "^2.3.8" -undici-types@~5.26.4: - version "5.26.5" - resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617" - integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== undici-types@~6.20.0: version "6.20.0" @@ -10294,9 +10204,9 @@ undici-types@~6.20.0: integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== unicode-canonical-property-names-ecmascript@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz#301acdc525631670d39f6146e0e77ff6bbdebddc" - integrity sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ== + version "2.0.1" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz#cb3173fe47ca743e228216e4a3ddc4c84d628cc2" + integrity sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg== unicode-match-property-ecmascript@^2.0.0: version "2.0.0" @@ -10307,9 +10217,9 @@ unicode-match-property-ecmascript@^2.0.0: unicode-property-aliases-ecmascript "^2.0.0" unicode-match-property-value-ecmascript@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.1.0.tgz#cb5fffdcd16a05124f5a4b0bf7c3770208acbbe0" - integrity sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA== + version "2.2.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz#a0401aee72714598f739b68b104e4fe3a0cb3c71" + integrity sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg== unicode-property-aliases-ecmascript@^2.0.0: version "2.1.0" @@ -10352,23 +10262,15 @@ upath@^1.2.0: resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== -update-browserslist-db@^1.0.13: - version "1.0.16" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz#f6d489ed90fb2f07d67784eb3f53d7891f736356" - integrity sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ== +update-browserslist-db@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" + integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" + escalade "^3.2.0" + picocolors "^1.1.1" -update-browserslist-db@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" - integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== - dependencies: - escalade "^3.1.2" - picocolors "^1.0.1" - -uri-js@^4.2.2, uri-js@^4.4.1: +uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== @@ -10389,29 +10291,29 @@ url-parse@^1.5.3: requires-port "^1.0.0" use-callback-ref@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" - integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== dependencies: tslib "^2.0.0" use-isomorphic-layout-effect@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz#497cefb13d863d687b08477d9e5a164ad8c1a6fb" - integrity sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz#afb292eb284c39219e8cb8d3d62d71999361a21d" + integrity sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w== use-sidecar@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.2.tgz#2f43126ba2d7d7e117aa5855e5d8f0276dfe73c2" - integrity sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw== + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== dependencies: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" - integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== +use-sync-external-store@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== util-deprecate@^1.0.1, util-deprecate@^1.0.2: version "1.0.2" @@ -10438,16 +10340,16 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz#cdada8bec61e15865f05d097c5f4fd30e94dc128" integrity sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw== -vite-node@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.0.5.tgz#36d909188fc6e3aba3da5fc095b3637d0d18e27b" - integrity sha512-LdsW4pxj0Ot69FAoXZ1yTnA9bjGohr2yNBU7QKRxpz8ITSkhuDl6h3zS/tvgz4qrNjeRnvrWeXQ8ZF7Um4W00Q== +vite-node@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-3.0.6.tgz#a68c06c08e95c9a83f21993eabb17e0398804b1b" + integrity sha512-s51RzrTkXKJrhNbUzQRsarjmAae7VmMPAsRT7lppVpIg6mK3zGthP9Hgz0YQQKuNcF+Ii7DfYk3Fxz40jRmePw== dependencies: cac "^6.7.14" - debug "^4.3.5" - pathe "^1.1.2" - tinyrainbow "^1.2.0" - vite "^5.0.0" + debug "^4.4.0" + es-module-lexer "^1.6.0" + pathe "^2.0.3" + vite "^5.0.0 || ^6.0.0" vite-plugin-checker@0.7.2: version "0.7.2" @@ -10494,16 +10396,16 @@ vite-plugin-html@3.2.2: node-html-parser "^5.3.3" pathe "^0.2.0" -vite-plugin-pwa@0.17.4: - version "0.17.4" - resolved "https://registry.yarnpkg.com/vite-plugin-pwa/-/vite-plugin-pwa-0.17.4.tgz#be3b3714d4148681bc73e8e0b1e6ce1a71fa79f2" - integrity sha512-j9iiyinFOYyof4Zk3Q+DtmYyDVBDAi6PuMGNGq6uGI0pw7E+LNm9e+nQ2ep9obMP/kjdWwzilqUrlfVRj9OobA== +vite-plugin-pwa@0.21.1: + version "0.21.1" + resolved "https://registry.yarnpkg.com/vite-plugin-pwa/-/vite-plugin-pwa-0.21.1.tgz#2fb718ce6c7e62729d51e91bce739232e4a8e792" + integrity sha512-rkTbKFbd232WdiRJ9R3u+hZmf5SfQljX1b45NF6oLA6DSktEKpYllgTo1l2lkiZWMWV78pABJtFjNXfBef3/3Q== dependencies: - debug "^4.3.4" - fast-glob "^3.3.2" + debug "^4.3.6" pretty-bytes "^6.1.1" - workbox-build "^7.0.0" - workbox-window "^7.0.0" + tinyglobby "^0.2.10" + workbox-build "^7.3.0" + workbox-window "^7.3.0" vite-plugin-sitemap@0.7.1: version "0.7.1" @@ -10530,14 +10432,14 @@ vite@5.0.12: optionalDependencies: fsevents "~2.3.3" -vite@^5.0.0: - version "5.2.11" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.11.tgz#726ec05555431735853417c3c0bfb36003ca0cbd" - integrity sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ== +"vite@^5.0.0 || ^6.0.0": + version "6.1.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.1.1.tgz#c1f221749298357b9230782a04483e60ad83c8db" + integrity sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA== dependencies: - esbuild "^0.20.1" - postcss "^8.4.38" - rollup "^4.13.0" + esbuild "^0.24.2" + postcss "^8.5.2" + rollup "^4.30.1" optionalDependencies: fsevents "~2.3.3" @@ -10548,29 +10450,30 @@ vitest-canvas-mock@0.3.3: dependencies: jest-canvas-mock "~2.5.2" -vitest@2.0.5: - version "2.0.5" - resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.0.5.tgz#2f15a532704a7181528e399cc5b754c7f335fd62" - integrity sha512-8GUxONfauuIdeSl5f9GTgVEpg5BTOlplET4WEDaeY2QBiN8wSm68vxN/tb5z405OwppfoCavnwXafiaYBC/xOA== +vitest@3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-3.0.6.tgz#2fd1571a3cc1fa1648e29af73ff2dc85872f3a69" + integrity sha512-/iL1Sc5VeDZKPDe58oGK4HUFLhw6b5XdY1MYawjuSaDA4sEfYlY9HnS6aCEG26fX+MgUi7MwlduTBHHAI/OvMA== dependencies: - "@ampproject/remapping" "^2.3.0" - "@vitest/expect" "2.0.5" - "@vitest/pretty-format" "^2.0.5" - "@vitest/runner" "2.0.5" - "@vitest/snapshot" "2.0.5" - "@vitest/spy" "2.0.5" - "@vitest/utils" "2.0.5" - chai "^5.1.1" - debug "^4.3.5" - execa "^8.0.1" - magic-string "^0.30.10" - pathe "^1.1.2" - std-env "^3.7.0" - tinybench "^2.8.0" - tinypool "^1.0.0" - tinyrainbow "^1.2.0" - vite "^5.0.0" - vite-node "2.0.5" + "@vitest/expect" "3.0.6" + "@vitest/mocker" "3.0.6" + "@vitest/pretty-format" "^3.0.6" + "@vitest/runner" "3.0.6" + "@vitest/snapshot" "3.0.6" + "@vitest/spy" "3.0.6" + "@vitest/utils" "3.0.6" + chai "^5.2.0" + debug "^4.4.0" + expect-type "^1.1.0" + magic-string "^0.30.17" + pathe "^2.0.3" + std-env "^3.8.0" + tinybench "^2.9.0" + tinyexec "^0.3.2" + tinypool "^1.0.2" + tinyrainbow "^2.0.0" + vite "^5.0.0 || ^6.0.0" + vite-node "3.0.6" why-is-node-running "^2.3.0" vscode-jsonrpc@6.0.0: @@ -10596,9 +10499,9 @@ vscode-languageserver-protocol@3.16.0: vscode-languageserver-types "3.16.0" vscode-languageserver-textdocument@^1.0.1: - version "1.0.11" - resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.11.tgz#0822a000e7d4dc083312580d7575fe9e3ba2e2bf" - integrity sha512-X+8T3GoiwTVlJbicx/sIAF+yuJAqz8VvwJyoMVhwEMoEKE/fkDmrqUgDMyBECcM2A2frVZIUj5HI/ErRXCfOeA== + version "1.0.12" + resolved "https://registry.yarnpkg.com/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz#457ee04271ab38998a093c68c2342f53f6e4a631" + integrity sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA== vscode-languageserver-types@3.16.0: version "3.16.0" @@ -10613,9 +10516,9 @@ vscode-languageserver@^7.0.0: vscode-languageserver-protocol "3.16.0" vscode-uri@^3.0.2: - version "3.0.8" - resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.0.8.tgz#1770938d3e72588659a172d0fd4642780083ff9f" - integrity sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/vscode-uri/-/vscode-uri-3.1.0.tgz#dd09ec5a66a38b5c3fffc774015713496d14e09c" + integrity sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ== w3c-xmlserializer@^4.0.0: version "4.0.0" @@ -10625,9 +10528,9 @@ w3c-xmlserializer@^4.0.0: xml-name-validator "^4.0.0" watchpack@^2.4.0, watchpack@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff" - integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg== + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -10645,9 +10548,9 @@ web-vitals@^4.2.4: integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== web-worker@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.3.0.tgz#e5f2df5c7fe356755a5fb8f8410d4312627e6776" - integrity sha512-BSR9wyRsy/KOValMgd5kMyr3JzpdeoR9KVId8u5GVlTTAtNChlsE4yTxeY7zMdNSyOmoKBv8NH2qeRY9Tg+IaA== + version "1.5.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5" + integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== webidl-conversions@^3.0.0: version "3.0.1" @@ -10747,20 +10650,19 @@ webpack@5.76.0: webpack-sources "^3.2.3" webpack@^5.88.2: - version "5.91.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9" - integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw== + version "5.98.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.98.0.tgz#44ae19a8f2ba97537978246072fb89d10d1fbd17" + integrity sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA== dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^1.0.5" - "@webassemblyjs/ast" "^1.12.1" - "@webassemblyjs/wasm-edit" "^1.12.1" - "@webassemblyjs/wasm-parser" "^1.12.1" - acorn "^8.7.1" - acorn-import-assertions "^1.9.0" - browserslist "^4.21.10" + "@types/eslint-scope" "^3.7.7" + "@types/estree" "^1.0.6" + "@webassemblyjs/ast" "^1.14.1" + "@webassemblyjs/wasm-edit" "^1.14.1" + "@webassemblyjs/wasm-parser" "^1.14.1" + acorn "^8.14.0" + browserslist "^4.24.0" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.16.0" + enhanced-resolve "^5.17.1" es-module-lexer "^1.2.1" eslint-scope "5.1.1" events "^3.2.0" @@ -10770,9 +10672,9 @@ webpack@^5.88.2: loader-runner "^4.2.0" mime-types "^2.1.27" neo-async "^2.6.2" - schema-utils "^3.2.0" + schema-utils "^4.3.0" tapable "^2.1.1" - terser-webpack-plugin "^5.3.10" + terser-webpack-plugin "^5.3.11" watchpack "^2.4.1" webpack-sources "^3.2.3" @@ -10841,36 +10743,37 @@ whatwg-url@^8.4.0: tr46 "^2.1.0" webidl-conversions "^6.1.0" -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" -which-builtin-type@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.3.tgz#b1b8443707cc58b6e9bf98d32110ff0c2cbd029b" - integrity sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw== +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== dependencies: - function.prototype.name "^1.1.5" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + function.prototype.name "^1.1.6" + has-tostringtag "^1.0.2" is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" is-generator-function "^1.0.10" - is-regex "^1.1.4" + is-regex "^1.2.1" is-weakref "^1.0.2" isarray "^2.0.5" - which-boxed-primitive "^1.0.2" - which-collection "^1.0.1" - which-typed-array "^1.1.9" + which-boxed-primitive "^1.1.0" + which-collection "^1.0.2" + which-typed-array "^1.1.16" -which-collection@^1.0.1: +which-collection@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== @@ -10880,15 +10783,16 @@ which-collection@^1.0.1: is-weakmap "^2.0.2" is-weakset "^2.0.3" -which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== +which-typed-array@^1.1.16, which-typed-array@^1.1.18: + version "1.1.18" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad" + integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" for-each "^0.3.3" - gopd "^1.0.1" + gopd "^1.2.0" has-tostringtag "^1.0.2" which@4.0.0: @@ -10923,25 +10827,25 @@ word-wrap@^1.2.5: resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -workbox-background-sync@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-7.1.0.tgz#dac65e30af603511f1c92c3e99f53d6c064fde90" - integrity sha512-rMbgrzueVWDFcEq1610YyDW71z0oAXLfdRHRQcKw4SGihkfOK0JUEvqWHFwA6rJ+6TClnMIn7KQI5PNN1XQXwQ== +workbox-background-sync@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-background-sync/-/workbox-background-sync-7.3.0.tgz#b6340731a8d5b42b9e75a8a87c8806928e6e6303" + integrity sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg== dependencies: idb "^7.0.1" - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-broadcast-update@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-7.1.0.tgz#fe21c491cc70f1e037898bba63de0752ef59bd82" - integrity sha512-O36hIfhjej/c5ar95pO67k1GQw0/bw5tKP7CERNgK+JdxBANQhDmIuOXZTNvwb2IHBx9hj2kxvcDyRIh5nzOgQ== +workbox-broadcast-update@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-broadcast-update/-/workbox-broadcast-update-7.3.0.tgz#bff86b91795c4b9fa46a758d1a7a151828623280" + integrity sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-build@^7.0.0: - version "7.1.1" - resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-7.1.1.tgz#bfbd4c44848c175b7773f921be3597cbfaaef827" - integrity sha512-WdkVdC70VMpf5NBCtNbiwdSZeKVuhTEd5PV3mAwpTQCGAB5XbOny1P9egEgNdetv4srAMmMKjvBk4RD58LpooA== +workbox-build@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-build/-/workbox-build-7.3.0.tgz#ab688f3241b32862236aeeb62b240195f1fe4b62" + integrity sha512-JGL6vZTPlxnlqZRhR/K/msqg3wKP+m0wfEUVosK7gsYzSgeIxvZLi1ViJJzVL7CEeI8r7rGFV973RiEqkP3lWQ== dependencies: "@apideck/better-ajv-errors" "^0.3.1" "@babel/core" "^7.24.4" @@ -10965,121 +10869,121 @@ workbox-build@^7.0.0: strip-comments "^2.0.1" tempy "^0.6.0" upath "^1.2.0" - workbox-background-sync "7.1.0" - workbox-broadcast-update "7.1.0" - workbox-cacheable-response "7.1.0" - workbox-core "7.1.0" - workbox-expiration "7.1.0" - workbox-google-analytics "7.1.0" - workbox-navigation-preload "7.1.0" - workbox-precaching "7.1.0" - workbox-range-requests "7.1.0" - workbox-recipes "7.1.0" - workbox-routing "7.1.0" - workbox-strategies "7.1.0" - workbox-streams "7.1.0" - workbox-sw "7.1.0" - workbox-window "7.1.0" + workbox-background-sync "7.3.0" + workbox-broadcast-update "7.3.0" + workbox-cacheable-response "7.3.0" + workbox-core "7.3.0" + workbox-expiration "7.3.0" + workbox-google-analytics "7.3.0" + workbox-navigation-preload "7.3.0" + workbox-precaching "7.3.0" + workbox-range-requests "7.3.0" + workbox-recipes "7.3.0" + workbox-routing "7.3.0" + workbox-strategies "7.3.0" + workbox-streams "7.3.0" + workbox-sw "7.3.0" + workbox-window "7.3.0" -workbox-cacheable-response@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-7.1.0.tgz#d138cc8ef2c32a9f28f29c5b2b0a8681da846c33" - integrity sha512-iwsLBll8Hvua3xCuBB9h92+/e0wdsmSVgR2ZlvcfjepZWwhd3osumQB3x9o7flj+FehtWM2VHbZn8UJeBXXo6Q== +workbox-cacheable-response@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-cacheable-response/-/workbox-cacheable-response-7.3.0.tgz#557b0f5fdfceb22fe243e3f19807c76a0ae646e3" + integrity sha512-eAFERIg6J2LuyELhLlmeRcJFa5e16Mj8kL2yCDbhWE+HUun9skRQrGIFVUagqWj4DMaaPSMWfAolM7XZZxNmxA== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-core@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-7.1.0.tgz#1867576f994f20d9991b71a7d0b2581af22db170" - integrity sha512-5KB4KOY8rtL31nEF7BfvU7FMzKT4B5TkbYa2tzkS+Peqj0gayMT9SytSFtNzlrvMaWgv6y/yvP9C0IbpFjV30Q== +workbox-core@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-core/-/workbox-core-7.3.0.tgz#f24fb92041a0b7482fe2dd856544aaa9fa105248" + integrity sha512-Z+mYrErfh4t3zi7NVTvOuACB0A/jA3bgxUN3PwtAVHvfEsZxV9Iju580VEETug3zYJRc0Dmii/aixI/Uxj8fmw== -workbox-expiration@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-7.1.0.tgz#c9d348ffc8c3d1ffdddaf6c37bf5be830a69073e" - integrity sha512-m5DcMY+A63rJlPTbbBNtpJ20i3enkyOtSgYfv/l8h+D6YbbNiA0zKEkCUaMsdDlxggla1oOfRkyqTvl5Ni5KQQ== +workbox-expiration@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-expiration/-/workbox-expiration-7.3.0.tgz#2c1ee1fdada34aa7e7474f706d5429c914bd10d2" + integrity sha512-lpnSSLp2BM+K6bgFCWc5bS1LR5pAwDWbcKt1iL87/eTSJRdLdAwGQznZE+1czLgn/X05YChsrEegTNxjM067vQ== dependencies: idb "^7.0.1" - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-google-analytics@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-7.1.0.tgz#25cca57a05554b6121521590543e59628eb15a65" - integrity sha512-FvE53kBQHfVTcZyczeBVRexhh7JTkyQ8HAvbVY6mXd2n2A7Oyz/9fIwnY406ZcDhvE4NFfKGjW56N4gBiqkrew== +workbox-google-analytics@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-google-analytics/-/workbox-google-analytics-7.3.0.tgz#3c4d4956c0a9800dfb587d82ec8bc0f9cf963791" + integrity sha512-ii/tSfFdhjLHZ2BrYgFNTrb/yk04pw2hasgbM70jpZfLk0vdJAXgaiMAWsoE+wfJDNWoZmBYY0hMVI0v5wWDbg== dependencies: - workbox-background-sync "7.1.0" - workbox-core "7.1.0" - workbox-routing "7.1.0" - workbox-strategies "7.1.0" + workbox-background-sync "7.3.0" + workbox-core "7.3.0" + workbox-routing "7.3.0" + workbox-strategies "7.3.0" -workbox-navigation-preload@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-7.1.0.tgz#2610674d412a1774b5d9f03c9644c9964407b8b6" - integrity sha512-4wyAbo0vNI/X0uWNJhCMKxnPanNyhybsReMGN9QUpaePLTiDpKxPqFxl4oUmBNddPwIXug01eTSLVIFXimRG/A== +workbox-navigation-preload@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-navigation-preload/-/workbox-navigation-preload-7.3.0.tgz#9d54693b9179d5175e66af5ef9a92d1b7cf3e605" + integrity sha512-fTJzogmFaTv4bShZ6aA7Bfj4Cewaq5rp30qcxl2iYM45YD79rKIhvzNHiFj1P+u5ZZldroqhASXwwoyusnr2cg== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-precaching@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-7.1.0.tgz#71e27ec2e85661a41b48dec0c92dae707c429eaa" - integrity sha512-LyxzQts+UEpgtmfnolo0hHdNjoB7EoRWcF7EDslt+lQGd0lW4iTvvSe3v5JiIckQSB5KTW5xiCqjFviRKPj1zA== +workbox-precaching@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-precaching/-/workbox-precaching-7.3.0.tgz#a84663d69efdb334f25c04dba0a72ed3391c4da8" + integrity sha512-ckp/3t0msgXclVAYaNndAGeAoWQUv7Rwc4fdhWL69CCAb2UHo3Cef0KIUctqfQj1p8h6aGyz3w8Cy3Ihq9OmIw== dependencies: - workbox-core "7.1.0" - workbox-routing "7.1.0" - workbox-strategies "7.1.0" + workbox-core "7.3.0" + workbox-routing "7.3.0" + workbox-strategies "7.3.0" -workbox-range-requests@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-7.1.0.tgz#8d4344cd85b87d8077289a64dda59fb614628783" - integrity sha512-m7+O4EHolNs5yb/79CrnwPR/g/PRzMFYEdo01LqwixVnc/sbzNSvKz0d04OE3aMRel1CwAAZQheRsqGDwATgPQ== +workbox-range-requests@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-range-requests/-/workbox-range-requests-7.3.0.tgz#1b3d5c235a0ff5271418c3a7183281dc131ccd0d" + integrity sha512-EyFmM1KpDzzAouNF3+EWa15yDEenwxoeXu9bgxOEYnFfCxns7eAxA9WSSaVd8kujFFt3eIbShNqa4hLQNFvmVQ== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-recipes@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-7.1.0.tgz#37625cd2fe7e5decd70c8934a673a7cc080a7675" - integrity sha512-NRrk4ycFN9BHXJB6WrKiRX3W3w75YNrNrzSX9cEZgFB5ubeGoO8s/SDmOYVrFYp9HMw6sh1Pm3eAY/1gVS8YLg== +workbox-recipes@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-recipes/-/workbox-recipes-7.3.0.tgz#fa407101e8ce52850dfba8e17a5afccb733a3942" + integrity sha512-BJro/MpuW35I/zjZQBcoxsctgeB+kyb2JAP5EB3EYzePg8wDGoQuUdyYQS+CheTb+GhqJeWmVs3QxLI8EBP1sg== dependencies: - workbox-cacheable-response "7.1.0" - workbox-core "7.1.0" - workbox-expiration "7.1.0" - workbox-precaching "7.1.0" - workbox-routing "7.1.0" - workbox-strategies "7.1.0" + workbox-cacheable-response "7.3.0" + workbox-core "7.3.0" + workbox-expiration "7.3.0" + workbox-precaching "7.3.0" + workbox-routing "7.3.0" + workbox-strategies "7.3.0" -workbox-routing@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-7.1.0.tgz#c44bda350d1c5eb633ee97a660e64ce5473250c4" - integrity sha512-oOYk+kLriUY2QyHkIilxUlVcFqwduLJB7oRZIENbqPGeBP/3TWHYNNdmGNhz1dvKuw7aqvJ7CQxn27/jprlTdg== +workbox-routing@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-routing/-/workbox-routing-7.3.0.tgz#fc86296bc1155c112ee2c16b3180853586c30208" + integrity sha512-ZUlysUVn5ZUzMOmQN3bqu+gK98vNfgX/gSTZ127izJg/pMMy4LryAthnYtjuqcjkN4HEAx1mdgxNiKJMZQM76A== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-strategies@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-7.1.0.tgz#a589f2adc0df8f33049c7f4d4cdf4c9556715918" - integrity sha512-/UracPiGhUNehGjRm/tLUQ+9PtWmCbRufWtV0tNrALuf+HZ4F7cmObSEK+E4/Bx1p8Syx2tM+pkIrvtyetdlew== +workbox-strategies@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-strategies/-/workbox-strategies-7.3.0.tgz#bb1530f205806895aacdea3639e6cf6bfb3a6cb0" + integrity sha512-tmZydug+qzDFATwX7QiEL5Hdf7FrkhjaF9db1CbB39sDmEZJg3l9ayDvPxy8Y18C3Y66Nrr9kkN1f/RlkDgllg== dependencies: - workbox-core "7.1.0" + workbox-core "7.3.0" -workbox-streams@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-7.1.0.tgz#8e080e56b5dee7aa0f956fdd3a10506821d2e786" - integrity sha512-WyHAVxRXBMfysM8ORwiZnI98wvGWTVAq/lOyBjf00pXFvG0mNaVz4Ji+u+fKa/mf1i2SnTfikoYKto4ihHeS6w== +workbox-streams@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-streams/-/workbox-streams-7.3.0.tgz#a4c0ae51b66121a2aa6f89229e237aca6dc27eb5" + integrity sha512-SZnXucyg8x2Y61VGtDjKPO5EgPUG5NDn/v86WYHX+9ZqvAsGOytP0Jxp1bl663YUuMoXSAtsGLL+byHzEuMRpw== dependencies: - workbox-core "7.1.0" - workbox-routing "7.1.0" + workbox-core "7.3.0" + workbox-routing "7.3.0" -workbox-sw@7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-7.1.0.tgz#3df97d7cccb647eb94d66be7dc733c9fda26b9fc" - integrity sha512-Hml/9+/njUXBglv3dtZ9WBKHI235AQJyLBV1G7EFmh4/mUdSQuXui80RtjDeVRrXnm/6QWgRUEHG3/YBVbxtsA== +workbox-sw@7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-sw/-/workbox-sw-7.3.0.tgz#39215017e868d7cfe6835b2961f55369d89b3e73" + integrity sha512-aCUyoAZU9IZtH05mn0ACUpyHzPs0lMeJimAYkQkBsOWiqaJLgusfDCR+yllkPkFRxWpZKF8vSvgHYeG7LwhlmA== -workbox-window@7.1.0, workbox-window@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-7.1.0.tgz#58a90ba89ca35d26f2b322223ee575c750bac7a1" - integrity sha512-ZHeROyqR+AS5UPzholQRDttLFqGMwP0Np8MKWAdyxsDETxq3qOAyXvqessc3GniohG6e0mAqSQyKOHmT8zPF7g== +workbox-window@7.3.0, workbox-window@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/workbox-window/-/workbox-window-7.3.0.tgz#e71bb0b4d880d2295c96bf1ccadb6cea0df51c07" + integrity sha512-qW8PDy16OV1UBaUNGlTVcepzrlzyzNW/ZJvFQQs2j2TzGsg6IKjcpZC1RSquqQnTOafl5pCj5bGfAHlCjOOjdA== dependencies: "@types/trusted-types" "^2.0.2" - workbox-core "7.1.0" + workbox-core "7.3.0" "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" @@ -11128,19 +11032,19 @@ ws@8.5.0: integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== ws@^7.3.1: - version "7.5.9" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591" - integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q== + version "7.5.10" + resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" + integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== ws@^8.13.0: - version "8.17.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea" - integrity sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow== + version "8.18.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" + integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w== -ws@~8.11.0: - version "8.11.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.11.0.tgz#6a0d36b8edfd9f96d8b25683db2f8d7de6e8e143" - integrity sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg== +ws@~8.17.1: + version "8.17.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b" + integrity sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ== xml-name-validator@^4.0.0: version "4.0.0" @@ -11157,6 +11061,11 @@ xmlhttprequest-ssl@~2.0.0: resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz#91360c86b914e67f44dce769180027c0da618c67" integrity sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A== +xmlhttprequest-ssl@~2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.2.tgz#e9e8023b3f29ef34b97a859f584c5e6c61418e23" + integrity sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -11204,8 +11113,8 @@ yauzl@^2.10.0: fd-slicer "~1.1.0" zustand@^4.3.2: - version "4.5.2" - resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.2.tgz#fddbe7cac1e71d45413b3682cdb47b48034c3848" - integrity sha512-2cN1tPkDVkwCy5ickKrI7vijSjPksFRfqS6237NzT0vqSsztTNnQdHw9mmN7uBdk3gceVXU0a+21jFzFzAc9+g== + version "4.5.6" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.6.tgz#6857d52af44874a79fb3408c9473f78367255c96" + integrity sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ== dependencies: - use-sync-external-store "1.2.0" + use-sync-external-store "^1.2.2" From 0ffeaeaecfc77a952c3468ad81f56f1c7489177a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Tue, 25 Feb 2025 22:52:06 +0100 Subject: [PATCH 25/51] feat: Remove GA code from binding (#9042) Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com> --- excalidraw-app/components/DebugCanvas.tsx | 34 + .../excalidraw/actions/actionProperties.tsx | 10 +- packages/excalidraw/constants.ts | 2 +- .../data/__snapshots__/transform.test.ts.snap | 32 +- packages/excalidraw/data/transform.test.ts | 7 +- packages/excalidraw/element/binding.ts | 999 +++++++----------- packages/excalidraw/element/collision.ts | 190 +++- packages/excalidraw/element/distance.ts | 123 +++ .../excalidraw/element/elbowArrow.test.tsx | 1 + packages/excalidraw/element/elbowArrow.ts | 58 +- packages/excalidraw/element/utils.ts | 355 +++++++ .../tests/__snapshots__/history.test.tsx.snap | 181 ++-- .../tests/__snapshots__/move.test.tsx.snap | 10 +- packages/excalidraw/tests/binding.test.tsx | 3 - packages/excalidraw/tests/history.test.tsx | 33 +- .../tests/linearElementEditor.test.tsx | 2 +- packages/excalidraw/tests/move.test.tsx | 2 +- packages/excalidraw/tests/resize.test.tsx | 25 +- packages/excalidraw/tests/rotate.test.tsx | 6 +- packages/excalidraw/tests/test-utils.ts | 31 - packages/excalidraw/visualdebug.ts | 56 +- packages/math/angle.ts | 5 +- packages/math/arc.test.ts | 41 - packages/math/arc.ts | 20 - packages/math/curve.test.ts | 101 ++ packages/math/curve.ts | 431 ++++---- packages/math/ellipse.test.ts | 126 +++ packages/math/ellipse.ts | 230 ++++ packages/math/ga/ga.test.ts | 70 -- packages/math/ga/ga.ts | 317 ------ packages/math/ga/gadirections.ts | 26 - packages/math/ga/galines.ts | 52 - packages/math/ga/gapoints.ts | 42 - packages/math/ga/gatransforms.ts | 41 - packages/math/index.ts | 2 +- packages/math/line.test.ts | 31 + packages/math/line.ts | 58 +- packages/math/point.ts | 49 +- packages/math/rectangle.ts | 23 + packages/math/segment.test.ts | 21 + packages/math/segment.ts | 32 +- packages/math/types.ts | 22 +- packages/math/vector.ts | 11 +- packages/utils/test-utils.ts | 33 + 44 files changed, 2112 insertions(+), 1832 deletions(-) create mode 100644 packages/excalidraw/element/distance.ts create mode 100644 packages/excalidraw/element/utils.ts delete mode 100644 packages/math/arc.test.ts delete mode 100644 packages/math/arc.ts create mode 100644 packages/math/curve.test.ts create mode 100644 packages/math/ellipse.test.ts create mode 100644 packages/math/ellipse.ts delete mode 100644 packages/math/ga/ga.test.ts delete mode 100644 packages/math/ga/ga.ts delete mode 100644 packages/math/ga/gadirections.ts delete mode 100644 packages/math/ga/galines.ts delete mode 100644 packages/math/ga/gapoints.ts delete mode 100644 packages/math/ga/gatransforms.ts create mode 100644 packages/math/line.test.ts create mode 100644 packages/math/rectangle.ts create mode 100644 packages/math/segment.test.ts create mode 100644 packages/utils/test-utils.ts diff --git a/excalidraw-app/components/DebugCanvas.tsx b/excalidraw-app/components/DebugCanvas.tsx index fe2c617fc..13b4bd6c0 100644 --- a/excalidraw-app/components/DebugCanvas.tsx +++ b/excalidraw-app/components/DebugCanvas.tsx @@ -12,11 +12,13 @@ import { TrashIcon, } from "../../packages/excalidraw/components/icons"; import { STORAGE_KEYS } from "../app_constants"; +import type { Curve } from "../../packages/math"; import { isLineSegment, type GlobalPoint, type LineSegment, } from "../../packages/math"; +import { isCurve } from "../../packages/math/curve"; const renderLine = ( context: CanvasRenderingContext2D, @@ -33,6 +35,28 @@ const renderLine = ( context.restore(); }; +const renderCubicBezier = ( + context: CanvasRenderingContext2D, + zoom: number, + [start, control1, control2, end]: Curve, + color: string, +) => { + context.save(); + context.strokeStyle = color; + context.beginPath(); + context.moveTo(start[0] * zoom, start[1] * zoom); + context.bezierCurveTo( + control1[0] * zoom, + control1[1] * zoom, + control2[0] * zoom, + control2[1] * zoom, + end[0] * zoom, + end[1] * zoom, + ); + context.stroke(); + context.restore(); +}; + const renderOrigin = (context: CanvasRenderingContext2D, zoom: number) => { context.strokeStyle = "#888"; context.save(); @@ -60,6 +84,16 @@ const render = ( el.color, ); break; + case isCurve(el.data): + renderCubicBezier( + context, + appState.zoom.value, + el.data as Curve, + el.color, + ); + break; + default: + throw new Error(`Unknown element type ${JSON.stringify(el)}`); } }); }; diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 660d7e679..1552fc0c8 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1633,18 +1633,16 @@ export const actionChangeArrowType = register({ const finalStartPoint = startHoveredElement ? bindPointToSnapToElementOutline( - startGlobalPoint, - endGlobalPoint, + newElement, startHoveredElement, - elementsMap, + "start", ) : startGlobalPoint; const finalEndPoint = endHoveredElement ? bindPointToSnapToElementOutline( - endGlobalPoint, - startGlobalPoint, + newElement, endHoveredElement, - elementsMap, + "end", ) : endGlobalPoint; diff --git a/packages/excalidraw/constants.ts b/packages/excalidraw/constants.ts index cb32190b2..b01dc98ee 100644 --- a/packages/excalidraw/constants.ts +++ b/packages/excalidraw/constants.ts @@ -188,7 +188,7 @@ export const DEFAULT_TRANSFORM_HANDLE_SPACING = 2; export const SIDE_RESIZING_THRESHOLD = 2 * DEFAULT_TRANSFORM_HANDLE_SPACING; // a small epsilon to make side resizing always take precedence // (avoids an increase in renders and changes to tests) -const EPSILON = 0.00001; +export const EPSILON = 0.00001; export const DEFAULT_COLLISION_THRESHOLD = 2 * SIDE_RESIZING_THRESHOLD - EPSILON; diff --git a/packages/excalidraw/data/__snapshots__/transform.test.ts.snap b/packages/excalidraw/data/__snapshots__/transform.test.ts.snap index 0f86b84eb..917f3d95e 100644 --- a/packages/excalidraw/data/__snapshots__/transform.test.ts.snap +++ b/packages/excalidraw/data/__snapshots__/transform.test.ts.snap @@ -88,9 +88,8 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "endArrowhead": "arrow", "endBinding": { "elementId": "ellipse-1", - "fixedPoint": null, - "focus": -0.008153707962747813, - "gap": 1, + "focus": -0.007519379844961235, + "gap": 11.562288374879595, }, "fillStyle": "solid", "frameId": null, @@ -119,8 +118,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "startArrowhead": null, "startBinding": { "elementId": "id49", - "fixedPoint": null, - "focus": -0.08139534883720931, + "focus": -0.0813953488372095, "gap": 1, }, "strokeColor": "#1864ab", @@ -146,9 +144,8 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "endArrowhead": "arrow", "endBinding": { "elementId": "ellipse-1", - "fixedPoint": null, "focus": 0.10666666666666667, - "gap": 3.834326468444573, + "gap": 3.8343264684446097, }, "fillStyle": "solid", "frameId": null, @@ -177,9 +174,8 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing s "startArrowhead": null, "startBinding": { "elementId": "diamond-1", - "fixedPoint": null, "focus": 0, - "gap": 1, + "gap": 4.545343408287929, }, "strokeColor": "#e67700", "strokeStyle": "solid", @@ -338,7 +334,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t "endArrowhead": "arrow", "endBinding": { "elementId": "text-2", - "fixedPoint": null, "focus": 0, "gap": 14, }, @@ -369,7 +364,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to existing t "startArrowhead": null, "startBinding": { "elementId": "text-1", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -442,8 +436,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe "endArrowhead": "arrow", "endBinding": { "elementId": "id42", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -473,7 +466,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to shapes whe "startArrowhead": null, "startBinding": { "elementId": "id41", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -620,8 +612,7 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when "endArrowhead": "arrow", "endBinding": { "elementId": "id46", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -651,7 +642,6 @@ exports[`Test Transform > Test arrow bindings > should bind arrows to text when "startArrowhead": null, "startBinding": { "elementId": "id45", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -1484,8 +1474,7 @@ exports[`Test Transform > should transform the elements correctly when linear el "endArrowhead": "arrow", "endBinding": { "elementId": "Alice", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 5.299874999999986, }, "fillStyle": "solid", @@ -1517,7 +1506,6 @@ exports[`Test Transform > should transform the elements correctly when linear el "startArrowhead": null, "startBinding": { "elementId": "Bob", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -1549,9 +1537,8 @@ exports[`Test Transform > should transform the elements correctly when linear el "endArrowhead": "arrow", "endBinding": { "elementId": "B", - "fixedPoint": null, "focus": 0, - "gap": 1, + "gap": 14, }, "fillStyle": "solid", "frameId": null, @@ -1578,7 +1565,6 @@ exports[`Test Transform > should transform the elements correctly when linear el "startArrowhead": null, "startBinding": { "elementId": "Bob", - "fixedPoint": null, "focus": 0, "gap": 1, }, diff --git a/packages/excalidraw/data/transform.test.ts b/packages/excalidraw/data/transform.test.ts index ce0cf89f7..98a62daf7 100644 --- a/packages/excalidraw/data/transform.test.ts +++ b/packages/excalidraw/data/transform.test.ts @@ -434,7 +434,7 @@ describe("Test Transform", () => { }, endBinding: { elementId: ellipse.id, - focus: 0, + focus: -0, }, }); @@ -519,7 +519,7 @@ describe("Test Transform", () => { }, endBinding: { elementId: text3.id, - focus: 0, + focus: -0, }, }); @@ -777,8 +777,7 @@ describe("Test Transform", () => { const [arrow, rect] = excalidrawElements; expect((arrow as ExcalidrawArrowElement).endBinding).toStrictEqual({ elementId: "rect-1", - fixedPoint: null, - focus: 0, + focus: -0, gap: 14, }); expect(rect.boundElements).toStrictEqual([ diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index fa5b46181..332a70fcd 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -1,18 +1,6 @@ -import * as GA from "../../math/ga/ga"; -import * as GAPoint from "../../math/ga/gapoints"; -import * as GADirection from "../../math/ga/gadirections"; -import * as GALine from "../../math/ga/galines"; -import * as GATransform from "../../math/ga/gatransforms"; - import type { ExcalidrawBindableElement, ExcalidrawElement, - ExcalidrawRectangleElement, - ExcalidrawDiamondElement, - ExcalidrawEllipseElement, - ExcalidrawImageElement, - ExcalidrawFrameLikeElement, - ExcalidrawIframeLikeElement, NonDeleted, ExcalidrawLinearElement, PointBinding, @@ -25,11 +13,11 @@ import type { ExcalidrawElbowArrowElement, FixedPoint, SceneElementsMap, - ExcalidrawRectanguloidElement, + FixedPointBinding, } from "./types"; import type { Bounds } from "./bounds"; -import { getCenterForBounds, getElementAbsoluteCoords } from "./bounds"; +import { getCenterForBounds } from "./bounds"; import type { AppState } from "../types"; import { isPointOnShape } from "../../utils/collision"; import { @@ -41,7 +29,7 @@ import { isFixedPointBinding, isFrameLikeElement, isLinearElement, - isRectangularElement, + isRectanguloidElement, isTextElement, } from "./typeChecks"; import type { ElementUpdate } from "./mutateElement"; @@ -59,7 +47,6 @@ import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; import { compareHeading, HEADING_DOWN, - HEADING_LEFT, HEADING_RIGHT, HEADING_UP, headingForPointFromElement, @@ -73,11 +60,18 @@ import { pointRotateRads, type GlobalPoint, vectorFromPoint, - pointFromPair, pointDistanceSq, clamp, + pointDistance, + pointFromVector, + vectorScale, + vectorNormalize, + vectorCross, + pointsEqual, + lineSegmentIntersectionPoints, } from "../../math"; -import { segmentIntersectRectangleElement } from "../../utils/geometry/shape"; +import { intersectElementWithLineSegment } from "./collision"; +import { distanceToBindableElement } from "./distance"; export type SuggestedBinding = | NonDeleted @@ -474,25 +468,31 @@ export const bindLinearElement = ( if (!isArrowElement(linearElement)) { return; } - const binding: PointBinding = { + + const binding: PointBinding | FixedPointBinding = { elementId: hoveredElement.id, - ...normalizePointBinding( - calculateFocusAndGap( - linearElement, - hoveredElement, - startOrEnd, - elementsMap, - ), - hoveredElement, - ), ...(isElbowArrow(linearElement) - ? calculateFixedPointForElbowArrowBinding( - linearElement, - hoveredElement, - startOrEnd, - elementsMap, - ) - : { fixedPoint: null }), + ? { + ...calculateFixedPointForElbowArrowBinding( + linearElement, + hoveredElement, + startOrEnd, + elementsMap, + ), + focus: 0, + gap: 0, + } + : { + ...normalizePointBinding( + calculateFocusAndGap( + linearElement, + hoveredElement, + startOrEnd, + elementsMap, + ), + hoveredElement, + ), + }), }; mutateElement(linearElement, { @@ -703,17 +703,10 @@ const calculateFocusAndGap = ( adjacentPointIndex, elementsMap, ); + return { - focus: determineFocusDistance( - hoveredElement, - adjacentPoint, - edgePoint, - elementsMap, - ), - gap: Math.max( - 1, - distanceToBindableElement(hoveredElement, edgePoint, elementsMap), - ), + focus: determineFocusDistance(hoveredElement, adjacentPoint, edgePoint), + gap: Math.max(1, distanceToBindableElement(hoveredElement, edgePoint)), }; }; @@ -882,11 +875,7 @@ const getDistanceForBinding = ( elementsMap: ElementsMap, zoom?: AppState["zoom"], ) => { - const distance = distanceToBindableElement( - bindableElement, - point, - elementsMap, - ); + const distance = distanceToBindableElement(bindableElement, point); const bindDistance = maxBindingGap( bindableElement, bindableElement.width, @@ -898,52 +887,58 @@ const getDistanceForBinding = ( }; export const bindPointToSnapToElementOutline = ( - p: Readonly, - otherPoint: Readonly, + arrow: ExcalidrawElbowArrowElement, bindableElement: ExcalidrawBindableElement | undefined, - elementsMap: ElementsMap, + startOrEnd: "start" | "end", ): GlobalPoint => { const aabb = bindableElement && aabbForElement(bindableElement); + const localP = + arrow.points[startOrEnd === "start" ? 0 : arrow.points.length - 1]; + const globalP = pointFrom( + arrow.x + localP[0], + arrow.y + localP[1], + ); + const p = isRectanguloidElement(bindableElement) + ? avoidRectangularCorner(bindableElement, globalP) + : globalP; if (bindableElement && aabb) { - // TODO: Dirty hacks until tangents are properly calculated - const heading = headingForPointFromElement(bindableElement, aabb, p); - const intersections = [ - ...(intersectElementWithLine( - bindableElement, - pointFrom(p[0], p[1] - 2 * bindableElement.height), - pointFrom(p[0], p[1] + 2 * bindableElement.height), - FIXED_BINDING_DISTANCE, - elementsMap, - ) ?? []), - ...(intersectElementWithLine( - bindableElement, - pointFrom(p[0] - 2 * bindableElement.width, p[1]), - pointFrom(p[0] + 2 * bindableElement.width, p[1]), - FIXED_BINDING_DISTANCE, - elementsMap, - ) ?? []), - ]; + const center = getCenterForBounds(aabb); - const isVertical = - compareHeading(heading, HEADING_LEFT) || - compareHeading(heading, HEADING_RIGHT); - const dist = Math.abs( - distanceToBindableElement(bindableElement, p, elementsMap), - ); - const isInner = isVertical - ? dist < bindableElement.width * -0.1 - : dist < bindableElement.height * -0.1; + const intersection = intersectElementWithLineSegment( + bindableElement, + lineSegment( + center, + pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(p, center)), + Math.max(bindableElement.width, bindableElement.height), + ), + center, + ), + ), + )[0]; + const currentDistance = pointDistance(p, center); + const fullDistance = pointDistance(intersection, center); + const ratio = currentDistance / fullDistance; - intersections.sort((a, b) => pointDistanceSq(a, p) - pointDistanceSq(b, p)); + switch (true) { + case ratio > 0.9: + if (currentDistance - fullDistance > FIXED_BINDING_DISTANCE) { + return p; + } - return isInner - ? headingToMidBindPoint(otherPoint, bindableElement, aabb) - : intersections.filter((i) => - isVertical - ? Math.abs(p[1] - i[1]) < 0.1 - : Math.abs(p[0] - i[0]) < 0.1, - )[0] ?? p; + return pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(p, intersection)), + ratio > 1 ? FIXED_BINDING_DISTANCE : -FIXED_BINDING_DISTANCE, + ), + intersection, + ); + + default: + return headingToMidBindPoint(p, bindableElement, aabb); + } } return p; @@ -1208,7 +1203,6 @@ const updateBoundPoint = ( bindableElement, binding.focus, adjacentPoint, - elementsMap, ); let newEdgePoint: GlobalPoint; @@ -1218,20 +1212,64 @@ const updateBoundPoint = ( if (binding.gap === 0) { newEdgePoint = focusPointAbsolute; } else { - const intersections = intersectElementWithLine( - bindableElement, - adjacentPoint, - focusPointAbsolute, - binding.gap, - elementsMap, + const edgePointAbsolute = + LinearElementEditor.getPointAtIndexGlobalCoordinates( + linearElement, + edgePointIndex, + elementsMap, + ); + + const center = pointFrom( + bindableElement.x + bindableElement.width / 2, + bindableElement.y + bindableElement.height / 2, ); - if (!intersections || intersections.length === 0) { - // This should never happen, since focusPoint should always be - // inside the element, but just in case, bail out + const interceptorLength = + pointDistance(adjacentPoint, edgePointAbsolute) + + pointDistance(adjacentPoint, center) + + Math.max(bindableElement.width, bindableElement.height) * 2; + const intersections = intersectElementWithLineSegment( + bindableElement, + lineSegment( + adjacentPoint, + pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(focusPointAbsolute, adjacentPoint)), + interceptorLength, + ), + adjacentPoint, + ), + ), + binding.gap, + ).sort( + (g, h) => + pointDistanceSq(g, adjacentPoint) - pointDistanceSq(h, adjacentPoint), + ); + + // debugClear(); + // debugDrawPoint(intersections[0], { color: "red", permanent: true }); + // debugDrawLine( + // lineSegment( + // adjacentPoint, + // pointFromVector( + // vectorScale( + // vectorNormalize(vectorFromPoint(focusPointAbsolute, adjacentPoint)), + // interceptorLength, + // ), + // adjacentPoint, + // ), + // ), + // { permanent: true, color: "green" }, + // ); + + if (intersections.length > 1) { + // The adjacent point is outside the shape (+ gap) + newEdgePoint = intersections[0]; + } else if (intersections.length === 1) { + // The adjacent point is inside the shape (+ gap) newEdgePoint = focusPointAbsolute; } else { - // Guaranteed to intersect because focusPoint is always inside the shape - newEdgePoint = intersections[0]; + // Shouldn't happend, but just in case + newEdgePoint = edgePointAbsolute; } } @@ -1254,23 +1292,10 @@ export const calculateFixedPointForElbowArrowBinding = ( hoveredElement.x + hoveredElement.width, hoveredElement.y + hoveredElement.height, ] as Bounds; - const edgePointIndex = - startOrEnd === "start" ? 0 : linearElement.points.length - 1; - const globalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates( - linearElement, - edgePointIndex, - elementsMap, - ); - const otherGlobalPoint = LinearElementEditor.getPointAtIndexGlobalCoordinates( - linearElement, - edgePointIndex, - elementsMap, - ); const snappedPoint = bindPointToSnapToElementOutline( - globalPoint, - otherGlobalPoint, + linearElement, hoveredElement, - elementsMap, + startOrEnd, ); const globalMidPoint = pointFrom( bounds[0] + (bounds[2] - bounds[0]) / 2, @@ -1524,171 +1549,6 @@ export const maxBindingGap = ( ); }; -export const distanceToBindableElement = ( - element: ExcalidrawBindableElement, - point: GlobalPoint, - elementsMap: ElementsMap, -): number => { - switch (element.type) { - case "rectangle": - case "image": - case "text": - case "iframe": - case "embeddable": - case "frame": - case "magicframe": - return distanceToRectangle(element, point, elementsMap); - case "diamond": - return distanceToDiamond(element, point, elementsMap); - case "ellipse": - return distanceToEllipse(element, point, elementsMap); - } -}; - -const distanceToRectangle = ( - element: ExcalidrawRectanguloidElement, - p: GlobalPoint, - elementsMap: ElementsMap, -): number => { - const [, pointRel, hwidth, hheight] = pointRelativeToElement( - element, - p, - elementsMap, - ); - return Math.max( - GAPoint.distanceToLine(pointRel, GALine.equation(0, 1, -hheight)), - GAPoint.distanceToLine(pointRel, GALine.equation(1, 0, -hwidth)), - ); -}; - -const distanceToDiamond = ( - element: ExcalidrawDiamondElement, - point: GlobalPoint, - elementsMap: ElementsMap, -): number => { - const [, pointRel, hwidth, hheight] = pointRelativeToElement( - element, - point, - elementsMap, - ); - const side = GALine.equation(hheight, hwidth, -hheight * hwidth); - return GAPoint.distanceToLine(pointRel, side); -}; - -const distanceToEllipse = ( - element: ExcalidrawEllipseElement, - point: GlobalPoint, - elementsMap: ElementsMap, -): number => { - const [pointRel, tangent] = ellipseParamsForTest(element, point, elementsMap); - return -GALine.sign(tangent) * GAPoint.distanceToLine(pointRel, tangent); -}; - -const ellipseParamsForTest = ( - element: ExcalidrawEllipseElement, - point: GlobalPoint, - elementsMap: ElementsMap, -): [GA.Point, GA.Line] => { - const [, pointRel, hwidth, hheight] = pointRelativeToElement( - element, - point, - elementsMap, - ); - const [px, py] = GAPoint.toTuple(pointRel); - - // We're working in positive quadrant, so start with `t = 45deg`, `tx=cos(t)` - let tx = 0.707; - let ty = 0.707; - - const a = hwidth; - const b = hheight; - - // This is a numerical method to find the params tx, ty at which - // the ellipse has the closest point to the given point - [0, 1, 2, 3].forEach((_) => { - const xx = a * tx; - const yy = b * ty; - - const ex = ((a * a - b * b) * tx ** 3) / a; - const ey = ((b * b - a * a) * ty ** 3) / b; - - const rx = xx - ex; - const ry = yy - ey; - - const qx = px - ex; - const qy = py - ey; - - const r = Math.hypot(ry, rx); - const q = Math.hypot(qy, qx); - - tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a)); - ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b)); - const t = Math.hypot(ty, tx); - tx /= t; - ty /= t; - }); - - const closestPoint = GA.point(a * tx, b * ty); - - const tangent = GALine.orthogonalThrough(pointRel, closestPoint); - return [pointRel, tangent]; -}; - -// Returns: -// 1. the point relative to the elements (x, y) position -// 2. the point relative to the element's center with positive (x, y) -// 3. half element width -// 4. half element height -// -// Note that for linear elements the (x, y) position is not at the -// top right corner of their boundary. -// -// Rectangles, diamonds and ellipses are symmetrical over axes, -// and other elements have a rectangular boundary, -// so we only need to perform hit tests for the positive quadrant. -const pointRelativeToElement = ( - element: ExcalidrawElement, - pointTuple: GlobalPoint, - elementsMap: ElementsMap, -): [GA.Point, GA.Point, number, number] => { - const point = GAPoint.from(pointTuple); - const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap); - const center = coordsCenter(x1, y1, x2, y2); - // GA has angle orientation opposite to `rotate` - const rotate = GATransform.rotation(center, element.angle); - const pointRotated = GATransform.apply(rotate, point); - const pointRelToCenter = GA.sub(pointRotated, GADirection.from(center)); - const pointRelToCenterAbs = GAPoint.abs(pointRelToCenter); - const elementPos = GA.offset(element.x, element.y); - const pointRelToPos = GA.sub(pointRotated, elementPos); - const halfWidth = (x2 - x1) / 2; - const halfHeight = (y2 - y1) / 2; - return [pointRelToPos, pointRelToCenterAbs, halfWidth, halfHeight]; -}; - -const relativizationToElementCenter = ( - element: ExcalidrawElement, - elementsMap: ElementsMap, -): GA.Transform => { - const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap); - const center = coordsCenter(x1, y1, x2, y2); - // GA has angle orientation opposite to `rotate` - const rotate = GATransform.rotation(center, element.angle); - const translate = GA.reverse( - GATransform.translation(GADirection.from(center)), - ); - return GATransform.compose(rotate, translate); -}; - -const coordsCenter = ( - x1: number, - y1: number, - x2: number, - y2: number, -): GA.Point => { - return GA.point((x1 + x2) / 2, (y1 + y2) / 2); -}; - // The focus distance is the oriented ratio between the size of // the `element` and the "focus image" of the element on which // all focus points lie, so it's a number between -1 and 1. @@ -1700,39 +1560,146 @@ const determineFocusDistance = ( a: GlobalPoint, // Another point on the line, in absolute coordinates (closer to element) b: GlobalPoint, - elementsMap: ElementsMap, ): number => { - const relateToCenter = relativizationToElementCenter(element, elementsMap); - const aRel = GATransform.apply(relateToCenter, GAPoint.from(a)); - const bRel = GATransform.apply(relateToCenter, GAPoint.from(b)); - const line = GALine.through(aRel, bRel); - const q = element.height / element.width; - const hwidth = element.width / 2; - const hheight = element.height / 2; - const n = line[2]; - const m = line[3]; - const c = line[1]; - const mabs = Math.abs(m); - const nabs = Math.abs(n); - let ret; - switch (element.type) { - case "rectangle": - case "image": - case "text": - case "iframe": - case "embeddable": - case "frame": - case "magicframe": - ret = c / (hwidth * (nabs + q * mabs)); - break; - case "diamond": - ret = mabs < nabs ? c / (nabs * hwidth) : c / (mabs * hheight); - break; - case "ellipse": - ret = c / (hwidth * Math.sqrt(n ** 2 + q ** 2 * m ** 2)); - break; + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + if (pointsEqual(a, b)) { + return 0; } - return ret || 0; + + const rotatedA = pointRotateRads(a, center, -element.angle as Radians); + const rotatedB = pointRotateRads(b, center, -element.angle as Radians); + const sign = + Math.sign( + vectorCross( + vectorFromPoint(rotatedB, a), + vectorFromPoint(rotatedB, center), + ), + ) * -1; + const rotatedInterceptor = lineSegment( + rotatedB, + pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(rotatedB, rotatedA)), + Math.max(element.width * 2, element.height * 2), + ), + rotatedB, + ), + ); + const axes = + element.type === "diamond" + ? [ + lineSegment( + pointFrom(element.x + element.width / 2, element.y), + pointFrom( + element.x + element.width / 2, + element.y + element.height, + ), + ), + lineSegment( + pointFrom(element.x, element.y + element.height / 2), + pointFrom( + element.x + element.width, + element.y + element.height / 2, + ), + ), + ] + : [ + lineSegment( + pointFrom(element.x, element.y), + pointFrom( + element.x + element.width, + element.y + element.height, + ), + ), + lineSegment( + pointFrom(element.x + element.width, element.y), + pointFrom(element.x, element.y + element.height), + ), + ]; + const interceptees = + element.type === "diamond" + ? [ + lineSegment( + pointFrom( + element.x + element.width / 2, + element.y - element.height, + ), + pointFrom( + element.x + element.width / 2, + element.y + element.height * 2, + ), + ), + lineSegment( + pointFrom( + element.x - element.width, + element.y + element.height / 2, + ), + pointFrom( + element.x + element.width * 2, + element.y + element.height / 2, + ), + ), + ] + : [ + lineSegment( + pointFrom( + element.x - element.width, + element.y - element.height, + ), + pointFrom( + element.x + element.width * 2, + element.y + element.height * 2, + ), + ), + lineSegment( + pointFrom( + element.x + element.width * 2, + element.y - element.height, + ), + pointFrom( + element.x - element.width, + element.y + element.height * 2, + ), + ), + ]; + + const ordered = [ + lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[0]), + lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[1]), + ] + .filter((p): p is GlobalPoint => p !== null) + .sort((g, h) => pointDistanceSq(g, b) - pointDistanceSq(h, b)) + .map( + (p, idx): number => + (sign * pointDistance(center, p)) / + (element.type === "diamond" + ? pointDistance(axes[idx][0], axes[idx][1]) / 2 + : Math.sqrt(element.width ** 2 + element.height ** 2) / 2), + ) + .sort((g, h) => Math.abs(g) - Math.abs(h)); + + // debugClear(); + // [ + // lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[0]), + // lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[1]), + // ] + // .filter((p): p is GlobalPoint => p !== null) + // .forEach((p) => debugDrawPoint(p, { color: "black", permanent: true })); + // debugDrawPoint(determineFocusPoint(element, ordered[0] ?? 0, rotatedA), { + // color: "red", + // permanent: true, + // }); + // debugDrawLine(rotatedInterceptor, { color: "green", permanent: true }); + // debugDrawLine(interceptees[0], { color: "red", permanent: true }); + // debugDrawLine(interceptees[1], { color: "red", permanent: true }); + + const signedDistanceRatio = ordered[0] ?? 0; + + return signedDistanceRatio; }; const determineFocusPoint = ( @@ -1740,317 +1707,123 @@ const determineFocusPoint = ( // The oriented, relative distance from the center of `element` of the // returned focusPoint focus: number, - adjecentPoint: GlobalPoint, - elementsMap: ElementsMap, + adjacentPoint: GlobalPoint, ): GlobalPoint => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + if (focus === 0) { - const [x1, y1, x2, y2] = getElementAbsoluteCoords(element, elementsMap); - const center = coordsCenter(x1, y1, x2, y2); - return pointFromPair(GAPoint.toTuple(center)); - } - const relateToCenter = relativizationToElementCenter(element, elementsMap); - const adjecentPointRel = GATransform.apply( - relateToCenter, - GAPoint.from(adjecentPoint), - ); - const reverseRelateToCenter = GA.reverse(relateToCenter); - let point; - switch (element.type) { - case "rectangle": - case "image": - case "text": - case "diamond": - case "iframe": - case "embeddable": - case "frame": - case "magicframe": - point = findFocusPointForRectangulars(element, focus, adjecentPointRel); - break; - case "ellipse": - point = findFocusPointForEllipse(element, focus, adjecentPointRel); - break; - } - return pointFromPair( - GAPoint.toTuple(GATransform.apply(reverseRelateToCenter, point)), - ); -}; - -// Returns 2 or 0 intersection points between line going through `a` and `b` -// and the `element`, in ascending order of distance from `a`. -const intersectElementWithLine = ( - element: ExcalidrawBindableElement, - // Point on the line, in absolute coordinates - a: GlobalPoint, - // Another point on the line, in absolute coordinates - b: GlobalPoint, - // If given, the element is inflated by this value - gap: number = 0, - elementsMap: ElementsMap, -): GlobalPoint[] | undefined => { - if (isRectangularElement(element)) { - return segmentIntersectRectangleElement(element, lineSegment(a, b), gap); + return center; } - const relateToCenter = relativizationToElementCenter(element, elementsMap); - const aRel = GATransform.apply(relateToCenter, GAPoint.from(a)); - const bRel = GATransform.apply(relateToCenter, GAPoint.from(b)); - const line = GALine.through(aRel, bRel); - const reverseRelateToCenter = GA.reverse(relateToCenter); - const intersections = getSortedElementLineIntersections( - element, - line, - aRel, - gap, - ); - return intersections.map( - (point) => - pointFromPair( - GAPoint.toTuple(GATransform.apply(reverseRelateToCenter, point)), + const candidates = ( + element.type === "diamond" + ? [ + pointFrom(element.x, element.y + element.height / 2), + pointFrom(element.x + element.width / 2, element.y), + pointFrom( + element.x + element.width, + element.y + element.height / 2, + ), + pointFrom( + element.x + element.width / 2, + element.y + element.height, + ), + ] + : [ + pointFrom(element.x, element.y), + pointFrom(element.x + element.width, element.y), + pointFrom( + element.x + element.width, + element.y + element.height, + ), + pointFrom(element.x, element.y + element.height), + ] + ) + .map((p) => + pointFromVector( + vectorScale(vectorFromPoint(p, center), Math.abs(focus)), + center, ), - // pointFromArray( - // , - // ), - ); -}; + ) + .map((p) => pointRotateRads(p, center, element.angle as Radians)); -const getSortedElementLineIntersections = ( - element: ExcalidrawBindableElement, - // Relative to element center - line: GA.Line, - // Relative to element center - nearPoint: GA.Point, - gap: number = 0, -): GA.Point[] => { - let intersections: GA.Point[]; - switch (element.type) { - case "rectangle": - case "image": - case "text": - case "diamond": - case "iframe": - case "embeddable": - case "frame": - case "magicframe": - const corners = getCorners(element); - intersections = corners - .flatMap((point, i) => { - const edge: [GA.Point, GA.Point] = [point, corners[(i + 1) % 4]]; - return intersectSegment(line, offsetSegment(edge, gap)); - }) - .concat( - corners.flatMap((point) => getCircleIntersections(point, gap, line)), - ); - break; - case "ellipse": - intersections = getEllipseIntersections(element, gap, line); - break; - } - if (intersections.length < 2) { - // Ignore the "edge" case of only intersecting with a single corner - return []; - } - const sortedIntersections = intersections.sort( - (i1, i2) => - GAPoint.distance(i1, nearPoint) - GAPoint.distance(i2, nearPoint), - ); - return [ - sortedIntersections[0], - sortedIntersections[sortedIntersections.length - 1], + const selected = [ + vectorCross( + vectorFromPoint(adjacentPoint, candidates[0]), + vectorFromPoint(candidates[1], candidates[0]), + ) > 0 && // TOP + (focus > 0 + ? vectorCross( + vectorFromPoint(adjacentPoint, candidates[1]), + vectorFromPoint(candidates[2], candidates[1]), + ) < 0 + : vectorCross( + vectorFromPoint(adjacentPoint, candidates[3]), + vectorFromPoint(candidates[0], candidates[3]), + ) < 0), + vectorCross( + vectorFromPoint(adjacentPoint, candidates[1]), + vectorFromPoint(candidates[2], candidates[1]), + ) > 0 && // RIGHT + (focus > 0 + ? vectorCross( + vectorFromPoint(adjacentPoint, candidates[2]), + vectorFromPoint(candidates[3], candidates[2]), + ) < 0 + : vectorCross( + vectorFromPoint(adjacentPoint, candidates[0]), + vectorFromPoint(candidates[1], candidates[0]), + ) < 0), + vectorCross( + vectorFromPoint(adjacentPoint, candidates[2]), + vectorFromPoint(candidates[3], candidates[2]), + ) > 0 && // BOTTOM + (focus > 0 + ? vectorCross( + vectorFromPoint(adjacentPoint, candidates[3]), + vectorFromPoint(candidates[0], candidates[3]), + ) < 0 + : vectorCross( + vectorFromPoint(adjacentPoint, candidates[1]), + vectorFromPoint(candidates[2], candidates[1]), + ) < 0), + vectorCross( + vectorFromPoint(adjacentPoint, candidates[3]), + vectorFromPoint(candidates[0], candidates[3]), + ) > 0 && // LEFT + (focus > 0 + ? vectorCross( + vectorFromPoint(adjacentPoint, candidates[0]), + vectorFromPoint(candidates[1], candidates[0]), + ) < 0 + : vectorCross( + vectorFromPoint(adjacentPoint, candidates[2]), + vectorFromPoint(candidates[3], candidates[2]), + ) < 0), ]; + + const focusPoint = selected[0] + ? focus > 0 + ? candidates[1] + : candidates[0] + : selected[1] + ? focus > 0 + ? candidates[2] + : candidates[1] + : selected[2] + ? focus > 0 + ? candidates[3] + : candidates[2] + : focus > 0 + ? candidates[0] + : candidates[3]; + + return focusPoint; }; -const getCorners = ( - element: - | ExcalidrawRectangleElement - | ExcalidrawImageElement - | ExcalidrawDiamondElement - | ExcalidrawTextElement - | ExcalidrawIframeLikeElement - | ExcalidrawFrameLikeElement, - scale: number = 1, -): GA.Point[] => { - const hx = (scale * element.width) / 2; - const hy = (scale * element.height) / 2; - switch (element.type) { - case "rectangle": - case "image": - case "text": - case "iframe": - case "embeddable": - case "frame": - case "magicframe": - return [ - GA.point(hx, hy), - GA.point(hx, -hy), - GA.point(-hx, -hy), - GA.point(-hx, hy), - ]; - case "diamond": - return [ - GA.point(0, hy), - GA.point(hx, 0), - GA.point(0, -hy), - GA.point(-hx, 0), - ]; - } -}; - -// Returns intersection of `line` with `segment`, with `segment` moved by -// `gap` in its polar direction. -// If intersection coincides with second segment point returns empty array. -const intersectSegment = ( - line: GA.Line, - segment: [GA.Point, GA.Point], -): GA.Point[] => { - const [a, b] = segment; - const aDist = GAPoint.distanceToLine(a, line); - const bDist = GAPoint.distanceToLine(b, line); - if (aDist * bDist >= 0) { - // The intersection is outside segment `(a, b)` - return []; - } - return [GAPoint.intersect(line, GALine.through(a, b))]; -}; - -const offsetSegment = ( - segment: [GA.Point, GA.Point], - distance: number, -): [GA.Point, GA.Point] => { - const [a, b] = segment; - const offset = GATransform.translationOrthogonal( - GADirection.fromTo(a, b), - distance, - ); - return [GATransform.apply(offset, a), GATransform.apply(offset, b)]; -}; - -const getEllipseIntersections = ( - element: ExcalidrawEllipseElement, - gap: number, - line: GA.Line, -): GA.Point[] => { - const a = element.width / 2 + gap; - const b = element.height / 2 + gap; - const m = line[2]; - const n = line[3]; - const c = line[1]; - const squares = a * a * m * m + b * b * n * n; - const discr = squares - c * c; - if (squares === 0 || discr <= 0) { - return []; - } - const discrRoot = Math.sqrt(discr); - const xn = -a * a * m * c; - const yn = -b * b * n * c; - return [ - GA.point( - (xn + a * b * n * discrRoot) / squares, - (yn - a * b * m * discrRoot) / squares, - ), - GA.point( - (xn - a * b * n * discrRoot) / squares, - (yn + a * b * m * discrRoot) / squares, - ), - ]; -}; - -const getCircleIntersections = ( - center: GA.Point, - radius: number, - line: GA.Line, -): GA.Point[] => { - if (radius === 0) { - return GAPoint.distanceToLine(line, center) === 0 ? [center] : []; - } - const m = line[2]; - const n = line[3]; - const c = line[1]; - const [a, b] = GAPoint.toTuple(center); - const r = radius; - const squares = m * m + n * n; - const discr = r * r * squares - (m * a + n * b + c) ** 2; - if (squares === 0 || discr <= 0) { - return []; - } - const discrRoot = Math.sqrt(discr); - const xn = a * n * n - b * m * n - m * c; - const yn = b * m * m - a * m * n - n * c; - - return [ - GA.point((xn + n * discrRoot) / squares, (yn - m * discrRoot) / squares), - GA.point((xn - n * discrRoot) / squares, (yn + m * discrRoot) / squares), - ]; -}; - -// The focus point is the tangent point of the "focus image" of the -// `element`, where the tangent goes through `point`. -const findFocusPointForEllipse = ( - ellipse: ExcalidrawEllipseElement, - // Between -1 and 1 (not 0) the relative size of the "focus image" of - // the element on which the focus point lies - relativeDistance: number, - // The point for which we're trying to find the focus point, relative - // to the ellipse center. - point: GA.Point, -): GA.Point => { - const relativeDistanceAbs = Math.abs(relativeDistance); - const a = (ellipse.width * relativeDistanceAbs) / 2; - const b = (ellipse.height * relativeDistanceAbs) / 2; - - const orientation = Math.sign(relativeDistance); - const [px, pyo] = GAPoint.toTuple(point); - - // The calculation below can't handle py = 0 - const py = pyo === 0 ? 0.0001 : pyo; - - const squares = px ** 2 * b ** 2 + py ** 2 * a ** 2; - // Tangent mx + ny + 1 = 0 - const m = - (-px * b ** 2 + - orientation * py * Math.sqrt(Math.max(0, squares - a ** 2 * b ** 2))) / - squares; - - let n = (-m * px - 1) / py; - - if (n === 0) { - // if zero {-0, 0}, fall back to a same-sign value in the similar range - n = (Object.is(n, -0) ? -1 : 1) * 0.01; - } - - const x = -(a ** 2 * m) / (n ** 2 * b ** 2 + m ** 2 * a ** 2); - return GA.point(x, (-m * x - 1) / n); -}; - -const findFocusPointForRectangulars = ( - element: - | ExcalidrawRectangleElement - | ExcalidrawImageElement - | ExcalidrawDiamondElement - | ExcalidrawTextElement - | ExcalidrawIframeLikeElement - | ExcalidrawFrameLikeElement, - // Between -1 and 1 for how far away should the focus point be relative - // to the size of the element. Sign determines orientation. - relativeDistance: number, - // The point for which we're trying to find the focus point, relative - // to the element center. - point: GA.Point, -): GA.Point => { - const relativeDistanceAbs = Math.abs(relativeDistance); - const orientation = Math.sign(relativeDistance); - const corners = getCorners(element, relativeDistanceAbs); - - let maxDistance = 0; - let tangentPoint: null | GA.Point = null; - corners.forEach((corner) => { - const distance = orientation * GALine.through(point, corner)[1]; - if (distance > maxDistance) { - maxDistance = distance; - tangentPoint = corner; - } - }); - return tangentPoint!; -}; export const bindingProperties: Set = new Set([ "boundElements", "frameId", diff --git a/packages/excalidraw/element/collision.ts b/packages/excalidraw/element/collision.ts index a1593d2f6..bbd89cfa5 100644 --- a/packages/excalidraw/element/collision.ts +++ b/packages/excalidraw/element/collision.ts @@ -1,7 +1,10 @@ import type { ElementsMap, + ExcalidrawDiamondElement, ExcalidrawElement, + ExcalidrawEllipseElement, ExcalidrawRectangleElement, + ExcalidrawRectanguloidElement, } from "./types"; import { getElementBounds } from "./bounds"; import type { FrameNameBounds } from "../types"; @@ -16,8 +19,28 @@ import { isTextElement, } from "./typeChecks"; import { getBoundTextShape, isPathALoop } from "../shapes"; -import type { GlobalPoint, LocalPoint, Polygon } from "../../math"; -import { isPointWithinBounds, pointFrom } from "../../math"; +import type { + GlobalPoint, + LineSegment, + LocalPoint, + Polygon, + Radians, +} from "../../math"; +import { + curveIntersectLineSegment, + isPointWithinBounds, + line, + lineSegment, + lineSegmentIntersectionPoints, + pointFrom, + pointRotateRads, + pointsEqual, +} from "../../math"; +import { ellipse, ellipseLineIntersectionPoints } from "../../math/ellipse"; +import { + deconstructDiamondElement, + deconstructRectanguloidElement, +} from "./utils"; export const shouldTestInside = (element: ExcalidrawElement) => { if (element.type === "arrow") { @@ -121,3 +144,166 @@ export const hitElementBoundText = ( ): boolean => { return !!textShape && isPointInShape(pointFrom(x, y), textShape); }; + +/** + * Intersect a line with an element for binding test + * + * @param element + * @param line + * @param offset + * @returns + */ +export const intersectElementWithLineSegment = ( + element: ExcalidrawElement, + line: LineSegment, + offset: number = 0, +): GlobalPoint[] => { + switch (element.type) { + case "rectangle": + case "image": + case "text": + case "iframe": + case "embeddable": + case "frame": + case "magicframe": + return intersectRectanguloidWithLineSegment(element, line, offset); + case "diamond": + return intersectDiamondWithLineSegment(element, line, offset); + case "ellipse": + return intersectEllipseWithLineSegment(element, line, offset); + default: + throw new Error(`Unimplemented element type '${element.type}'`); + } +}; + +const intersectRectanguloidWithLineSegment = ( + element: ExcalidrawRectanguloidElement, + l: LineSegment, + offset: number = 0, +): GlobalPoint[] => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + // To emulate a rotated rectangle we rotate the point in the inverse angle + // instead. It's all the same distance-wise. + const rotatedA = pointRotateRads( + l[0], + center, + -element.angle as Radians, + ); + const rotatedB = pointRotateRads( + l[1], + center, + -element.angle as Radians, + ); + + // Get the element's building components we can test against + const [sides, corners] = deconstructRectanguloidElement(element, offset); + + return ( + [ + // Test intersection against the sides, keep only the valid + // intersection points and rotate them back to scene space + ...sides + .map((s) => + lineSegmentIntersectionPoints( + lineSegment(rotatedA, rotatedB), + s, + ), + ) + .filter((x) => x != null) + .map((j) => pointRotateRads(j!, center, element.angle)), + // Test intersection against the corners which are cubic bezier curves, + // keep only the valid intersection points and rotate them back to scene + // space + ...corners + .flatMap((t) => + curveIntersectLineSegment(t, lineSegment(rotatedA, rotatedB)), + ) + .filter((i) => i != null) + .map((j) => pointRotateRads(j, center, element.angle)), + ] + // Remove duplicates + .filter( + (p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx, + ) + ); +}; + +/** + * + * @param element + * @param a + * @param b + * @returns + */ +const intersectDiamondWithLineSegment = ( + element: ExcalidrawDiamondElement, + l: LineSegment, + offset: number = 0, +): GlobalPoint[] => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + // Rotate the point to the inverse direction to simulate the rotated diamond + // points. It's all the same distance-wise. + const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians); + const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians); + + const [sides, curves] = deconstructDiamondElement(element, offset); + + return ( + [ + ...sides + .map((s) => + lineSegmentIntersectionPoints( + lineSegment(rotatedA, rotatedB), + s, + ), + ) + .filter((p): p is GlobalPoint => p != null) + // Rotate back intersection points + .map((p) => pointRotateRads(p!, center, element.angle)), + ...curves + .flatMap((p) => + curveIntersectLineSegment(p, lineSegment(rotatedA, rotatedB)), + ) + .filter((p) => p != null) + // Rotate back intersection points + .map((p) => pointRotateRads(p, center, element.angle)), + ] + // Remove duplicates + .filter( + (p, idx, points) => points.findIndex((d) => pointsEqual(p, d)) === idx, + ) + ); +}; + +/** + * + * @param element + * @param a + * @param b + * @returns + */ +const intersectEllipseWithLineSegment = ( + element: ExcalidrawEllipseElement, + l: LineSegment, + offset: number = 0, +): GlobalPoint[] => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + const rotatedA = pointRotateRads(l[0], center, -element.angle as Radians); + const rotatedB = pointRotateRads(l[1], center, -element.angle as Radians); + + return ellipseLineIntersectionPoints( + ellipse(center, element.width / 2 + offset, element.height / 2 + offset), + line(rotatedA, rotatedB), + ).map((p) => pointRotateRads(p, center, element.angle)); +}; diff --git a/packages/excalidraw/element/distance.ts b/packages/excalidraw/element/distance.ts new file mode 100644 index 000000000..d23bf7ee8 --- /dev/null +++ b/packages/excalidraw/element/distance.ts @@ -0,0 +1,123 @@ +import type { GlobalPoint, Radians } from "../../math"; +import { + curvePointDistance, + distanceToLineSegment, + pointFrom, + pointRotateRads, +} from "../../math"; +import { ellipse, ellipseDistanceFromPoint } from "../../math/ellipse"; +import type { + ExcalidrawBindableElement, + ExcalidrawDiamondElement, + ExcalidrawEllipseElement, + ExcalidrawRectanguloidElement, +} from "./types"; +import { + deconstructDiamondElement, + deconstructRectanguloidElement, +} from "./utils"; + +export const distanceToBindableElement = ( + element: ExcalidrawBindableElement, + p: GlobalPoint, +): number => { + switch (element.type) { + case "rectangle": + case "image": + case "text": + case "iframe": + case "embeddable": + case "frame": + case "magicframe": + return distanceToRectanguloidElement(element, p); + case "diamond": + return distanceToDiamondElement(element, p); + case "ellipse": + return distanceToEllipseElement(element, p); + } +}; + +/** + * Returns the distance of a point and the provided rectangular-shaped element, + * accounting for roundness and rotation + * + * @param element The rectanguloid element + * @param p The point to consider + * @returns The eucledian distance to the outline of the rectanguloid element + */ +const distanceToRectanguloidElement = ( + element: ExcalidrawRectanguloidElement, + p: GlobalPoint, +) => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + // To emulate a rotated rectangle we rotate the point in the inverse angle + // instead. It's all the same distance-wise. + const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians); + + // Get the element's building components we can test against + const [sides, corners] = deconstructRectanguloidElement(element); + + return Math.min( + ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)), + ...corners + .map((a) => curvePointDistance(a, rotatedPoint)) + .filter((d): d is number => d !== null), + ); +}; + +/** + * Returns the distance of a point and the provided diamond element, accounting + * for roundness and rotation + * + * @param element The diamond element + * @param p The point to consider + * @returns The eucledian distance to the outline of the diamond + */ +const distanceToDiamondElement = ( + element: ExcalidrawDiamondElement, + p: GlobalPoint, +): number => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + // Rotate the point to the inverse direction to simulate the rotated diamond + // points. It's all the same distance-wise. + const rotatedPoint = pointRotateRads(p, center, -element.angle as Radians); + + const [sides, curves] = deconstructDiamondElement(element); + + return Math.min( + ...sides.map((s) => distanceToLineSegment(rotatedPoint, s)), + ...curves + .map((a) => curvePointDistance(a, rotatedPoint)) + .filter((d): d is number => d !== null), + ); +}; + +/** + * Returns the distance of a point and the provided ellipse element, accounting + * for roundness and rotation + * + * @param element The ellipse element + * @param p The point to consider + * @returns The eucledian distance to the outline of the ellipse + */ +const distanceToEllipseElement = ( + element: ExcalidrawEllipseElement, + p: GlobalPoint, +): number => { + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + return ellipseDistanceFromPoint( + // Instead of rotating the ellipse, rotate the point to the inverse angle + pointRotateRads(p, center, -element.angle as Radians), + ellipse(center, element.width / 2, element.height / 2), + ); +}; diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index fd5682d28..2dd82e7c9 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -18,6 +18,7 @@ import type { import { ARROW_TYPE } from "../constants"; import type { LocalPoint } from "../../math"; import { pointFrom } from "../../math"; +import "../../utils/test-utils"; const { h } = window; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index d3154cae9..b990fb93b 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -19,8 +19,6 @@ import { invariant, isAnyTrue, toBrandedType, tupleToCoors } from "../utils"; import type { AppState } from "../types"; import { bindPointToSnapToElementOutline, - distanceToBindableElement, - avoidRectangularCorner, FIXED_BINDING_DISTANCE, getHeadingForElbowArrowSnap, getGlobalFixedPointForBindableElement, @@ -42,7 +40,7 @@ import { headingForPoint, } from "./heading"; import { type ElementUpdate } from "./mutateElement"; -import { isBindableElement, isRectanguloidElement } from "./typeChecks"; +import { isBindableElement } from "./typeChecks"; import { type ExcalidrawElbowArrowElement, type NonDeletedSceneElementsMap, @@ -55,6 +53,7 @@ import type { FixedPointBinding, FixedSegment, } from "./types"; +import { distanceToBindableElement } from "./distance"; type GridAddress = [number, number] & { _brand: "gridaddress" }; @@ -1177,19 +1176,27 @@ const getElbowArrowData = ( ) : [startElement, endElement]; const startGlobalPoint = getGlobalPoint( + { + ...arrow, + elbowed: true, + points: nextPoints, + } as ExcalidrawElbowArrowElement, + "start", arrow.startBinding?.fixedPoint, origStartGlobalPoint, - origEndGlobalPoint, - elementsMap, startElement, hoveredStartElement, options?.isDragging, ); const endGlobalPoint = getGlobalPoint( + { + ...arrow, + elbowed: true, + points: nextPoints, + } as ExcalidrawElbowArrowElement, + "end", arrow.endBinding?.fixedPoint, origEndGlobalPoint, - origStartGlobalPoint, - elementsMap, endElement, hoveredEndElement, options?.isDragging, @@ -2133,21 +2140,20 @@ const neighborIndexToHeading = (idx: number): Heading => { }; const getGlobalPoint = ( + arrow: ExcalidrawElbowArrowElement, + startOrEnd: "start" | "end", fixedPointRatio: [number, number] | undefined | null, initialPoint: GlobalPoint, - otherPoint: GlobalPoint, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, boundElement?: ExcalidrawBindableElement | null, hoveredElement?: ExcalidrawBindableElement | null, isDragging?: boolean, ): GlobalPoint => { if (isDragging) { if (hoveredElement) { - const snapPoint = getSnapPoint( - initialPoint, - otherPoint, + const snapPoint = bindPointToSnapToElementOutline( + arrow, hoveredElement, - elementsMap, + startOrEnd, ); return snapToMid(hoveredElement, snapPoint); @@ -2164,29 +2170,16 @@ const getGlobalPoint = ( // NOTE: Resize scales the binding position point too, so we need to update it return Math.abs( - distanceToBindableElement(boundElement, fixedGlobalPoint, elementsMap) - + distanceToBindableElement(boundElement, fixedGlobalPoint) - FIXED_BINDING_DISTANCE, ) > 0.01 - ? getSnapPoint(initialPoint, otherPoint, boundElement, elementsMap) + ? bindPointToSnapToElementOutline(arrow, boundElement, startOrEnd) : fixedGlobalPoint; } return initialPoint; }; -const getSnapPoint = ( - p: GlobalPoint, - otherPoint: GlobalPoint, - element: ExcalidrawBindableElement, - elementsMap: ElementsMap, -) => - bindPointToSnapToElementOutline( - isRectanguloidElement(element) ? avoidRectangularCorner(element, p) : p, - otherPoint, - element, - elementsMap, - ); - const getBindPointHeading = ( p: GlobalPoint, otherPoint: GlobalPoint, @@ -2201,9 +2194,12 @@ const getBindPointHeading = ( hoveredElement && aabbForElement( hoveredElement, - Array(4).fill( - distanceToBindableElement(hoveredElement, p, elementsMap), - ) as [number, number, number, number], + Array(4).fill(distanceToBindableElement(hoveredElement, p)) as [ + number, + number, + number, + number, + ], ), elementsMap, origPoint, diff --git a/packages/excalidraw/element/utils.ts b/packages/excalidraw/element/utils.ts new file mode 100644 index 000000000..68717ac8c --- /dev/null +++ b/packages/excalidraw/element/utils.ts @@ -0,0 +1,355 @@ +import { getDiamondPoints } from "."; +import type { Curve, LineSegment } from "../../math"; +import { + curve, + lineSegment, + pointFrom, + pointFromVector, + rectangle, + vectorFromPoint, + vectorNormalize, + vectorScale, + type GlobalPoint, +} from "../../math"; +import { getCornerRadius } from "../shapes"; +import type { + ExcalidrawDiamondElement, + ExcalidrawRectanguloidElement, +} from "./types"; + +/** + * Get the building components of a rectanguloid element in the form of + * line segments and curves. + * + * @param element Target rectanguloid element + * @param offset Optional offset to expand the rectanguloid shape + * @returns Tuple of line segments (0) and curves (1) + */ +export function deconstructRectanguloidElement( + element: ExcalidrawRectanguloidElement, + offset: number = 0, +): [LineSegment[], Curve[]] { + const roundness = getCornerRadius( + Math.min(element.width, element.height), + element, + ); + + if (roundness <= 0) { + const r = rectangle( + pointFrom(element.x - offset, element.y - offset), + pointFrom( + element.x + element.width + offset, + element.y + element.height + offset, + ), + ); + + const top = lineSegment( + pointFrom(r[0][0] + roundness, r[0][1]), + pointFrom(r[1][0] - roundness, r[0][1]), + ); + const right = lineSegment( + pointFrom(r[1][0], r[0][1] + roundness), + pointFrom(r[1][0], r[1][1] - roundness), + ); + const bottom = lineSegment( + pointFrom(r[0][0] + roundness, r[1][1]), + pointFrom(r[1][0] - roundness, r[1][1]), + ); + const left = lineSegment( + pointFrom(r[0][0], r[1][1] - roundness), + pointFrom(r[0][0], r[0][1] + roundness), + ); + const sides = [top, right, bottom, left]; + + return [sides, []]; + } + + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + const r = rectangle( + pointFrom(element.x, element.y), + pointFrom(element.x + element.width, element.y + element.height), + ); + + const top = lineSegment( + pointFrom(r[0][0] + roundness, r[0][1]), + pointFrom(r[1][0] - roundness, r[0][1]), + ); + const right = lineSegment( + pointFrom(r[1][0], r[0][1] + roundness), + pointFrom(r[1][0], r[1][1] - roundness), + ); + const bottom = lineSegment( + pointFrom(r[0][0] + roundness, r[1][1]), + pointFrom(r[1][0] - roundness, r[1][1]), + ); + const left = lineSegment( + pointFrom(r[0][0], r[1][1] - roundness), + pointFrom(r[0][0], r[0][1] + roundness), + ); + + const offsets = [ + vectorScale( + vectorNormalize( + vectorFromPoint(pointFrom(r[0][0] - offset, r[0][1] - offset), center), + ), + offset, + ), // TOP LEFT + vectorScale( + vectorNormalize( + vectorFromPoint(pointFrom(r[1][0] + offset, r[0][1] - offset), center), + ), + offset, + ), //TOP RIGHT + vectorScale( + vectorNormalize( + vectorFromPoint(pointFrom(r[1][0] + offset, r[1][1] + offset), center), + ), + offset, + ), // BOTTOM RIGHT + vectorScale( + vectorNormalize( + vectorFromPoint(pointFrom(r[0][0] - offset, r[1][1] + offset), center), + ), + offset, + ), // BOTTOM LEFT + ]; + + const corners = [ + curve( + pointFromVector(offsets[0], left[1]), + pointFromVector( + offsets[0], + pointFrom( + left[1][0] + (2 / 3) * (r[0][0] - left[1][0]), + left[1][1] + (2 / 3) * (r[0][1] - left[1][1]), + ), + ), + pointFromVector( + offsets[0], + pointFrom( + top[0][0] + (2 / 3) * (r[0][0] - top[0][0]), + top[0][1] + (2 / 3) * (r[0][1] - top[0][1]), + ), + ), + pointFromVector(offsets[0], top[0]), + ), // TOP LEFT + curve( + pointFromVector(offsets[1], top[1]), + pointFromVector( + offsets[1], + pointFrom( + top[1][0] + (2 / 3) * (r[1][0] - top[1][0]), + top[1][1] + (2 / 3) * (r[0][1] - top[1][1]), + ), + ), + pointFromVector( + offsets[1], + pointFrom( + right[0][0] + (2 / 3) * (r[1][0] - right[0][0]), + right[0][1] + (2 / 3) * (r[0][1] - right[0][1]), + ), + ), + pointFromVector(offsets[1], right[0]), + ), // TOP RIGHT + curve( + pointFromVector(offsets[2], right[1]), + pointFromVector( + offsets[2], + pointFrom( + right[1][0] + (2 / 3) * (r[1][0] - right[1][0]), + right[1][1] + (2 / 3) * (r[1][1] - right[1][1]), + ), + ), + pointFromVector( + offsets[2], + pointFrom( + bottom[1][0] + (2 / 3) * (r[1][0] - bottom[1][0]), + bottom[1][1] + (2 / 3) * (r[1][1] - bottom[1][1]), + ), + ), + pointFromVector(offsets[2], bottom[1]), + ), // BOTTOM RIGHT + curve( + pointFromVector(offsets[3], bottom[0]), + pointFromVector( + offsets[3], + pointFrom( + bottom[0][0] + (2 / 3) * (r[0][0] - bottom[0][0]), + bottom[0][1] + (2 / 3) * (r[1][1] - bottom[0][1]), + ), + ), + pointFromVector( + offsets[3], + pointFrom( + left[0][0] + (2 / 3) * (r[0][0] - left[0][0]), + left[0][1] + (2 / 3) * (r[1][1] - left[0][1]), + ), + ), + pointFromVector(offsets[3], left[0]), + ), // BOTTOM LEFT + ]; + + const sides = [ + lineSegment(corners[0][3], corners[1][0]), + lineSegment(corners[1][3], corners[2][0]), + lineSegment(corners[2][3], corners[3][0]), + lineSegment(corners[3][3], corners[0][0]), + ]; + + return [sides, corners]; +} + +/** + * Get the building components of a diamond element in the form of + * line segments and curves as a tuple, in this order. + * + * @param element The element to deconstruct + * @param offset An optional offset + * @returns Tuple of line segments (0) and curves (1) + */ +export function deconstructDiamondElement( + element: ExcalidrawDiamondElement, + offset: number = 0, +): [LineSegment[], Curve[]] { + const [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY] = + getDiamondPoints(element); + const verticalRadius = getCornerRadius(Math.abs(topX - leftX), element); + const horizontalRadius = getCornerRadius(Math.abs(rightY - topY), element); + + if (element.roundness?.type == null) { + const [top, right, bottom, left]: GlobalPoint[] = [ + pointFrom(element.x + topX, element.y + topY - offset), + pointFrom(element.x + rightX + offset, element.y + rightY), + pointFrom(element.x + bottomX, element.y + bottomY + offset), + pointFrom(element.x + leftX - offset, element.y + leftY), + ]; + + // Create the line segment parts of the diamond + // NOTE: Horizontal and vertical seems to be flipped here + const topRight = lineSegment( + pointFrom(top[0] + verticalRadius, top[1] + horizontalRadius), + pointFrom(right[0] - verticalRadius, right[1] - horizontalRadius), + ); + const bottomRight = lineSegment( + pointFrom(right[0] - verticalRadius, right[1] + horizontalRadius), + pointFrom(bottom[0] + verticalRadius, bottom[1] - horizontalRadius), + ); + const bottomLeft = lineSegment( + pointFrom(bottom[0] - verticalRadius, bottom[1] - horizontalRadius), + pointFrom(left[0] + verticalRadius, left[1] + horizontalRadius), + ); + const topLeft = lineSegment( + pointFrom(left[0] + verticalRadius, left[1] - horizontalRadius), + pointFrom(top[0] - verticalRadius, top[1] + horizontalRadius), + ); + + return [[topRight, bottomRight, bottomLeft, topLeft], []]; + } + + const center = pointFrom( + element.x + element.width / 2, + element.y + element.height / 2, + ); + + const [top, right, bottom, left]: GlobalPoint[] = [ + pointFrom(element.x + topX, element.y + topY), + pointFrom(element.x + rightX, element.y + rightY), + pointFrom(element.x + bottomX, element.y + bottomY), + pointFrom(element.x + leftX, element.y + leftY), + ]; + + const offsets = [ + vectorScale(vectorNormalize(vectorFromPoint(right, center)), offset), // RIGHT + vectorScale(vectorNormalize(vectorFromPoint(bottom, center)), offset), // BOTTOM + vectorScale(vectorNormalize(vectorFromPoint(left, center)), offset), // LEFT + vectorScale(vectorNormalize(vectorFromPoint(top, center)), offset), // TOP + ]; + + const corners = [ + curve( + pointFromVector( + offsets[0], + pointFrom( + right[0] - verticalRadius, + right[1] - horizontalRadius, + ), + ), + pointFromVector(offsets[0], right), + pointFromVector(offsets[0], right), + pointFromVector( + offsets[0], + pointFrom( + right[0] - verticalRadius, + right[1] + horizontalRadius, + ), + ), + ), // RIGHT + curve( + pointFromVector( + offsets[1], + pointFrom( + bottom[0] + verticalRadius, + bottom[1] - horizontalRadius, + ), + ), + pointFromVector(offsets[1], bottom), + pointFromVector(offsets[1], bottom), + pointFromVector( + offsets[1], + pointFrom( + bottom[0] - verticalRadius, + bottom[1] - horizontalRadius, + ), + ), + ), // BOTTOM + curve( + pointFromVector( + offsets[2], + pointFrom( + left[0] + verticalRadius, + left[1] + horizontalRadius, + ), + ), + pointFromVector(offsets[2], left), + pointFromVector(offsets[2], left), + pointFromVector( + offsets[2], + pointFrom( + left[0] + verticalRadius, + left[1] - horizontalRadius, + ), + ), + ), // LEFT + curve( + pointFromVector( + offsets[3], + pointFrom( + top[0] - verticalRadius, + top[1] + horizontalRadius, + ), + ), + pointFromVector(offsets[3], top), + pointFromVector(offsets[3], top), + pointFromVector( + offsets[3], + pointFrom( + top[0] + verticalRadius, + top[1] + horizontalRadius, + ), + ), + ), // TOP + ]; + + const sides = [ + lineSegment(corners[0][3], corners[1][0]), + lineSegment(corners[1][3], corners[2][0]), + lineSegment(corners[2][3], corners[3][0]), + lineSegment(corners[3][3], corners[0][0]), + ]; + + return [sides, corners]; +} diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 9e353c06f..d8cf4ec2d 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -197,7 +197,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": 99, + "height": "102.35417", "id": "id172", "index": "a2", "isDeleted": false, @@ -211,8 +211,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "98.20800", - 99, + "101.77517", + "102.35417", ], ], "roughness": 1, @@ -227,8 +227,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 40, - "width": "98.20800", - "x": 1, + "width": "101.77517", + "x": "0.70711", "y": 0, } `; @@ -294,24 +294,22 @@ History { "deleted": { "endBinding": { "elementId": "id171", - "fixedPoint": null, "focus": "0.00990", "gap": 1, }, - "height": "0.98017", + "height": "0.98597", "points": [ [ 0, 0, ], [ - 98, - "-0.98017", + "98.58579", + "-0.98597", ], ], "startBinding": { "elementId": "id170", - "fixedPoint": null, "focus": "0.02970", "gap": 1, }, @@ -319,24 +317,22 @@ History { "inserted": { "endBinding": { "elementId": "id171", - "fixedPoint": null, "focus": "-0.02000", "gap": 1, }, - "height": "0.00169", + "height": "0.00119", "points": [ [ 0, 0, ], [ - 98, - "0.00169", + "98.58579", + "0.00119", ], ], "startBinding": { "elementId": "id170", - "fixedPoint": null, "focus": "0.02000", "gap": 1, }, @@ -393,15 +389,15 @@ History { "focus": 0, "gap": 1, }, - "height": 99, + "height": "102.35417", "points": [ [ 0, 0, ], [ - "98.20800", - 99, + "101.77517", + "102.35417", ], ], "startBinding": null, @@ -410,28 +406,26 @@ History { "inserted": { "endBinding": { "elementId": "id171", - "fixedPoint": null, "focus": "0.00990", "gap": 1, }, - "height": "0.98161", + "height": "0.98700", "points": [ [ 0, 0, ], [ - 98, - "-0.98161", + "98.58579", + "-0.98700", ], ], "startBinding": { "elementId": "id170", - "fixedPoint": null, "focus": "0.02970", "gap": 1, }, - "y": "0.99245", + "y": "0.99465", }, }, "id175" => Delta { @@ -824,7 +818,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 30, - "width": 0, + "width": 50, "x": 200, "y": 0, } @@ -858,7 +852,7 @@ History { 0, ], [ - 0, + 50, 0, ], ], @@ -934,8 +928,7 @@ History { "inserted": { "endBinding": { "elementId": "id166", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "points": [ @@ -944,13 +937,12 @@ History { 0, ], [ - 0, + 50, 0, ], ], "startBinding": { "elementId": "id165", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -1246,7 +1238,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "2.61991", + "height": "2.52823", "id": "id178", "index": "Zz", "isDeleted": false, @@ -1260,8 +1252,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "98.00000", - "-2.61991", + "98.58579", + "-2.52823", ], ], "roughness": 1, @@ -1284,9 +1276,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 11, - "width": "98.00000", - "x": "1.00000", - "y": "3.98333", + "width": "98.58579", + "x": "0.70711", + "y": "3.82861", } `; @@ -1617,7 +1609,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "2.61991", + "height": "2.52823", "id": "id181", "index": "a0", "isDeleted": false, @@ -1631,8 +1623,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "98.00000", - "-2.61991", + "98.58579", + "-2.52823", ], ], "roughness": 1, @@ -1655,9 +1647,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 11, - "width": "98.00000", - "x": "1.00000", - "y": "3.98333", + "width": "98.58579", + "x": "0.70711", + "y": "3.82861", } `; @@ -1775,7 +1767,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "22.36242", + "height": "22.07000", "index": "a0", "isDeleted": false, "lastCommittedPoint": null, @@ -1788,8 +1780,8 @@ History { 0, ], [ - "98.00000", - "-22.36242", + "99.27949", + "-22.07000", ], ], "roughness": 1, @@ -1810,9 +1802,9 @@ History { "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "width": "98.00000", - "x": 1, - "y": 34, + "width": "99.27949", + "x": "0.01341", + "y": "33.34227", }, "inserted": { "isDeleted": true, @@ -2322,14 +2314,13 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "endArrowhead": "arrow", "endBinding": { "elementId": "id185", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "408.19672", + "height": "410.63965", "id": "id186", "index": "a2", "isDeleted": false, @@ -2343,8 +2334,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - 498, - "-408.19672", + "501.24760", + "-410.63965", ], ], "roughness": 1, @@ -2354,7 +2345,6 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "startArrowhead": null, "startBinding": { "elementId": "id184", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -2364,8 +2354,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 10, - "width": 498, - "x": 1, + "width": "501.24760", + "x": "0.70711", "y": 0, } `; @@ -2484,8 +2474,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id185", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -2515,7 +2504,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id184", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -15122,8 +15110,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endArrowhead": "arrow", "endBinding": { "elementId": "id58", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -15143,7 +15130,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "98.00000", + "98.58579", 0, ], ], @@ -15154,7 +15141,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "startArrowhead": null, "startBinding": { "elementId": "id56", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -15164,8 +15150,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", "updated": 1, "version": 10, - "width": "98.00000", - "x": 1, + "width": "98.58579", + "x": "0.70711", "y": 0, } `; @@ -15493,8 +15479,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id58", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -15524,7 +15509,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id56", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -15821,8 +15805,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endArrowhead": "arrow", "endBinding": { "elementId": "id52", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -15842,7 +15825,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "98.00000", + "98.58579", 0, ], ], @@ -15853,7 +15836,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "startArrowhead": null, "startBinding": { "elementId": "id50", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -15863,8 +15845,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", "updated": 1, "version": 10, - "width": "98.00000", - "x": 1, + "width": "98.58579", + "x": "0.70711", "y": 0, } `; @@ -16116,8 +16098,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id52", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -16147,7 +16128,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id50", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -16444,8 +16424,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endArrowhead": "arrow", "endBinding": { "elementId": "id64", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -16465,7 +16444,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "98.00000", + "98.58579", 0, ], ], @@ -16476,7 +16455,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "startArrowhead": null, "startBinding": { "elementId": "id62", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -16486,8 +16464,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", "updated": 1, "version": 10, - "width": "98.00000", - "x": 1, + "width": "98.58579", + "x": "0.70711", "y": 0, } `; @@ -16739,8 +16717,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id64", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -16770,7 +16747,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id62", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -17065,8 +17041,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endArrowhead": "arrow", "endBinding": { "elementId": "id70", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -17086,7 +17061,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "98.00000", + "98.58579", 0, ], ], @@ -17097,7 +17072,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "startArrowhead": null, "startBinding": { "elementId": "id68", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -17107,8 +17081,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", "updated": 1, "version": 10, - "width": "98.00000", - "x": 1, + "width": "98.58579", + "x": "0.70711", "y": 0, } `; @@ -17170,7 +17144,6 @@ History { ], "startBinding": { "elementId": "id68", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -17431,8 +17404,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id70", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -17462,7 +17434,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id68", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -17783,8 +17754,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "endArrowhead": "arrow", "endBinding": { "elementId": "id77", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -17804,7 +17774,7 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding 0, ], [ - "98.00000", + "98.58579", 0, ], ], @@ -17815,7 +17785,6 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "startArrowhead": null, "startBinding": { "elementId": "id75", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -17825,8 +17794,8 @@ exports[`history > singleplayer undo/redo > should support bidirectional binding "type": "arrow", "updated": 1, "version": 11, - "width": "98.00000", - "x": 1, + "width": "98.58579", + "x": "0.70711", "y": 0, } `; @@ -17887,8 +17856,7 @@ History { "deleted": { "endBinding": { "elementId": "id77", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "points": [ @@ -17903,7 +17871,6 @@ History { ], "startBinding": { "elementId": "id75", - "fixedPoint": null, "focus": 0, "gap": 1, }, @@ -18165,8 +18132,7 @@ History { "endArrowhead": "arrow", "endBinding": { "elementId": "id77", - "fixedPoint": null, - "focus": 0, + "focus": -0, "gap": 1, }, "fillStyle": "solid", @@ -18196,7 +18162,6 @@ History { "startArrowhead": null, "startBinding": { "elementId": "id75", - "fixedPoint": null, "focus": 0, "gap": 1, }, diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 2e34ec6b2..eb5f14498 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -190,14 +190,13 @@ exports[`move element > rectangles with binding arrow 7`] = ` "endArrowhead": "arrow", "endBinding": { "elementId": "id1", - "fixedPoint": null, "focus": "-0.46667", "gap": 10, }, "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "81.47368", + "height": "84.41974", "id": "id2", "index": "a2", "isDeleted": false, @@ -211,8 +210,8 @@ exports[`move element > rectangles with binding arrow 7`] = ` 0, ], [ - 81, - "81.47368", + "83.92893", + "84.41974", ], ], "roughness": 1, @@ -223,7 +222,6 @@ exports[`move element > rectangles with binding arrow 7`] = ` "startArrowhead": null, "startBinding": { "elementId": "id0", - "fixedPoint": null, "focus": "-0.60000", "gap": 10, }, @@ -234,7 +232,7 @@ exports[`move element > rectangles with binding arrow 7`] = ` "updated": 1, "version": 11, "versionNonce": 1051383431, - "width": 81, + "width": "83.92893", "x": 110, "y": 50, } diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx index 680cbfa85..dff4d3347 100644 --- a/packages/excalidraw/tests/binding.test.tsx +++ b/packages/excalidraw/tests/binding.test.tsx @@ -64,7 +64,6 @@ describe("element binding", () => { expect(arrow.startBinding).toEqual({ elementId: rect.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -77,13 +76,11 @@ describe("element binding", () => { // Both the start and the end points should be bound expect(arrow.startBinding).toEqual({ elementId: rect.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); diff --git a/packages/excalidraw/tests/history.test.tsx b/packages/excalidraw/tests/history.test.tsx index 5000940ca..4942fb2b3 100644 --- a/packages/excalidraw/tests/history.test.tsx +++ b/packages/excalidraw/tests/history.test.tsx @@ -9,6 +9,7 @@ import { togglePopover, getCloneByOrigId, } from "./test-utils"; +import "../../utils/test-utils"; import { Excalidraw } from "../index"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { API } from "./helpers/api"; @@ -1321,13 +1322,11 @@ describe("history", () => { expect(API.getUndoStack().length).toBe(5); expect(arrow.startBinding).toEqual({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -1346,13 +1345,11 @@ describe("history", () => { expect(API.getRedoStack().length).toBe(1); expect(arrow.startBinding).toEqual({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -1371,13 +1368,11 @@ describe("history", () => { expect(API.getRedoStack().length).toBe(0); expect(arrow.startBinding).toEqual({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -1404,13 +1399,11 @@ describe("history", () => { expect(API.getRedoStack().length).toBe(0); expect(arrow.startBinding).toEqual({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -1429,13 +1422,11 @@ describe("history", () => { expect(API.getRedoStack().length).toBe(1); expect(arrow.startBinding).toEqual({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); expect(arrow.endBinding).toEqual({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }); @@ -1486,13 +1477,11 @@ describe("history", () => { id: arrow.id, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -1533,13 +1522,11 @@ describe("history", () => { id: arrow.id, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -1614,13 +1601,11 @@ describe("history", () => { id: arrow.id, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -1689,13 +1674,11 @@ describe("history", () => { id: arrow.id, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -4276,13 +4259,11 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -4347,13 +4328,11 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -4414,13 +4393,11 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -4489,14 +4466,12 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), // rebound with previous rectangle endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), @@ -4788,14 +4763,12 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: 0, gap: 1, }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, - focus: 0, + focus: -0, gap: 1, }), isDeleted: true, @@ -4838,13 +4811,11 @@ describe("history", () => { id: arrowId, startBinding: expect.objectContaining({ elementId: rect1.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), endBinding: expect.objectContaining({ elementId: rect2.id, - fixedPoint: null, focus: expect.toBeNonNaNNumber(), gap: expect.toBeNonNaNNumber(), }), diff --git a/packages/excalidraw/tests/linearElementEditor.test.tsx b/packages/excalidraw/tests/linearElementEditor.test.tsx index ef67329e0..986a63512 100644 --- a/packages/excalidraw/tests/linearElementEditor.test.tsx +++ b/packages/excalidraw/tests/linearElementEditor.test.tsx @@ -1238,7 +1238,7 @@ describe("Test Linear Elements", () => { mouse.downAt(rect.x, rect.y); mouse.moveTo(200, 0); mouse.upAt(200, 0); - expect(arrow.width).toBe(200); + expect(arrow.width).toBeCloseTo(204, 0); expect(rect.x).toBe(200); expect(rect.y).toBe(0); expect(handleBindTextResizeSpy).toHaveBeenCalledWith( diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 5e11fe5b6..17de52247 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -123,7 +123,7 @@ describe("move element", () => { expect([rectB.x, rectB.y]).toEqual([201, 2]); expect([Math.round(arrow.x), Math.round(arrow.y)]).toEqual([110, 50]); expect([Math.round(arrow.width), Math.round(arrow.height)]).toEqual([ - 81, 81, + 84, 84, ]); h.elements.forEach((element) => expect(element).toMatchSnapshot()); diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index 1e2e0f4aa..eca7b7e50 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -181,12 +181,12 @@ describe("generic element", () => { UI.resize(rectangle, "e", [40, 0]); - expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(30); + expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(30, 0); UI.resize(rectangle, "w", [50, 0]); expect(arrow.endBinding?.elementId).toEqual(rectangle.id); - expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(80); + expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(80, 0); }); it("resizes with a label", async () => { @@ -501,12 +501,12 @@ describe("arrow element", () => { h.state, )[0] as ExcalidrawElbowArrowElement; - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize(rectangle, "se", [-200, -150]); - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); }); @@ -529,13 +529,13 @@ describe("arrow element", () => { h.state, )[0] as ExcalidrawElbowArrowElement; - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1.05); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(1); expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize([rectangle, arrow], "nw", [300, 350]); - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.144); - expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.25); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.13); + expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.11); }); }); @@ -811,15 +811,16 @@ describe("image element", () => { UI.resize(image, "ne", [40, 0]); - expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(30); + expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo(31, 0); const imageWidth = image.width; const scale = 20 / image.height; UI.resize(image, "nw", [50, 20]); expect(arrow.endBinding?.elementId).toEqual(image.id); - expect(arrow.width + arrow.endBinding!.gap).toBeCloseTo( + expect(Math.floor(arrow.width + arrow.endBinding!.gap)).toBeCloseTo( 30 + imageWidth * scale, + 0, ); }); }); @@ -1024,7 +1025,7 @@ describe("multiple selection", () => { expect(leftBoundArrow.x).toBeCloseTo(-110); expect(leftBoundArrow.y).toBeCloseTo(50); - expect(leftBoundArrow.width).toBeCloseTo(140, 0); + expect(leftBoundArrow.width).toBeCloseTo(143, 0); expect(leftBoundArrow.height).toBeCloseTo(7, 0); expect(leftBoundArrow.angle).toEqual(0); expect(leftBoundArrow.startBinding).toBeNull(); @@ -1046,7 +1047,9 @@ describe("multiple selection", () => { expect(rightBoundArrow.endBinding?.elementId).toBe( rightArrowBinding.elementId, ); - expect(rightBoundArrow.endBinding?.focus).toBe(rightArrowBinding.focus); + expect(rightBoundArrow.endBinding?.focus).toBeCloseTo( + rightArrowBinding.focus!, + ); }); it("resizes with labeled arrows", async () => { diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index a5301cc34..367313ea9 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -32,7 +32,7 @@ test("unselected bound arrow updates when rotating its target element", async () expect(arrow.endBinding?.elementId).toEqual(rectangle.id); expect(arrow.x).toBeCloseTo(-80); expect(arrow.y).toBeCloseTo(50); - expect(arrow.width).toBeCloseTo(110.7, 1); + expect(arrow.width).toBeCloseTo(116.7, 1); expect(arrow.height).toBeCloseTo(0); }); @@ -69,8 +69,8 @@ test("unselected bound arrows update when rotating their target elements", async expect(ellipseArrow.x).toEqual(0); expect(ellipseArrow.y).toEqual(0); expect(ellipseArrow.points[0]).toEqual([0, 0]); - expect(ellipseArrow.points[1][0]).toBeCloseTo(48.5, 1); - expect(ellipseArrow.points[1][1]).toBeCloseTo(126.5, 1); + expect(ellipseArrow.points[1][0]).toBeCloseTo(48.98, 1); + expect(ellipseArrow.points[1][1]).toBeCloseTo(125.79, 1); expect(textArrow.endBinding?.elementId).toEqual(text.id); expect(textArrow.x).toEqual(360); diff --git a/packages/excalidraw/tests/test-utils.ts b/packages/excalidraw/tests/test-utils.ts index 5e395c1e8..84936f520 100644 --- a/packages/excalidraw/tests/test-utils.ts +++ b/packages/excalidraw/tests/test-utils.ts @@ -16,7 +16,6 @@ import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants"; import { getSelectedElements } from "../scene/selection"; import type { ExcalidrawElement } from "../element/types"; import { UI } from "./helpers/ui"; -import { diffStringsUnified } from "jest-diff"; import ansi from "ansicolor"; import { ORIG_ID } from "../constants"; import { arrayToMap } from "../utils"; @@ -259,36 +258,6 @@ expect.extend({ pass: false, }; }, - - toCloselyEqualPoints(received, expected, precision) { - if (!Array.isArray(received) || !Array.isArray(expected)) { - throw new Error("expected and received are not point arrays"); - } - - const COMPARE = 1 / Math.pow(10, precision || 2); - const pass = received.every( - (point, idx) => - Math.abs(expected[idx]?.[0] - point[0]) < COMPARE && - Math.abs(expected[idx]?.[1] - point[1]) < COMPARE, - ); - - if (!pass) { - return { - message: () => ` The provided array of points are not close enough. - -${diffStringsUnified( - JSON.stringify(expected, undefined, 2), - JSON.stringify(received, undefined, 2), -)}`, - pass: false, - }; - } - - return { - message: () => `expected ${received} to not be close to ${expected}`, - pass: true, - }; - }, }); /** diff --git a/packages/excalidraw/visualdebug.ts b/packages/excalidraw/visualdebug.ts index 96befa731..49dacc916 100644 --- a/packages/excalidraw/visualdebug.ts +++ b/packages/excalidraw/visualdebug.ts @@ -1,3 +1,4 @@ +import type { Curve } from "../math"; import { isLineSegment, lineSegment, @@ -6,7 +7,7 @@ import { type LocalPoint, } from "../math"; import type { LineSegment } from "../utils"; -import type { BoundingBox, Bounds } from "./element/bounds"; +import type { Bounds } from "./element/bounds"; import { isBounds } from "./element/typeChecks"; // The global data holder to collect the debug operations @@ -16,17 +17,29 @@ declare global { data: DebugElement[][]; currentFrame?: number; }; - debugDrawPoint: typeof debugDrawPoint; - debugDrawLine: typeof debugDrawLine; } } export type DebugElement = { color: string; - data: LineSegment; + data: LineSegment | Curve; permanent: boolean; }; +export const debugDrawCubicBezier = ( + c: Curve, + opts?: { + color?: string; + permanent?: boolean; + }, +) => { + addToCurrentFrame({ + color: opts?.color ?? "purple", + permanent: !!opts?.permanent, + data: c, + }); +}; + export const debugDrawLine = ( segment: LineSegment | LineSegment[], opts?: { @@ -80,41 +93,6 @@ export const debugDrawPoint = ( ); }; -export const debugDrawBoundingBox = ( - box: BoundingBox | BoundingBox[], - opts?: { - color?: string; - permanent?: boolean; - }, -) => { - (Array.isArray(box) ? box : [box]).forEach((bbox) => - debugDrawLine( - [ - lineSegment( - pointFrom(bbox.minX, bbox.minY), - pointFrom(bbox.maxX, bbox.minY), - ), - lineSegment( - pointFrom(bbox.maxX, bbox.minY), - pointFrom(bbox.maxX, bbox.maxY), - ), - lineSegment( - pointFrom(bbox.maxX, bbox.maxY), - pointFrom(bbox.minX, bbox.maxY), - ), - lineSegment( - pointFrom(bbox.minX, bbox.maxY), - pointFrom(bbox.minX, bbox.minY), - ), - ], - { - color: opts?.color ?? "cyan", - permanent: opts?.permanent, - }, - ), - ); -}; - export const debugDrawBounds = ( box: Bounds | Bounds[], opts?: { diff --git a/packages/math/angle.ts b/packages/math/angle.ts index 2dc97a469..8d473cf55 100644 --- a/packages/math/angle.ts +++ b/packages/math/angle.ts @@ -26,7 +26,10 @@ export const normalizeRadians = (angle: Radians): Radians => { export const cartesian2Polar =

([ x, y, -]: P): PolarCoords => [Math.hypot(x, y), Math.atan2(y, x)]; +]: P): PolarCoords => [ + Math.hypot(x, y), + normalizeRadians(Math.atan2(y, x) as Radians), +]; export function degreesToRadians(degrees: Degrees): Radians { return ((degrees * Math.PI) / 180) as Radians; diff --git a/packages/math/arc.test.ts b/packages/math/arc.test.ts deleted file mode 100644 index adf778591..000000000 --- a/packages/math/arc.test.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { isPointOnSymmetricArc } from "./arc"; -import { pointFrom } from "./point"; - -describe("point on arc", () => { - it("should detect point on simple arc", () => { - expect( - isPointOnSymmetricArc( - { - radius: 1, - startAngle: -Math.PI / 4, - endAngle: Math.PI / 4, - }, - pointFrom(0.92291667, 0.385), - ), - ).toBe(true); - }); - it("should not detect point outside of a simple arc", () => { - expect( - isPointOnSymmetricArc( - { - radius: 1, - startAngle: -Math.PI / 4, - endAngle: Math.PI / 4, - }, - pointFrom(-0.92291667, 0.385), - ), - ).toBe(false); - }); - it("should not detect point with good angle but incorrect radius", () => { - expect( - isPointOnSymmetricArc( - { - radius: 1, - startAngle: -Math.PI / 4, - endAngle: Math.PI / 4, - }, - pointFrom(-0.5, 0.5), - ), - ).toBe(false); - }); -}); diff --git a/packages/math/arc.ts b/packages/math/arc.ts deleted file mode 100644 index c93830dba..000000000 --- a/packages/math/arc.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { cartesian2Polar } from "./angle"; -import type { GlobalPoint, LocalPoint, SymmetricArc } from "./types"; -import { PRECISION } from "./utils"; - -/** - * Determines if a cartesian point lies on a symmetric arc, i.e. an arc which - * is part of a circle contour centered on 0, 0. - */ -export const isPointOnSymmetricArc =

( - { radius: arcRadius, startAngle, endAngle }: SymmetricArc, - point: P, -): boolean => { - const [radius, angle] = cartesian2Polar(point); - - return startAngle < endAngle - ? Math.abs(radius - arcRadius) < PRECISION && - startAngle <= angle && - endAngle >= angle - : startAngle <= angle || endAngle >= angle; -}; diff --git a/packages/math/curve.test.ts b/packages/math/curve.test.ts new file mode 100644 index 000000000..94670d7ab --- /dev/null +++ b/packages/math/curve.test.ts @@ -0,0 +1,101 @@ +import "../utils/test-utils"; +import { + curve, + curveClosestPoint, + curveIntersectLineSegment, + curvePointDistance, +} from "./curve"; +import { pointFrom } from "./point"; +import { lineSegment } from "./segment"; + +describe("Math curve", () => { + describe("line segment intersection", () => { + it("point is found when control points are the same", () => { + const c = curve( + pointFrom(100, 0), + pointFrom(100, 100), + pointFrom(100, 100), + pointFrom(0, 100), + ); + const l = lineSegment(pointFrom(0, 0), pointFrom(200, 200)); + + expect(curveIntersectLineSegment(c, l)).toCloselyEqualPoints([ + [87.5, 87.5], + ]); + }); + + it("point is found when control points aren't the same", () => { + const c = curve( + pointFrom(100, 0), + pointFrom(100, 60), + pointFrom(60, 100), + pointFrom(0, 100), + ); + const l = lineSegment(pointFrom(0, 0), pointFrom(200, 200)); + + expect(curveIntersectLineSegment(c, l)).toCloselyEqualPoints([ + [72.5, 72.5], + ]); + }); + + it("points are found when curve is sliced at 3 points", () => { + const c = curve( + pointFrom(-50, -50), + pointFrom(10, -50), + pointFrom(10, 50), + pointFrom(50, 50), + ); + const l = lineSegment(pointFrom(0, 112.5), pointFrom(90, 0)); + + expect(curveIntersectLineSegment(c, l)).toCloselyEqualPoints([[50, 50]]); + }); + + it("can be detected where the determinant is overly precise", () => { + const c = curve( + pointFrom(41.028864759926016, 12.226249068355052), + pointFrom(41.028864759926016, 33.55958240168839), + pointFrom(30.362198093259348, 44.22624906835505), + pointFrom(9.028864759926016, 44.22624906835505), + ); + const l = lineSegment( + pointFrom(-82.30963544324186, -41.19949363038283), + + pointFrom(188.2149592542487, 134.75505940984908), + ); + + expect(curveIntersectLineSegment(c, l)).toCloselyEqualPoints([ + [34.4, 34.71], + ]); + }); + }); + + describe("point closest to other", () => { + it("point can be found", () => { + const c = curve( + pointFrom(-50, -50), + pointFrom(10, -50), + pointFrom(10, 50), + pointFrom(50, 50), + ); + const p = pointFrom(0, 0); + + expect([curveClosestPoint(c, p)]).toCloselyEqualPoints([ + [5.965462100367372, -3.04104878946646], + ]); + }); + }); + + describe("point shortest distance", () => { + it("can be determined", () => { + const c = curve( + pointFrom(-50, -50), + pointFrom(10, -50), + pointFrom(10, 50), + pointFrom(50, 50), + ); + const p = pointFrom(0, 0); + + expect(curvePointDistance(c, p)).toBeCloseTo(6.695873043213627); + }); + }); +}); diff --git a/packages/math/curve.ts b/packages/math/curve.ts index 68a885fd8..9b275ceec 100644 --- a/packages/math/curve.ts +++ b/packages/math/curve.ts @@ -1,5 +1,7 @@ -import { pointFrom, pointRotateRads } from "./point"; -import type { Curve, GlobalPoint, LocalPoint, Radians } from "./types"; +import type { Bounds } from "../excalidraw/element/bounds"; +import { isPoint, pointDistance, pointFrom } from "./point"; +import { rectangle, rectangleIntersectLineSegment } from "./rectangle"; +import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types"; /** * @@ -18,206 +20,263 @@ export function curve( return [a, b, c, d] as Curve; } -export const curveRotate = ( - curve: Curve, - angle: Radians, - origin: Point, -) => { - return curve.map((p) => pointRotateRads(p, origin, angle)); -}; +function gradient( + f: (t: number, s: number) => number, + t0: number, + s0: number, + delta: number = 1e-6, +): number[] { + return [ + (f(t0 + delta, s0) - f(t0 - delta, s0)) / (2 * delta), + (f(t0, s0 + delta) - f(t0, s0 - delta)) / (2 * delta), + ]; +} + +function solve( + f: (t: number, s: number) => [number, number], + t0: number, + s0: number, + tolerance: number = 1e-3, + iterLimit: number = 10, +): number[] | null { + let error = Infinity; + let iter = 0; + + while (error >= tolerance) { + if (iter >= iterLimit) { + return null; + } + + const y0 = f(t0, s0); + const jacobian = [ + gradient((t, s) => f(t, s)[0], t0, s0), + gradient((t, s) => f(t, s)[1], t0, s0), + ]; + const b = [[-y0[0]], [-y0[1]]]; + const det = + jacobian[0][0] * jacobian[1][1] - jacobian[0][1] * jacobian[1][0]; + + if (det === 0) { + return null; + } + + const iJ = [ + [jacobian[1][1] / det, -jacobian[0][1] / det], + [-jacobian[1][0] / det, jacobian[0][0] / det], + ]; + const h = [ + [iJ[0][0] * b[0][0] + iJ[0][1] * b[1][0]], + [iJ[1][0] * b[0][0] + iJ[1][1] * b[1][0]], + ]; + + t0 = t0 + h[0][0]; + s0 = s0 + h[1][0]; + + const [tErr, sErr] = f(t0, s0); + error = Math.max(Math.abs(tErr), Math.abs(sErr)); + iter += 1; + } + + return [t0, s0]; +} + +const bezierEquation = ( + c: Curve, + t: number, +) => + pointFrom( + (1 - t) ** 3 * c[0][0] + + 3 * (1 - t) ** 2 * t * c[1][0] + + 3 * (1 - t) * t ** 2 * c[2][0] + + t ** 3 * c[3][0], + (1 - t) ** 3 * c[0][1] + + 3 * (1 - t) ** 2 * t * c[1][1] + + 3 * (1 - t) * t ** 2 * c[2][1] + + t ** 3 * c[3][1], + ); /** - * - * @param pointsIn - * @param curveTightness - * @returns + * Computes the intersection between a cubic spline and a line segment. */ -export function curveToBezier( - pointsIn: readonly Point[], - curveTightness = 0, -): Point[] { - const len = pointsIn.length; - if (len < 3) { - throw new Error("A curve must have at least three points."); +export function curveIntersectLineSegment< + Point extends GlobalPoint | LocalPoint, +>(c: Curve, l: LineSegment): Point[] { + // Optimize by doing a cheap bounding box check first + const bounds = curveBounds(c); + if ( + rectangleIntersectLineSegment( + rectangle( + pointFrom(bounds[0], bounds[1]), + pointFrom(bounds[2], bounds[3]), + ), + l, + ).length === 0 + ) { + return []; } - const out: Point[] = []; - if (len === 3) { - out.push( - pointFrom(pointsIn[0][0], pointsIn[0][1]), // Points need to be cloned - pointFrom(pointsIn[1][0], pointsIn[1][1]), // Points need to be cloned - pointFrom(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned - pointFrom(pointsIn[2][0], pointsIn[2][1]), // Points need to be cloned + + const line = (s: number) => + pointFrom( + l[0][0] + s * (l[1][0] - l[0][0]), + l[0][1] + s * (l[1][1] - l[0][1]), ); - } else { - const points: Point[] = []; - points.push(pointsIn[0], pointsIn[0]); - for (let i = 1; i < pointsIn.length; i++) { - points.push(pointsIn[i]); - if (i === pointsIn.length - 1) { - points.push(pointsIn[i]); - } + + const initial_guesses: [number, number][] = [ + [0.5, 0], + [0.2, 0], + [0.8, 0], + ]; + + const calculate = ([t0, s0]: [number, number]) => { + const solution = solve( + (t: number, s: number) => { + const bezier_point = bezierEquation(c, t); + const line_point = line(s); + + return [ + bezier_point[0] - line_point[0], + bezier_point[1] - line_point[1], + ]; + }, + t0, + s0, + ); + + if (!solution) { + return null; } - const b: Point[] = []; - const s = 1 - curveTightness; - out.push(pointFrom(points[0][0], points[0][1])); - for (let i = 1; i + 2 < points.length; i++) { - const cachedVertArray = points[i]; - b[0] = pointFrom(cachedVertArray[0], cachedVertArray[1]); - b[1] = pointFrom( - cachedVertArray[0] + (s * points[i + 1][0] - s * points[i - 1][0]) / 6, - cachedVertArray[1] + (s * points[i + 1][1] - s * points[i - 1][1]) / 6, - ); - b[2] = pointFrom( - points[i + 1][0] + (s * points[i][0] - s * points[i + 2][0]) / 6, - points[i + 1][1] + (s * points[i][1] - s * points[i + 2][1]) / 6, - ); - b[3] = pointFrom(points[i + 1][0], points[i + 1][1]); - out.push(b[1], b[2], b[3]); + + const [t, s] = solution; + + if (t < 0 || t > 1 || s < 0 || s > 1) { + return null; } + + return bezierEquation(c, t); + }; + + let solution = calculate(initial_guesses[0]); + if (solution) { + return [solution]; } - return out; + + solution = calculate(initial_guesses[1]); + if (solution) { + return [solution]; + } + + solution = calculate(initial_guesses[2]); + if (solution) { + return [solution]; + } + + return []; } /** + * Finds the closest point on the Bezier curve from another point * - * @param t - * @param controlPoints + * @param x + * @param y + * @param P0 + * @param P1 + * @param P2 + * @param P3 + * @param tolerance + * @param maxLevel * @returns */ -export const cubicBezierPoint = ( - t: number, - controlPoints: Curve, -): Point => { - const [p0, p1, p2, p3] = controlPoints; +export function curveClosestPoint( + c: Curve, + p: Point, + tolerance: number = 1e-3, +): Point | null { + const localMinimum = ( + min: number, + max: number, + f: (t: number) => number, + e: number = tolerance, + ) => { + let m = min; + let n = max; + let k; - const x = - Math.pow(1 - t, 3) * p0[0] + - 3 * Math.pow(1 - t, 2) * t * p1[0] + - 3 * (1 - t) * Math.pow(t, 2) * p2[0] + - Math.pow(t, 3) * p3[0]; - - const y = - Math.pow(1 - t, 3) * p0[1] + - 3 * Math.pow(1 - t, 2) * t * p1[1] + - 3 * (1 - t) * Math.pow(t, 2) * p2[1] + - Math.pow(t, 3) * p3[1]; - - return pointFrom(x, y); -}; - -/** - * - * @param point - * @param controlPoints - * @returns - */ -export const cubicBezierDistance = ( - point: Point, - controlPoints: Curve, -) => { - // Calculate the closest point on the Bezier curve to the given point - const t = findClosestParameter(point, controlPoints); - - // Calculate the coordinates of the closest point on the curve - const [closestX, closestY] = cubicBezierPoint(t, controlPoints); - - // Calculate the distance between the given point and the closest point on the curve - const distance = Math.sqrt( - (point[0] - closestX) ** 2 + (point[1] - closestY) ** 2, - ); - - return distance; -}; - -const solveCubic = (a: number, b: number, c: number, d: number) => { - // This function solves the cubic equation ax^3 + bx^2 + cx + d = 0 - const roots: number[] = []; - - const discriminant = - 18 * a * b * c * d - - 4 * Math.pow(b, 3) * d + - Math.pow(b, 2) * Math.pow(c, 2) - - 4 * a * Math.pow(c, 3) - - 27 * Math.pow(a, 2) * Math.pow(d, 2); - - if (discriminant >= 0) { - const C = Math.cbrt((discriminant + Math.sqrt(discriminant)) / 2); - const D = Math.cbrt((discriminant - Math.sqrt(discriminant)) / 2); - - const root1 = (-b - C - D) / (3 * a); - const root2 = (-b + (C + D) / 2) / (3 * a); - const root3 = (-b + (C + D) / 2) / (3 * a); - - roots.push(root1, root2, root3); - } else { - const realPart = -b / (3 * a); - - const root1 = - 2 * Math.sqrt(-b / (3 * a)) * Math.cos(Math.acos(realPart) / 3); - const root2 = - 2 * - Math.sqrt(-b / (3 * a)) * - Math.cos((Math.acos(realPart) + 2 * Math.PI) / 3); - const root3 = - 2 * - Math.sqrt(-b / (3 * a)) * - Math.cos((Math.acos(realPart) + 4 * Math.PI) / 3); - - roots.push(root1, root2, root3); - } - - return roots; -}; - -const findClosestParameter = ( - point: Point, - controlPoints: Curve, -) => { - // This function finds the parameter t that minimizes the distance between the point - // and any point on the cubic Bezier curve. - - const [p0, p1, p2, p3] = controlPoints; - - // Use the direct formula to find the parameter t - const a = p3[0] - 3 * p2[0] + 3 * p1[0] - p0[0]; - const b = 3 * p2[0] - 6 * p1[0] + 3 * p0[0]; - const c = 3 * p1[0] - 3 * p0[0]; - const d = p0[0] - point[0]; - - const rootsX = solveCubic(a, b, c, d); - - // Do the same for the y-coordinate - const e = p3[1] - 3 * p2[1] + 3 * p1[1] - p0[1]; - const f = 3 * p2[1] - 6 * p1[1] + 3 * p0[1]; - const g = 3 * p1[1] - 3 * p0[1]; - const h = p0[1] - point[1]; - - const rootsY = solveCubic(e, f, g, h); - - // Select the real root that is between 0 and 1 (inclusive) - const validRootsX = rootsX.filter((root) => root >= 0 && root <= 1); - const validRootsY = rootsY.filter((root) => root >= 0 && root <= 1); - - if (validRootsX.length === 0 || validRootsY.length === 0) { - // No valid roots found, use the midpoint as a fallback - return 0.5; - } - - // Choose the parameter t that minimizes the distance - let minDistance = Infinity; - let closestT = 0; - - for (const rootX of validRootsX) { - for (const rootY of validRootsY) { - const distance = Math.sqrt( - (rootX - point[0]) ** 2 + (rootY - point[1]) ** 2, - ); - if (distance < minDistance) { - minDistance = distance; - closestT = (rootX + rootY) / 2; // Use the average for a smoother result + while (n - m > e) { + k = (n + m) / 2; + if (f(k - e) < f(k + e)) { + n = k; + } else { + m = k; } } + + return k; + }; + + const maxSteps = 30; + let closestStep = 0; + for (let min = Infinity, step = 0; step < maxSteps; step++) { + const d = pointDistance(p, bezierEquation(c, step / maxSteps)); + if (d < min) { + min = d; + closestStep = step; + } } - return closestT; -}; + const t0 = Math.max((closestStep - 1) / maxSteps, 0); + const t1 = Math.min((closestStep + 1) / maxSteps, 1); + const solution = localMinimum(t0, t1, (t) => + pointDistance(p, bezierEquation(c, t)), + ); + + if (!solution) { + return null; + } + + return bezierEquation(c, solution); +} + +/** + * Determines the distance between a point and the closest point on the + * Bezier curve. + * + * @param c The curve to test + * @param p The point to measure from + */ +export function curvePointDistance( + c: Curve, + p: Point, +) { + const closest = curveClosestPoint(c, p); + + if (!closest) { + return 0; + } + + return pointDistance(p, closest); +} + +/** + * Determines if the parameter is a Curve + */ +export function isCurve

( + v: unknown, +): v is Curve

{ + return ( + Array.isArray(v) && + v.length === 4 && + isPoint(v[0]) && + isPoint(v[1]) && + isPoint(v[2]) && + isPoint(v[3]) + ); +} + +function curveBounds( + c: Curve, +): Bounds { + const [P0, P1, P2, P3] = c; + const x = [P0[0], P1[0], P2[0], P3[0]]; + const y = [P0[1], P1[1], P2[1], P3[1]]; + return [Math.min(...x), Math.min(...y), Math.max(...x), Math.max(...y)]; +} diff --git a/packages/math/ellipse.test.ts b/packages/math/ellipse.test.ts new file mode 100644 index 000000000..507cc5a1a --- /dev/null +++ b/packages/math/ellipse.test.ts @@ -0,0 +1,126 @@ +import { + ellipse, + ellipseSegmentInterceptPoints, + ellipseIncludesPoint, + ellipseTouchesPoint, + ellipseLineIntersectionPoints, +} from "./ellipse"; +import { line } from "./line"; +import { pointFrom } from "./point"; +import { lineSegment } from "./segment"; +import type { Ellipse, GlobalPoint } from "./types"; + +describe("point and ellipse", () => { + it("point on ellipse", () => { + const target: Ellipse = ellipse(pointFrom(1, 2), 2, 1); + [ + pointFrom(1, 3), + pointFrom(1, 1), + pointFrom(3, 2), + pointFrom(-1, 2), + ].forEach((p) => { + expect(ellipseTouchesPoint(p, target)).toBe(true); + }); + expect(ellipseTouchesPoint(pointFrom(-0.4, 2.7), target, 0.1)).toBe(true); + expect(ellipseTouchesPoint(pointFrom(-0.4, 2.71), target, 0.01)).toBe(true); + + expect(ellipseTouchesPoint(pointFrom(2.4, 2.7), target, 0.1)).toBe(true); + expect(ellipseTouchesPoint(pointFrom(2.4, 2.71), target, 0.01)).toBe(true); + + expect(ellipseTouchesPoint(pointFrom(2, 1.14), target, 0.1)).toBe(true); + expect(ellipseTouchesPoint(pointFrom(2, 1.14), target, 0.01)).toBe(true); + + expect(ellipseTouchesPoint(pointFrom(0, 1.14), target, 0.1)).toBe(true); + expect(ellipseTouchesPoint(pointFrom(0, 1.14), target, 0.01)).toBe(true); + + expect(ellipseTouchesPoint(pointFrom(0, 2.8), target)).toBe(false); + expect(ellipseTouchesPoint(pointFrom(2, 1.2), target)).toBe(false); + }); + + it("point in ellipse", () => { + const target: Ellipse = ellipse(pointFrom(0, 0), 2, 1); + [ + pointFrom(0, 1), + pointFrom(0, -1), + pointFrom(2, 0), + pointFrom(-2, 0), + ].forEach((p) => { + expect(ellipseIncludesPoint(p, target)).toBe(true); + }); + + expect(ellipseIncludesPoint(pointFrom(-1, 0.8), target)).toBe(true); + expect(ellipseIncludesPoint(pointFrom(1, -0.8), target)).toBe(true); + + // Point on outline + expect(ellipseIncludesPoint(pointFrom(2, 0), target)).toBe(true); + + expect(ellipseIncludesPoint(pointFrom(-1, 1), target)).toBe(false); + expect(ellipseIncludesPoint(pointFrom(-1.4, 0.8), target)).toBe(false); + }); +}); + +describe("segment and ellipse", () => { + it("detects outside segment", () => { + const e = ellipse(pointFrom(0, 0), 2, 2); + + expect( + ellipseSegmentInterceptPoints( + e, + lineSegment(pointFrom(-100, 0), pointFrom(-10, 0)), + ), + ).toEqual([]); + expect( + ellipseSegmentInterceptPoints( + e, + lineSegment(pointFrom(-10, 0), pointFrom(10, 0)), + ), + ).toEqual([pointFrom(-2, 0), pointFrom(2, 0)]); + expect( + ellipseSegmentInterceptPoints( + e, + lineSegment(pointFrom(-10, -2), pointFrom(10, -2)), + ), + ).toEqual([pointFrom(0, -2)]); + expect( + ellipseSegmentInterceptPoints( + e, + lineSegment(pointFrom(0, -1), pointFrom(0, 1)), + ), + ).toEqual([]); + }); +}); + +describe("line and ellipse", () => { + const e = ellipse(pointFrom(0, 0), 2, 2); + + it("detects outside line", () => { + expect( + ellipseLineIntersectionPoints( + e, + line(pointFrom(-10, -10), pointFrom(10, -10)), + ), + ).toEqual([]); + }); + it("detects line intersecting ellipse", () => { + expect( + ellipseLineIntersectionPoints( + e, + line(pointFrom(0, -1), pointFrom(0, 1)), + ), + ).toEqual([pointFrom(0, 2), pointFrom(0, -2)]); + expect( + ellipseLineIntersectionPoints( + e, + line(pointFrom(-100, 0), pointFrom(-10, 0)), + ).map(([x, y]) => pointFrom(Math.round(x), Math.round(y))), + ).toEqual([pointFrom(2, 0), pointFrom(-2, 0)]); + }); + it("detects line touching ellipse", () => { + expect( + ellipseLineIntersectionPoints( + e, + line(pointFrom(-2, -2), pointFrom(2, -2)), + ), + ).toEqual([pointFrom(0, -2)]); + }); +}); diff --git a/packages/math/ellipse.ts b/packages/math/ellipse.ts new file mode 100644 index 000000000..c32def0eb --- /dev/null +++ b/packages/math/ellipse.ts @@ -0,0 +1,230 @@ +import { + pointFrom, + pointDistance, + pointFromVector, + pointsEqual, +} from "./point"; +import type { + Ellipse, + GlobalPoint, + Line, + LineSegment, + LocalPoint, +} from "./types"; +import { PRECISION } from "./utils"; +import { + vector, + vectorAdd, + vectorDot, + vectorFromPoint, + vectorScale, +} from "./vector"; + +/** + * Construct an Ellipse object from the parameters + * + * @param center The center of the ellipse + * @param angle The slanting of the ellipse in radians + * @param halfWidth Half of the width of a non-slanted version of the ellipse + * @param halfHeight Half of the height of a non-slanted version of the ellipse + * @returns The constructed Ellipse object + */ +export function ellipse( + center: Point, + halfWidth: number, + halfHeight: number, +): Ellipse { + return { + center, + halfWidth, + halfHeight, + } as Ellipse; +} + +/** + * Determines if a point is inside or on the ellipse outline + * + * @param p The point to test + * @param ellipse The ellipse to compare against + * @returns TRUE if the point is inside or on the outline of the ellipse + */ +export const ellipseIncludesPoint = ( + p: Point, + ellipse: Ellipse, +) => { + const { center, halfWidth, halfHeight } = ellipse; + const normalizedX = (p[0] - center[0]) / halfWidth; + const normalizedY = (p[1] - center[1]) / halfHeight; + + return normalizedX * normalizedX + normalizedY * normalizedY <= 1; +}; + +/** + * Tests whether a point lies on the outline of the ellipse within a given + * tolerance + * + * @param point The point to test + * @param ellipse The ellipse to compare against + * @param threshold The distance to consider a point close enough to be "on" the outline + * @returns TRUE if the point is on the ellise outline + */ +export const ellipseTouchesPoint = ( + point: Point, + ellipse: Ellipse, + threshold = PRECISION, +) => { + return ellipseDistanceFromPoint(point, ellipse) <= threshold; +}; + +/** + * Determine the shortest euclidean distance from a point to the + * outline of the ellipse + * + * @param p The point to consider + * @param ellipse The ellipse to calculate the distance to + * @returns The eucledian distance + */ +export const ellipseDistanceFromPoint = < + Point extends GlobalPoint | LocalPoint, +>( + p: Point, + ellipse: Ellipse, +): number => { + const { halfWidth, halfHeight, center } = ellipse; + const a = halfWidth; + const b = halfHeight; + const translatedPoint = vectorAdd( + vectorFromPoint(p), + vectorScale(vectorFromPoint(center), -1), + ); + + const px = Math.abs(translatedPoint[0]); + const py = Math.abs(translatedPoint[1]); + + let tx = 0.707; + let ty = 0.707; + + for (let i = 0; i < 3; i++) { + const x = a * tx; + const y = b * ty; + + const ex = ((a * a - b * b) * tx ** 3) / a; + const ey = ((b * b - a * a) * ty ** 3) / b; + + const rx = x - ex; + const ry = y - ey; + + const qx = px - ex; + const qy = py - ey; + + const r = Math.hypot(ry, rx); + const q = Math.hypot(qy, qx); + + tx = Math.min(1, Math.max(0, ((qx * r) / q + ex) / a)); + ty = Math.min(1, Math.max(0, ((qy * r) / q + ey) / b)); + const t = Math.hypot(ty, tx); + tx /= t; + ty /= t; + } + + const [minX, minY] = [ + a * tx * Math.sign(translatedPoint[0]), + b * ty * Math.sign(translatedPoint[1]), + ]; + + return pointDistance(pointFromVector(translatedPoint), pointFrom(minX, minY)); +}; + +/** + * Calculate a maximum of two intercept points for a line going throug an + * ellipse. + */ +export function ellipseSegmentInterceptPoints< + Point extends GlobalPoint | LocalPoint, +>(e: Readonly>, s: Readonly>): Point[] { + const rx = e.halfWidth; + const ry = e.halfHeight; + + const dir = vectorFromPoint(s[1], s[0]); + const diff = vector(s[0][0] - e.center[0], s[0][1] - e.center[1]); + const mDir = vector(dir[0] / (rx * rx), dir[1] / (ry * ry)); + const mDiff = vector(diff[0] / (rx * rx), diff[1] / (ry * ry)); + + const a = vectorDot(dir, mDir); + const b = vectorDot(dir, mDiff); + const c = vectorDot(diff, mDiff) - 1.0; + const d = b * b - a * c; + + const intersections: Point[] = []; + + if (d > 0) { + const t_a = (-b - Math.sqrt(d)) / a; + const t_b = (-b + Math.sqrt(d)) / a; + + if (0 <= t_a && t_a <= 1) { + intersections.push( + pointFrom( + s[0][0] + (s[1][0] - s[0][0]) * t_a, + s[0][1] + (s[1][1] - s[0][1]) * t_a, + ), + ); + } + + if (0 <= t_b && t_b <= 1) { + intersections.push( + pointFrom( + s[0][0] + (s[1][0] - s[0][0]) * t_b, + s[0][1] + (s[1][1] - s[0][1]) * t_b, + ), + ); + } + } else if (d === 0) { + const t = -b / a; + if (0 <= t && t <= 1) { + intersections.push( + pointFrom( + s[0][0] + (s[1][0] - s[0][0]) * t, + s[0][1] + (s[1][1] - s[0][1]) * t, + ), + ); + } + } + + return intersections; +} + +export function ellipseLineIntersectionPoints< + Point extends GlobalPoint | LocalPoint, +>( + { center, halfWidth, halfHeight }: Ellipse, + [g, h]: Line, +): Point[] { + const [cx, cy] = center; + const x1 = g[0] - cx; + const y1 = g[1] - cy; + const x2 = h[0] - cx; + const y2 = h[1] - cy; + const a = + Math.pow(x2 - x1, 2) / Math.pow(halfWidth, 2) + + Math.pow(y2 - y1, 2) / Math.pow(halfHeight, 2); + const b = + 2 * + ((x1 * (x2 - x1)) / Math.pow(halfWidth, 2) + + (y1 * (y2 - y1)) / Math.pow(halfHeight, 2)); + const c = + Math.pow(x1, 2) / Math.pow(halfWidth, 2) + + Math.pow(y1, 2) / Math.pow(halfHeight, 2) - + 1; + const t1 = (-b + Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a); + const t2 = (-b - Math.sqrt(Math.pow(b, 2) - 4 * a * c)) / (2 * a); + const candidates = [ + pointFrom(x1 + t1 * (x2 - x1) + cx, y1 + t1 * (y2 - y1) + cy), + pointFrom(x1 + t2 * (x2 - x1) + cx, y1 + t2 * (y2 - y1) + cy), + ].filter((p) => !isNaN(p[0]) && !isNaN(p[1])); + + if (candidates.length === 2 && pointsEqual(candidates[0], candidates[1])) { + return [candidates[0]]; + } + + return candidates; +} diff --git a/packages/math/ga/ga.test.ts b/packages/math/ga/ga.test.ts deleted file mode 100644 index 767b5b65b..000000000 --- a/packages/math/ga/ga.test.ts +++ /dev/null @@ -1,70 +0,0 @@ -import * as GA from "./ga"; -import { point, toString, direction, offset } from "./ga"; -import * as GAPoint from "./gapoints"; -import * as GALine from "./galines"; -import * as GATransform from "./gatransforms"; - -describe("geometric algebra", () => { - describe("points", () => { - it("distanceToLine", () => { - const point = GA.point(3, 3); - const line = GALine.equation(0, 1, -1); - expect(GAPoint.distanceToLine(point, line)).toEqual(2); - }); - - it("distanceToLine neg", () => { - const point = GA.point(-3, -3); - const line = GALine.equation(0, 1, -1); - expect(GAPoint.distanceToLine(point, line)).toEqual(-4); - }); - }); - describe("lines", () => { - it("through", () => { - const a = GA.point(0, 0); - const b = GA.point(2, 0); - expect(toString(GALine.through(a, b))).toEqual( - toString(GALine.equation(0, 2, 0)), - ); - }); - it("parallel", () => { - const point = GA.point(3, 3); - const line = GALine.equation(0, 1, -1); - const parallel = GALine.parallel(line, 2); - expect(GAPoint.distanceToLine(point, parallel)).toEqual(0); - }); - }); - - describe("translation", () => { - it("points", () => { - const start = point(2, 2); - const move = GATransform.translation(direction(0, 1)); - const end = GATransform.apply(move, start); - expect(toString(end)).toEqual(toString(point(2, 3))); - }); - - it("points 2", () => { - const start = point(2, 2); - const move = GATransform.translation(offset(3, 4)); - const end = GATransform.apply(move, start); - expect(toString(end)).toEqual(toString(point(5, 6))); - }); - - it("lines", () => { - const original = GALine.through(point(2, 2), point(3, 4)); - const move = GATransform.translation(offset(3, 4)); - const parallel = GATransform.apply(move, original); - expect(toString(parallel)).toEqual( - toString(GALine.through(point(5, 6), point(6, 8))), - ); - }); - }); - describe("rotation", () => { - it("points", () => { - const start = point(2, 2); - const pivot = point(1, 1); - const rotate = GATransform.rotation(pivot, Math.PI / 2); - const end = GATransform.apply(rotate, start); - expect(toString(end)).toEqual(toString(point(2, 0))); - }); - }); -}); diff --git a/packages/math/ga/ga.ts b/packages/math/ga/ga.ts deleted file mode 100644 index 271aa7ae9..000000000 --- a/packages/math/ga/ga.ts +++ /dev/null @@ -1,317 +0,0 @@ -/** - * This is a 2D Projective Geometric Algebra implementation. - * - * For wider context on geometric algebra visit see https://bivector.net. - * - * For this specific algebra see cheatsheet https://bivector.net/2DPGA.pdf. - * - * Converted from generator written by enki, with a ton of added on top. - * - * This library uses 8-vectors to represent points, directions and lines - * in 2D space. - * - * An array `[a, b, c, d, e, f, g, h]` represents a n(8)vector: - * a + b*e0 + c*e1 + d*e2 + e*e01 + f*e20 + g*e12 + h*e012 - * - * See GAPoint, GALine, GADirection and GATransform modules for common - * operations. - */ - -export type Point = NVector; -export type Direction = NVector; -export type Line = NVector; -export type Transform = NVector; - -export const point = (x: number, y: number): Point => [0, 0, 0, 0, y, x, 1, 0]; - -export const origin = (): Point => [0, 0, 0, 0, 0, 0, 1, 0]; - -export const direction = (x: number, y: number): Direction => { - const norm = Math.hypot(x, y); // same as `inorm(direction(x, y))` - return [0, 0, 0, 0, y / norm, x / norm, 0, 0]; -}; - -export const offset = (x: number, y: number): Direction => [ - 0, - 0, - 0, - 0, - y, - x, - 0, - 0, -]; - -/// This is the "implementation" part of the library - -type NVector = readonly [ - number, - number, - number, - number, - number, - number, - number, - number, -]; - -// These are labels for what each number in an nvector represents -const NVECTOR_BASE = ["1", "e0", "e1", "e2", "e01", "e20", "e12", "e012"]; - -// Used to represent points, lines and transformations -export const nvector = (value: number = 0, index: number = 0): NVector => { - const result = [0, 0, 0, 0, 0, 0, 0, 0]; - if (index < 0 || index > 7) { - throw new Error(`Expected \`index\` between 0 and 7, got \`${index}\``); - } - if (value !== 0) { - result[index] = value; - } - return result as unknown as NVector; -}; - -const STRING_EPSILON = 0.000001; -export const toString = (nvector: NVector): string => { - const result = nvector - .map((value, index) => - Math.abs(value) > STRING_EPSILON - ? value.toFixed(7).replace(/(\.|0+)$/, "") + - (index > 0 ? NVECTOR_BASE[index] : "") - : null, - ) - .filter((representation) => representation != null) - .join(" + "); - return result === "" ? "0" : result; -}; - -// Reverse the order of the basis blades. -export const reverse = (nvector: NVector): NVector => [ - nvector[0], - nvector[1], - nvector[2], - nvector[3], - -nvector[4], - -nvector[5], - -nvector[6], - -nvector[7], -]; - -// Poincare duality operator. -export const dual = (nvector: NVector): NVector => [ - nvector[7], - nvector[6], - nvector[5], - nvector[4], - nvector[3], - nvector[2], - nvector[1], - nvector[0], -]; - -// Clifford Conjugation -export const conjugate = (nvector: NVector): NVector => [ - nvector[0], - -nvector[1], - -nvector[2], - -nvector[3], - -nvector[4], - -nvector[5], - -nvector[6], - nvector[7], -]; - -// Main involution -export const involute = (nvector: NVector): NVector => [ - nvector[0], - -nvector[1], - -nvector[2], - -nvector[3], - nvector[4], - nvector[5], - nvector[6], - -nvector[7], -]; - -// Multivector addition -export const add = (a: NVector, b: NVector | number): NVector => { - if (isNumber(b)) { - return [a[0] + b, a[1], a[2], a[3], a[4], a[5], a[6], a[7]]; - } - return [ - a[0] + b[0], - a[1] + b[1], - a[2] + b[2], - a[3] + b[3], - a[4] + b[4], - a[5] + b[5], - a[6] + b[6], - a[7] + b[7], - ]; -}; - -// Multivector subtraction -export const sub = (a: NVector, b: NVector | number): NVector => { - if (isNumber(b)) { - return [a[0] - b, a[1], a[2], a[3], a[4], a[5], a[6], a[7]]; - } - return [ - a[0] - b[0], - a[1] - b[1], - a[2] - b[2], - a[3] - b[3], - a[4] - b[4], - a[5] - b[5], - a[6] - b[6], - a[7] - b[7], - ]; -}; - -// The geometric product. -export const mul = (a: NVector, b: NVector | number): NVector => { - if (isNumber(b)) { - return [ - a[0] * b, - a[1] * b, - a[2] * b, - a[3] * b, - a[4] * b, - a[5] * b, - a[6] * b, - a[7] * b, - ]; - } - return [ - mulScalar(a, b), - b[1] * a[0] + - b[0] * a[1] - - b[4] * a[2] + - b[5] * a[3] + - b[2] * a[4] - - b[3] * a[5] - - b[7] * a[6] - - b[6] * a[7], - b[2] * a[0] + b[0] * a[2] - b[6] * a[3] + b[3] * a[6], - b[3] * a[0] + b[6] * a[2] + b[0] * a[3] - b[2] * a[6], - b[4] * a[0] + - b[2] * a[1] - - b[1] * a[2] + - b[7] * a[3] + - b[0] * a[4] + - b[6] * a[5] - - b[5] * a[6] + - b[3] * a[7], - b[5] * a[0] - - b[3] * a[1] + - b[7] * a[2] + - b[1] * a[3] - - b[6] * a[4] + - b[0] * a[5] + - b[4] * a[6] + - b[2] * a[7], - b[6] * a[0] + b[3] * a[2] - b[2] * a[3] + b[0] * a[6], - b[7] * a[0] + - b[6] * a[1] + - b[5] * a[2] + - b[4] * a[3] + - b[3] * a[4] + - b[2] * a[5] + - b[1] * a[6] + - b[0] * a[7], - ]; -}; - -export const mulScalar = (a: NVector, b: NVector): number => - b[0] * a[0] + b[2] * a[2] + b[3] * a[3] - b[6] * a[6]; - -// The outer/exterior/wedge product. -export const meet = (a: NVector, b: NVector): NVector => [ - b[0] * a[0], - b[1] * a[0] + b[0] * a[1], - b[2] * a[0] + b[0] * a[2], - b[3] * a[0] + b[0] * a[3], - b[4] * a[0] + b[2] * a[1] - b[1] * a[2] + b[0] * a[4], - b[5] * a[0] - b[3] * a[1] + b[1] * a[3] + b[0] * a[5], - b[6] * a[0] + b[3] * a[2] - b[2] * a[3] + b[0] * a[6], - b[7] * a[0] + - b[6] * a[1] + - b[5] * a[2] + - b[4] * a[3] + - b[3] * a[4] + - b[2] * a[5] + - b[1] * a[6], -]; - -// The regressive product. -export const join = (a: NVector, b: NVector): NVector => [ - joinScalar(a, b), - a[1] * b[7] + a[4] * b[5] - a[5] * b[4] + a[7] * b[1], - a[2] * b[7] - a[4] * b[6] + a[6] * b[4] + a[7] * b[2], - a[3] * b[7] + a[5] * b[6] - a[6] * b[5] + a[7] * b[3], - a[4] * b[7] + a[7] * b[4], - a[5] * b[7] + a[7] * b[5], - a[6] * b[7] + a[7] * b[6], - a[7] * b[7], -]; - -export const joinScalar = (a: NVector, b: NVector): number => - a[0] * b[7] + - a[1] * b[6] + - a[2] * b[5] + - a[3] * b[4] + - a[4] * b[3] + - a[5] * b[2] + - a[6] * b[1] + - a[7] * b[0]; - -// The inner product. -export const dot = (a: NVector, b: NVector): NVector => [ - b[0] * a[0] + b[2] * a[2] + b[3] * a[3] - b[6] * a[6], - b[1] * a[0] + - b[0] * a[1] - - b[4] * a[2] + - b[5] * a[3] + - b[2] * a[4] - - b[3] * a[5] - - b[7] * a[6] - - b[6] * a[7], - b[2] * a[0] + b[0] * a[2] - b[6] * a[3] + b[3] * a[6], - b[3] * a[0] + b[6] * a[2] + b[0] * a[3] - b[2] * a[6], - b[4] * a[0] + b[7] * a[3] + b[0] * a[4] + b[3] * a[7], - b[5] * a[0] + b[7] * a[2] + b[0] * a[5] + b[2] * a[7], - b[6] * a[0] + b[0] * a[6], - b[7] * a[0] + b[0] * a[7], -]; - -export const norm = (a: NVector): number => - Math.sqrt(Math.abs(a[0] * a[0] - a[2] * a[2] - a[3] * a[3] + a[6] * a[6])); - -export const inorm = (a: NVector): number => - Math.sqrt(Math.abs(a[7] * a[7] - a[5] * a[5] - a[4] * a[4] + a[1] * a[1])); - -export const normalized = (a: NVector): NVector => { - const n = norm(a); - if (n === 0 || n === 1) { - return a; - } - const sign = a[6] < 0 ? -1 : 1; - return mul(a, sign / n); -}; - -export const inormalized = (a: NVector): NVector => { - const n = inorm(a); - if (n === 0 || n === 1) { - return a; - } - return mul(a, 1 / n); -}; - -const isNumber = (a: any): a is number => typeof a === "number"; - -export const E0: NVector = nvector(1, 1); -export const E1: NVector = nvector(1, 2); -export const E2: NVector = nvector(1, 3); -export const E01: NVector = nvector(1, 4); -export const E20: NVector = nvector(1, 5); -export const E12: NVector = nvector(1, 6); -export const E012: NVector = nvector(1, 7); -export const I = E012; diff --git a/packages/math/ga/gadirections.ts b/packages/math/ga/gadirections.ts deleted file mode 100644 index 2f631fa6a..000000000 --- a/packages/math/ga/gadirections.ts +++ /dev/null @@ -1,26 +0,0 @@ -import * as GA from "./ga"; -import type { Line, Direction, Point } from "./ga"; - -/** - * A direction is stored as an array `[0, 0, 0, 0, y, x, 0, 0]` representing - * vector `(x, y)`. - */ - -export const from = (point: Point): Point => [ - 0, - 0, - 0, - 0, - point[4], - point[5], - 0, - 0, -]; - -export const fromTo = (from: Point, to: Point): Direction => - GA.inormalized([0, 0, 0, 0, to[4] - from[4], to[5] - from[5], 0, 0]); - -export const orthogonal = (direction: Direction): Direction => - GA.inormalized([0, 0, 0, 0, -direction[5], direction[4], 0, 0]); - -export const orthogonalToLine = (line: Line): Direction => GA.mul(line, GA.I); diff --git a/packages/math/ga/galines.ts b/packages/math/ga/galines.ts deleted file mode 100644 index f5058ce69..000000000 --- a/packages/math/ga/galines.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as GA from "./ga"; -import type { Line, Point } from "./ga"; - -/** - * A line is stored as an array `[0, c, a, b, 0, 0, 0, 0]` representing: - * c * e0 + a * e1 + b*e2 - * - * This maps to a standard formula `a * x + b * y + c`. - * - * `(-b, a)` corresponds to a 2D vector parallel to the line. The lines - * have a natural orientation, corresponding to that vector. - * - * The magnitude ("norm") of the line is `sqrt(a ^ 2 + b ^ 2)`. - * `c / norm(line)` is the oriented distance from line to origin. - */ - -// Returns line with direction (x, y) through origin -export const vector = (x: number, y: number): Line => - GA.normalized([0, 0, -y, x, 0, 0, 0, 0]); - -// For equation ax + by + c = 0. -export const equation = (a: number, b: number, c: number): Line => - GA.normalized([0, c, a, b, 0, 0, 0, 0]); - -export const through = (from: Point, to: Point): Line => - GA.normalized(GA.join(to, from)); - -export const orthogonal = (line: Line, point: Point): Line => - GA.dot(line, point); - -// Returns a line perpendicular to the line through `against` and `intersection` -// going through `intersection`. -export const orthogonalThrough = (against: Point, intersection: Point): Line => - orthogonal(through(against, intersection), intersection); - -export const parallel = (line: Line, distance: number): Line => { - const result = line.slice(); - result[1] -= distance; - return result as unknown as Line; -}; - -export const parallelThrough = (line: Line, point: Point): Line => - orthogonal(orthogonal(point, line), point); - -export const distance = (line1: Line, line2: Line): number => - GA.inorm(GA.meet(line1, line2)); - -export const angle = (line1: Line, line2: Line): number => - Math.acos(GA.dot(line1, line2)[0]); - -// The orientation of the line -export const sign = (line: Line): number => Math.sign(line[1]); diff --git a/packages/math/ga/gapoints.ts b/packages/math/ga/gapoints.ts deleted file mode 100644 index 909e8ffe6..000000000 --- a/packages/math/ga/gapoints.ts +++ /dev/null @@ -1,42 +0,0 @@ -import * as GA from "./ga"; -import * as GALine from "./galines"; -import type { Point, Line } from "./ga"; -import { join } from "./ga"; - -export const from = ([x, y]: readonly [number, number]): Point => [ - 0, - 0, - 0, - 0, - y, - x, - 1, - 0, -]; - -export const toTuple = (point: Point): [number, number] => [point[5], point[4]]; - -export const abs = (point: Point): Point => [ - 0, - 0, - 0, - 0, - Math.abs(point[4]), - Math.abs(point[5]), - 1, - 0, -]; - -export const intersect = (line1: Line, line2: Line): Point => - GA.normalized(GA.meet(line1, line2)); - -// Projects `point` onto the `line`. -// The returned point is the closest point on the `line` to the `point`. -export const project = (point: Point, line: Line): Point => - intersect(GALine.orthogonal(line, point), line); - -export const distance = (point1: Point, point2: Point): number => - GA.norm(join(point1, point2)); - -export const distanceToLine = (point: Point, line: Line): number => - GA.joinScalar(point, line); diff --git a/packages/math/ga/gatransforms.ts b/packages/math/ga/gatransforms.ts deleted file mode 100644 index 2301d979e..000000000 --- a/packages/math/ga/gatransforms.ts +++ /dev/null @@ -1,41 +0,0 @@ -import * as GA from "./ga"; -import type { Line, Direction, Point, Transform } from "./ga"; -import * as GADirection from "./gadirections"; - -/** - * TODO: docs - */ - -export const rotation = (pivot: Point, angle: number): Transform => - GA.add(GA.mul(pivot, Math.sin(angle / 2)), Math.cos(angle / 2)); - -export const translation = (direction: Direction): Transform => [ - 1, - 0, - 0, - 0, - -(0.5 * direction[5]), - 0.5 * direction[4], - 0, - 0, -]; - -export const translationOrthogonal = ( - direction: Direction, - distance: number, -): Transform => { - const scale = 0.5 * distance; - return [1, 0, 0, 0, scale * direction[4], scale * direction[5], 0, 0]; -}; - -export const translationAlong = (line: Line, distance: number): Transform => - GA.add(GA.mul(GADirection.orthogonalToLine(line), 0.5 * distance), 1); - -export const compose = (motor1: Transform, motor2: Transform): Transform => - GA.mul(motor2, motor1); - -export const apply = ( - motor: Transform, - nvector: Point | Direction | Line, -): Point | Direction | Line => - GA.normalized(GA.mul(GA.mul(motor, nvector), GA.reverse(motor))); diff --git a/packages/math/index.ts b/packages/math/index.ts index 05ec5158f..d00ab469d 100644 --- a/packages/math/index.ts +++ b/packages/math/index.ts @@ -1,10 +1,10 @@ -export * from "./arc"; export * from "./angle"; export * from "./curve"; export * from "./line"; export * from "./point"; export * from "./polygon"; export * from "./range"; +export * from "./rectangle"; export * from "./segment"; export * from "./triangle"; export * from "./types"; diff --git a/packages/math/line.test.ts b/packages/math/line.test.ts new file mode 100644 index 000000000..0e6bb1cc8 --- /dev/null +++ b/packages/math/line.test.ts @@ -0,0 +1,31 @@ +import { line, linesIntersectAt } from "./line"; +import { pointFrom } from "./point"; + +describe("line-line intersections", () => { + it("should correctly detect intersection at origin", () => { + expect( + linesIntersectAt( + line(pointFrom(-5, -5), pointFrom(5, 5)), + line(pointFrom(5, -5), pointFrom(-5, 5)), + ), + ).toEqual(pointFrom(0, 0)); + }); + + it("should correctly detect intersection at non-origin", () => { + expect( + linesIntersectAt( + line(pointFrom(0, 0), pointFrom(10, 10)), + line(pointFrom(10, 0), pointFrom(0, 10)), + ), + ).toEqual(pointFrom(5, 5)); + }); + + it("should correctly detect parallel lines", () => { + expect( + linesIntersectAt( + line(pointFrom(0, 0), pointFrom(0, 10)), + line(pointFrom(10, 0), pointFrom(10, 10)), + ), + ).toBe(null); + }); +}); diff --git a/packages/math/line.ts b/packages/math/line.ts index 89999baa9..bcb4f6d90 100644 --- a/packages/math/line.ts +++ b/packages/math/line.ts @@ -1,5 +1,5 @@ -import { pointCenter, pointFrom, pointRotateRads } from "./point"; -import type { GlobalPoint, Line, LocalPoint, Radians } from "./types"; +import { pointFrom } from "./point"; +import type { GlobalPoint, Line, LocalPoint } from "./types"; /** * Create a line from two points. @@ -11,54 +11,6 @@ export function line

(a: P, b: P): Line

{ return [a, b] as Line

; } -/** - * Convenient point creation from an array of two points. - * - * @param param0 The array with the two points to convert to a line - * @returns The created line - */ -export function lineFromPointPair

([a, b]: [ - P, - P, -]): Line

{ - return line(a, b); -} - -/** - * TODO - * - * @param pointArray - * @returns - */ -export function lineFromPointArray

( - pointArray: P[], -): Line

| undefined { - return pointArray.length === 2 - ? line

(pointArray[0], pointArray[1]) - : undefined; -} - -/** - * Return the coordinates resulting from rotating the given line about an - * origin by an angle in degrees note that when the origin is not given, - * the midpoint of the given line is used as the origin - * - * @param l - * @param angle - * @param origin - * @returns - */ -export const lineRotate = ( - l: Line, - angle: Radians, - origin?: Point, -): Line => { - return line( - pointRotateRads(l[0], origin || pointCenter(l[0], l[1]), angle), - pointRotateRads(l[1], origin || pointCenter(l[0], l[1]), angle), - ); -}; - /** * Determines the intersection point (unless the lines are parallel) of two * lines @@ -67,10 +19,10 @@ export const lineRotate = ( * @param b * @returns */ -export const linesIntersectAt = ( +export function linesIntersectAt( a: Line, b: Line, -): Point | null => { +): Point | null { const A1 = a[1][1] - a[0][1]; const B1 = a[0][0] - a[1][0]; const A2 = b[1][1] - b[0][1]; @@ -83,4 +35,4 @@ export const linesIntersectAt = ( } return null; -}; +} diff --git a/packages/math/point.ts b/packages/math/point.ts index 40f178efb..92df18773 100644 --- a/packages/math/point.ts +++ b/packages/math/point.ts @@ -57,24 +57,9 @@ export function pointFromPair( */ export function pointFromVector

( v: Vector, + offset: P = pointFrom(0, 0), ): P { - return v as unknown as P; -} - -/** - * Convert the coordiante object to a point. - * - * @param coords The coordinate object with x and y properties - * @returns - */ -export function pointFromCoords({ - x, - y, -}: { - x: number; - y: number; -}) { - return [x, y] as Point; + return pointFrom

(offset[0] + v[0], offset[1] + v[1]); } /** @@ -176,36 +161,6 @@ export function pointCenter

(a: P, b: P): P { return pointFrom((a[0] + b[0]) / 2, (a[1] + b[1]) / 2); } -/** - * Add together two points by their coordinates like you'd apply a translation - * to a point by a vector. - * - * @param a One point to act as a basis - * @param b The other point to act like the vector to translate by - * @returns - */ -export function pointAdd( - a: Point, - b: Point, -): Point { - return pointFrom(a[0] + b[0], a[1] + b[1]); -} - -/** - * Subtract a point from another point like you'd translate a point by an - * invese vector. - * - * @param a The point to translate - * @param b The point which will act like a vector - * @returns The resulting point - */ -export function pointSubtract( - a: Point, - b: Point, -): Point { - return pointFrom(a[0] - b[0], a[1] - b[1]); -} - /** * Calculate the distance between two points. * diff --git a/packages/math/rectangle.ts b/packages/math/rectangle.ts new file mode 100644 index 000000000..7dde15ded --- /dev/null +++ b/packages/math/rectangle.ts @@ -0,0 +1,23 @@ +import { pointFrom } from "./point"; +import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; +import type { GlobalPoint, LineSegment, LocalPoint, Rectangle } from "./types"; + +export function rectangle

( + topLeft: P, + bottomRight: P, +): Rectangle

{ + return [topLeft, bottomRight] as Rectangle

; +} + +export function rectangleIntersectLineSegment< + Point extends LocalPoint | GlobalPoint, +>(r: Rectangle, l: LineSegment): Point[] { + return [ + lineSegment(r[0], pointFrom(r[1][0], r[0][1])), + lineSegment(pointFrom(r[1][0], r[0][1]), r[1]), + lineSegment(r[1], pointFrom(r[0][0], r[1][1])), + lineSegment(pointFrom(r[0][0], r[1][1]), r[0]), + ] + .map((s) => lineSegmentIntersectionPoints(l, s)) + .filter((i): i is Point => !!i); +} diff --git a/packages/math/segment.test.ts b/packages/math/segment.test.ts new file mode 100644 index 000000000..4237a3c85 --- /dev/null +++ b/packages/math/segment.test.ts @@ -0,0 +1,21 @@ +import { pointFrom } from "./point"; +import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; + +describe("line-segment intersections", () => { + it("should correctly detect intersection", () => { + expect( + lineSegmentIntersectionPoints( + lineSegment(pointFrom(0, 0), pointFrom(5, 0)), + lineSegment(pointFrom(2, -2), pointFrom(3, 2)), + ), + ).toEqual(pointFrom(2.5, 0)); + }); + it("should correctly detect non-intersection", () => { + expect( + lineSegmentIntersectionPoints( + lineSegment(pointFrom(0, 0), pointFrom(5, 0)), + lineSegment(pointFrom(3, 1), pointFrom(4, 4)), + ), + ).toEqual(null); + }); +}); diff --git a/packages/math/segment.ts b/packages/math/segment.ts index 6c0c2de34..60943aacb 100644 --- a/packages/math/segment.ts +++ b/packages/math/segment.ts @@ -1,3 +1,4 @@ +import { line, linesIntersectAt } from "./line"; import { isPoint, pointCenter, @@ -27,14 +28,6 @@ export function lineSegment

( return [a, b] as LineSegment

; } -export function lineSegmentFromPointArray

( - pointArray: P[], -): LineSegment

| undefined { - return pointArray.length === 2 - ? lineSegment

(pointArray[0], pointArray[1]) - : undefined; -} - /** * * @param segment @@ -156,3 +149,26 @@ export const distanceToLineSegment = ( const dy = y - yy; return Math.sqrt(dx * dx + dy * dy); }; + +/** + * Returns the intersection point of a segment and a line + * + * @param l + * @param s + * @returns + */ +export function lineSegmentIntersectionPoints< + Point extends GlobalPoint | LocalPoint, +>(l: LineSegment, s: LineSegment): Point | null { + const candidate = linesIntersectAt(line(l[0], l[1]), line(s[0], s[1])); + + if ( + !candidate || + !pointOnLineSegment(candidate, s) || + !pointOnLineSegment(candidate, l) + ) { + return null; + } + + return candidate; +} diff --git a/packages/math/types.ts b/packages/math/types.ts index 138a44bc0..a2a575bd7 100644 --- a/packages/math/types.ts +++ b/packages/math/types.ts @@ -85,6 +85,13 @@ export type Triangle

= [ _brand: "excalimath__triangle"; }; +/** + * A rectangular shape represented by 4 points at its corners + */ +export type Rectangle

diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/utils/restore.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/utils/restore.mdx
index 3f2546483..2b4df2ccf 100644
--- a/dev-docs/docs/@excalidraw/excalidraw/api/utils/restore.mdx
+++ b/dev-docs/docs/@excalidraw/excalidraw/api/utils/restore.mdx
@@ -31,7 +31,7 @@ You can pass `null` / `undefined` if not applicable.
 restoreElements(
   elements: ImportedDataState["elements"],
  localElements: ExcalidrawElement[] | null | undefined): ExcalidrawElement[],
  - opts: { refreshDimensions?: boolean, repairBindings?: boolean }
+ opts: { refreshDimensions?: boolean, repairBindings?: boolean, normalizeIndices?: boolean }
)
@@ -51,8 +51,9 @@ The extra optional parameter to configure restored elements. It has the followin | Prop | Type | Description| | --- | --- | ------| -| `refreshDimensions` | `boolean` | Indicates whether we should also `recalculate` text element dimensions. Since this is a potentially costly operation, you may want to disable it if you restore elements in tight loops, such as during collaboration. | -| `repairBindings` |`boolean` | Indicates whether the `bindings` for the elements should be repaired. This is to make sure there are no containers with non existent bound text element id and no bound text elements with non existent container id. | +| `refreshDimensions` | `boolean` | Indicates whether we should also _recalculate_ text element dimensions. Since this is a potentially costly operation, you may want to disable it if you restore elements in tight loops, such as during collaboration. | +| `repairBindings` |`boolean` | Indicates whether the _bindings_ for the elements should be repaired. This is to make sure there are no containers with non existent bound text element id and no bound text elements with non existent container id. | +| `normalizeIndices` |`boolean` | Indicates whether _fractional indices_ for the elements should be normalized. This is to prevent possible issues caused by using stale (too old, too long) indices. | **_How to use_** @@ -73,7 +74,7 @@ restore( data: ImportedDataState,
  localAppState: Partial<AppState> | null | undefined,
  localElements: ExcalidrawElement[] | null | undefined
): DataState
- opts: { refreshDimensions?: boolean, repairBindings?: boolean }
+ opts: { refreshDimensions?: boolean, repairBindings?: boolean, normalizeIndices?: boolean }
) diff --git a/dev-docs/docs/@excalidraw/excalidraw/development.mdx b/dev-docs/docs/@excalidraw/excalidraw/development.mdx index 3c405a7d9..52ec484aa 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/development.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/development.mdx @@ -13,18 +13,18 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the 1. Install the dependencies ```bash - cd packages/excalidraw && yarn + yarn ``` 2. Start the example app ```bash - yarn start + yarn start:example ``` [http://localhost:3001](http://localhost:3001) will open in your default browser. - - The example is same as the [codesandbox example](https://ehlz3.csb.app/) + + This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. ## Releasing diff --git a/dev-docs/docs/@excalidraw/excalidraw/faq.mdx b/dev-docs/docs/@excalidraw/excalidraw/faq.mdx index e9c6a81d1..aea9ce788 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/faq.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/faq.mdx @@ -17,11 +17,9 @@ We strongly recommend turning it off. You can follow the steps below on how to d
2. Once opened, look for **Aggressively Block Fingerprinting** - ![Aggressive block fingerprinting](../../assets/aggressive-block-fingerprint.png) 3. Switch to **Block Fingerprinting** - ![Block filtering](../../assets/block-fingerprint.png) 4. Thats all. All text elements should be fixed now 🎉 diff --git a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx index d8ddd59c3..2ff6c2d2d 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx @@ -1,16 +1,12 @@ # Installation -**Excalidraw** is published to npm as a component you can directly embed in your projects. +**Excalidraw** is exported as a component to be directly embedded in your project. -Using `npm`: +Use `npm` or `yarn` to install the package. ```bash npm install react react-dom @excalidraw/excalidraw -``` - -or `yarn`: - -```bash +# or yarn add react react-dom @excalidraw/excalidraw ``` @@ -20,24 +16,40 @@ yarn add react react-dom @excalidraw/excalidraw ::: -### Static assets +### Self-hosting fonts -Excalidraw depends on assets such as localization files (if you opt to use them), fonts, and others. +By default, Excalidraw will try to download all the used fonts from the [CDN](https://esm.run/@excalidraw/excalidraw/dist/prod). -By default these assets are loaded from a public CDN [`https://unpkg.com/@excalidraw/excalidraw/dist/`](https://unpkg.com/@excalidraw/excalidraw/dist), so you don't need to do anything on your end. - -However, if you want to host these files yourself, you can find them in your `node_modules/@excalidraw/excalidraw/dist` directory, in folders `excalidraw-assets` (for production) and `excalidraw-assets-dev` (for development). - -Copy these folders to your static assets directory, and add a `window.EXCALIDRAW_ASSET_PATH` variable in your `index.html` or `index.js` entry file pointing to your public assets path (relative). For example, if you serve your assets from the root of your hostname, you would do: +For self-hosting purposes, you'll have to copy the content of the folder `node_modules/@excalidraw/excalidraw/dist/prod/fonts` to the path where your assets should be served from (i.e. `public/` directory in your project). In that case, you should also set `window.EXCALIDRAW_ASSET_PATH` to the very same path, i.e. `/` in case it's in the root: ```js window.EXCALIDRAW_ASSET_PATH = "/"; ``` +or, if you serve your assets from the root of your CDN, you would do: + +```js +// Vanilla + + + +``` + +or, if you prefer the path to be dynamicly set based on the `location.origin`, you could do the following: + +```jsx +// Next.js + +``` + ### Dimensions of Excalidraw Excalidraw takes _100%_ of `width` and `height` of the containing block so make sure the container in which you render Excalidraw has non zero dimensions. -### Demo +## Demo -[Try here](https://codesandbox.io/s/excalidraw-ehlz3). +Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. diff --git a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx index bb2cf597c..62bbbcca5 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx @@ -128,11 +128,10 @@ If you are using `pages router` then importing the wrapper dynamically would wor +{/* Link should be updated to point to the latest! */} +Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs.vercel.app/). -Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/excalidraw/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs-gh6smrdnq-excalidraw.vercel.app/). - - -The `types` are available at `@excalidraw/excalidraw/types`, you can view [example for typescript](https://codesandbox.io/s/excalidraw-types-9h2dm) +The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example for details. ### Preact @@ -157,27 +156,9 @@ Since Vite removes env variables by default, you can update the vite config to e ## Browser -To use it in a browser directly: +To use it Excalidraw in a browser directly, use the following setup :point_down: -For development use :point_down: - -```js - -``` - -For production use :point_down: - -```js - -``` - -You will need to make sure `react`, `react-dom` is available as shown in the below example. For prod please use the production versions of `react`, `react-dom`. +> **Note**: We rely on import maps to de-duplicate `react`, `react-dom` and `react/jsx-runtime` versions. import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; @@ -191,13 +172,23 @@ import TabItem from "@theme/TabItem"; Excalidraw in browser - - - - + + + + @@ -214,6 +205,14 @@ import TabItem from "@theme/TabItem"; ```js showLineNumbers +// See https://www.npmjs.com/package/@excalidraw/excalidraw documentation. +import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.1/dist/dev/index.js?external=react,react-dom'; +import React from "https://esm.sh/react@19.0.0"; +import ReactDOM from "https://esm.sh/react-dom@19.0.0" + +window.ExcalidrawLib = ExcalidrawLib; +console.log("Excalidraw library", ExcalidrawLib); + const App = () => { return React.createElement( React.Fragment, @@ -236,4 +235,4 @@ root.render(React.createElement(App)); -You can try it out [here](https://codesandbox.io/p/sandbox/excalidraw-in-browser-tlqom?file=%2Findex.html%3A1%2C10). +You can try it out [here](https://jsfiddle.net/64y130L8/1/). diff --git a/dev-docs/docusaurus.config.js b/dev-docs/docusaurus.config.js index 7899df164..4e8d75800 100644 --- a/dev-docs/docusaurus.config.js +++ b/dev-docs/docusaurus.config.js @@ -149,6 +149,29 @@ const config = { systemvars: true, }, ], + function () { + return { + name: "disable-fully-specified-error", + configureWebpack() { + return { + module: { + rules: [ + { + test: /\.m?js$/, + resolve: { + fullySpecified: false, + }, + }, + ], + }, + optimization: { + // disable terser minification + minimize: false, + }, + }; + }, + }; + }, ], }; diff --git a/dev-docs/package.json b/dev-docs/package.json index da2e5e48a..8cbd6d232 100644 --- a/dev-docs/package.json +++ b/dev-docs/package.json @@ -18,13 +18,13 @@ "@docusaurus/core": "2.2.0", "@docusaurus/preset-classic": "2.2.0", "@docusaurus/theme-live-codeblock": "2.2.0", - "@excalidraw/excalidraw": "0.17.6", + "@excalidraw/excalidraw": "0.18.0-rc.5", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "docusaurus-plugin-sass": "0.2.3", "prism-react-renderer": "^1.3.5", - "react": "19.0.0", - "react-dom": "19.0.0", + "react": "18.2.0", + "react-dom": "18.2.0", "sass": "1.57.1" }, "devDependencies": { diff --git a/dev-docs/src/theme/ReactLiveScope/index.js b/dev-docs/src/theme/ReactLiveScope/index.js index 7464db22f..4fa715f46 100644 --- a/dev-docs/src/theme/ReactLiveScope/index.js +++ b/dev-docs/src/theme/ReactLiveScope/index.js @@ -3,11 +3,18 @@ import ExecutionEnvironment from "@docusaurus/ExecutionEnvironment"; import initialData from "@site/src/initialData"; import { useColorMode } from "@docusaurus/theme-common"; +import "@excalidraw/excalidraw/index.css"; + let ExcalidrawComp = {}; if (ExecutionEnvironment.canUseDOM) { ExcalidrawComp = require("@excalidraw/excalidraw"); } const Excalidraw = React.forwardRef((props, ref) => { + if (!window.EXCALIDRAW_ASSET_PATH) { + window.EXCALIDRAW_ASSET_PATH = + "https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.5/dist/prod/"; + } + const { colorMode } = useColorMode(); return ; }); diff --git a/dev-docs/yarn.lock b/dev-docs/yarn.lock index 5b684e32b..6e54d978b 100644 --- a/dev-docs/yarn.lock +++ b/dev-docs/yarn.lock @@ -1207,6 +1207,13 @@ dependencies: regenerator-runtime "^0.13.4" +"@babel/runtime@^7.13.10": + version "7.26.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433" + integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg== + dependencies: + regenerator-runtime "^0.14.0" + "@babel/template@^7.12.7", "@babel/template@^7.18.6": version "7.18.6" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.6.tgz#1283f4993e00b929d6e2d3c72fdc9168a2977a31" @@ -1258,6 +1265,16 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" +"@braintree/sanitize-url@6.0.2": + version "6.0.2" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.2.tgz#6110f918d273fe2af8ea1c4398a88774bb9fc12f" + integrity sha512-Tbsj02wXCbqGmzdnXNk0SOF19ChhRU70BsroIi4Pm6Ehp56in6vch94mfbdQ17DozxkL3BAVjbZ4Qc1a0HFRAg== + +"@braintree/sanitize-url@^6.0.1": + version "6.0.4" + resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" + integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== + "@colors/colors@1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" @@ -1718,10 +1735,86 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@excalidraw/excalidraw@0.17.6": - version "0.17.6" - resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.17.6.tgz#5fd208ce69d33ca712d1804b50d7d06d5c46ac4d" - integrity sha512-fyCl+zG/Z5yhHDh5Fq2ZGmphcrALmuOdtITm8gN4d8w4ntnaopTXcTfnAAaU3VleDC6LhTkoLOTG6P5kgREiIg== +"@excalidraw/excalidraw@0.18.0-rc.5": + version "0.18.0-rc.5" + resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0-rc.5.tgz#c55598e01808693702251322e59bf9dba931b6e0" + integrity sha512-f6Z6cWlx+FWl1nxCu5F6OdKm9ooV/FPjndjIfFhGLVyERKATXhuNwZUHWwqsEW+SIGmiPG2515NG9KIOhjGd5g== + dependencies: + "@braintree/sanitize-url" "6.0.2" + "@excalidraw/laser-pointer" "1.3.1" + "@excalidraw/mermaid-to-excalidraw" "1.1.2" + "@excalidraw/random-username" "1.1.0" + "@radix-ui/react-popover" "1.0.3" + "@radix-ui/react-tabs" "1.0.2" + browser-fs-access "0.29.1" + canvas-roundrect-polyfill "0.0.1" + clsx "1.1.1" + cross-env "7.0.3" + es6-promise-pool "2.5.0" + fractional-indexing "3.2.0" + fuzzy "0.1.3" + image-blob-reduce "3.0.1" + jotai "2.11.0" + jotai-scope "0.7.2" + lodash.debounce "4.0.8" + lodash.throttle "4.1.1" + nanoid "3.3.3" + open-color "1.9.1" + pako "2.0.3" + perfect-freehand "1.2.0" + pica "7.1.1" + png-chunk-text "1.0.0" + png-chunks-encode "1.0.0" + png-chunks-extract "1.0.0" + points-on-curve "1.0.1" + pwacompat "2.0.17" + roughjs "4.6.4" + sass "1.51.0" + tunnel-rat "0.1.2" + +"@excalidraw/laser-pointer@1.3.1": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@excalidraw/laser-pointer/-/laser-pointer-1.3.1.tgz#7c40836598e8e6ad91f01057883ed8b88fb9266c" + integrity sha512-psA1z1N2qeAfsORdXc9JmD2y4CmDwmuMRxnNdJHZexIcPwaNEyIpNcelw+QkL9rz9tosaN9krXuKaRqYpRAR6g== + +"@excalidraw/markdown-to-text@0.1.2": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@excalidraw/markdown-to-text/-/markdown-to-text-0.1.2.tgz#1703705e7da608cf478f17bfe96fb295f55a23eb" + integrity sha512-1nDXBNAojfi3oSFwJswKREkFm5wrSjqay81QlyRv2pkITG/XYB5v+oChENVBQLcxQwX4IUATWvXM5BcaNhPiIg== + +"@excalidraw/mermaid-to-excalidraw@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@excalidraw/mermaid-to-excalidraw/-/mermaid-to-excalidraw-1.1.2.tgz#74d9507971976a7d3d960a1b2e8fb49a9f1f0d22" + integrity sha512-hAFv/TTIsOdoy0dL5v+oBd297SQ+Z88gZ5u99fCIFuEMHfQuPgLhU/ztKhFSTs7fISwVo6fizny/5oQRR3d4tQ== + dependencies: + "@excalidraw/markdown-to-text" "0.1.2" + mermaid "10.9.3" + nanoid "4.0.2" + +"@excalidraw/random-username@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@excalidraw/random-username/-/random-username-1.1.0.tgz#6f388d6a9708cf655b8c9c6aa3fa569ee71ecf0f" + integrity sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA== + +"@floating-ui/core@^0.7.3": + version "0.7.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" + integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== + +"@floating-ui/dom@^0.5.3": + version "0.5.4" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" + integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== + dependencies: + "@floating-ui/core" "^0.7.3" + +"@floating-ui/react-dom@0.7.2": + version "0.7.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" + integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== + dependencies: + "@floating-ui/dom" "^0.5.3" + use-isomorphic-layout-effect "^1.1.1" "@hapi/hoek@^9.0.0": version "9.3.0" @@ -1882,6 +1975,246 @@ resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.21.tgz#5de5a2385a35309427f6011992b544514d559aa1" integrity sha512-a5Sab1C4/icpTZVzZc5Ghpz88yQtGOyNqYXcZgOssB2uuAr+wF/MvN6bgtW32q7HHrvBki+BsZ0OuNv6EV3K9g== +"@radix-ui/primitive@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.0.0.tgz#e1d8ef30b10ea10e69c76e896f608d9276352253" + integrity sha512-3e7rn8FDMin4CgeL7Z/49smCA3rFYY3Ha2rUQ7HRWFadS5iCRw08ZgVT1LaNTCNqgvrUiyczLflrVrF0SRQtNA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-arrow@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" + integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + +"@radix-ui/react-collection@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5" + integrity sha512-uuiFbs+YCKjn3X1DTSx9G7BHApu4GHbi3kgiwsnFUbOKCrwejAJv4eE4Vc8C0Oaxt9T0aV4ox0WCOdx+39Xo+g== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-slot" "1.0.1" + +"@radix-ui/react-compose-refs@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.0.0.tgz#37595b1f16ec7f228d698590e78eeed18ff218ae" + integrity sha512-0KaSv6sx787/hK3eF53iOkiSLwAGlFMx5lotrqD2pTjB18KbybKoEIgkNZTKC60YECDQTKGTRcDBILwZVqVKvA== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-context@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" + integrity sha512-1pVM9RfOQ+n/N5PJK33kRSKsr1glNxomxONs5c49MliinBY6Yw2Q995qfBUUo0/Mbg05B/sGA0gkgPI7kmSHBg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-direction@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" + integrity sha512-2HV05lGUgYcA6xgLQ4BKPDmtL+QbIZYH5fCOTAOOcJ5O0QbWS3i9lKaurLzliYUDhORI2Qr3pyjhJh44lKA3rQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-dismissable-layer@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" + integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-escape-keydown" "1.0.2" + +"@radix-ui/react-focus-guards@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" + integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-focus-scope@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" + integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + +"@radix-ui/react-id@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e" + integrity sha512-Q6iAB/U7Tq3NTolBBQbHTgclPmGWE3OlktGGqrClPozSw4vkQ1DfQAOtzgRPecKsMdJINE05iaoDUG8tRzCBjw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.0" + +"@radix-ui/react-popover@1.0.3": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe" + integrity sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-dismissable-layer" "1.0.2" + "@radix-ui/react-focus-guards" "1.0.0" + "@radix-ui/react-focus-scope" "1.0.1" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-popper" "1.1.0" + "@radix-ui/react-portal" "1.0.1" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-slot" "1.0.1" + "@radix-ui/react-use-controllable-state" "1.0.0" + aria-hidden "^1.1.1" + react-remove-scroll "2.5.5" + +"@radix-ui/react-popper@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60" + integrity sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@floating-ui/react-dom" "0.7.2" + "@radix-ui/react-arrow" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/react-use-rect" "1.0.0" + "@radix-ui/react-use-size" "1.0.0" + "@radix-ui/rect" "1.0.0" + +"@radix-ui/react-portal@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" + integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "1.0.1" + +"@radix-ui/react-presence@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" + integrity sha512-A+6XEvN01NfVWiKu38ybawfHsBjWum42MRPnEuqPsBZ4eV7e/7K321B5VgYMPv3Xx5An6o1/l9ZuDBgmcmWK3w== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.0.0" + +"@radix-ui/react-primitive@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" + integrity sha512-fHbmislWVkZaIdeF6GZxF0A/NH/3BjrGIYj+Ae6eTmTCr7EB0RQAAVEiqsXK6p3/JcRqVSBQoceZroj30Jj3XA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-slot" "1.0.1" + +"@radix-ui/react-roving-focus@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de" + integrity sha512-HLK+CqD/8pN6GfJm3U+cqpqhSKYAWiOJDe+A+8MfxBnOue39QEeMa43csUn2CXCHQT0/mewh1LrrG4tfkM9DMA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-collection" "1.0.1" + "@radix-ui/react-compose-refs" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-slot@1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.1.tgz#e7868c669c974d649070e9ecbec0b367ee0b4d81" + integrity sha512-avutXAFL1ehGvAXtPquu0YK5oz6ctS474iM3vNGQIkswrVhdrS52e3uoMQBzZhNRAIE0jBnUyXWNmSjGHhCFcw== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-compose-refs" "1.0.0" + +"@radix-ui/react-tabs@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz#8f5ec73ca41b151a413bdd6e00553408ff34ce07" + integrity sha512-gOUwh+HbjCuL0UCo8kZ+kdUEG8QtpdO4sMQduJ34ZEz0r4922g9REOBM+vIsfwtGxSug4Yb1msJMJYN2Bk8TpQ== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/primitive" "1.0.0" + "@radix-ui/react-context" "1.0.0" + "@radix-ui/react-direction" "1.0.0" + "@radix-ui/react-id" "1.0.0" + "@radix-ui/react-presence" "1.0.0" + "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-roving-focus" "1.0.2" + "@radix-ui/react-use-controllable-state" "1.0.0" + +"@radix-ui/react-use-callback-ref@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.0.tgz#9e7b8b6b4946fe3cbe8f748c82a2cce54e7b6a90" + integrity sha512-GZtyzoHz95Rhs6S63D2t/eqvdFCm7I+yHMLVQheKM7nBD8mbZIt+ct1jz4536MDnaOGKIxynJ8eHTkVGVVkoTg== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-controllable-state@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" + integrity sha512-FohDoZvk3mEXh9AWAVyRTYR4Sq7/gavuofglmiXB2g1aKyboUD4YtgWxKj8O5n+Uak52gXQ4wKz5IFST4vtJHg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.0" + +"@radix-ui/react-use-escape-keydown@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" + integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-callback-ref" "1.0.0" + +"@radix-ui/react-use-layout-effect@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" + integrity sha512-6Tpkq+R6LOlmQb1R5NNETLG0B4YP0wc+klfXafpUCj6JGyaUc8il7/kUZ7m59rGbXGczE9Bs+iz2qloqsZBduQ== + dependencies: + "@babel/runtime" "^7.13.10" + +"@radix-ui/react-use-rect@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" + integrity sha512-TB7pID8NRMEHxb/qQJpvSt3hQU4sqNPM1VCTjTRjEOa7cEop/QMuq8S6fb/5Tsz64kqSvB9WnwsDHtjnrM9qew== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/rect" "1.0.0" + +"@radix-ui/react-use-size@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771" + integrity sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg== + dependencies: + "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.0.0" + +"@radix-ui/rect@1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" + integrity sha512-d0O68AYy/9oeEy1DdC07bz1/ZXX+DqCskRd3i4JzLSTXwefzaepQrKjXC7aNM8lTHjFLDO0pDgaEiQ7jEk+HVg== + dependencies: + "@babel/runtime" "^7.13.10" + "@sideway/address@^4.1.3": version "4.1.4" resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.4.tgz#03dccebc6ea47fdc226f7d3d1ad512955d4783f0" @@ -2064,6 +2397,30 @@ dependencies: "@types/node" "*" +"@types/d3-scale-chromatic@^3.0.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#dc6d4f9a98376f18ea50bad6c39537f1b5463c39" + integrity sha512-iWMJgwkK7yTRmWqRB5plb1kadXyQ5Sj8V/zYlFGMUBbIPKQScw+Dku9cAAMgJG+z5GYDoMjWGLVOvjghDEFnKQ== + +"@types/d3-scale@^4.0.3": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/d3-scale/-/d3-scale-4.0.9.tgz#57a2f707242e6fe1de81ad7bfcccaaf606179afb" + integrity sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw== + dependencies: + "@types/d3-time" "*" + +"@types/d3-time@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/d3-time/-/d3-time-3.0.4.tgz#8472feecd639691450dd8000eb33edd444e1323f" + integrity sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g== + +"@types/debug@^4.0.0": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917" + integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ== + dependencies: + "@types/ms" "*" + "@types/eslint-scope@^3.7.3": version "3.7.4" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" @@ -2150,6 +2507,11 @@ resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw== +"@types/ms@*": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" + integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== + "@types/node@*": version "18.6.1" resolved "https://registry.yarnpkg.com/@types/node/-/node-18.6.1.tgz#828e4785ccca13f44e2fb6852ae0ef11e3e20ba5" @@ -2590,6 +2952,13 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== +aria-hidden@^1.1.1: + version "1.2.4" + resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" + integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== + dependencies: + tslib "^2.0.0" + array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" @@ -2803,6 +3172,11 @@ braces@~3.0.2: dependencies: fill-range "^7.0.1" +browser-fs-access@0.29.1: + version "0.29.1" + resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.29.1.tgz#8a9794c73cf86b9aec74201829999c597128379c" + integrity sha512-LSvVX5e21LRrXqVMhqtAwj5xPgDb+fXAIH80NsnCQ9xuZPs2xWsOREi24RKgZa1XOiQRbcmVrv87+ulOKsgjxw== + browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.18.1, browserslist@^4.20.2, browserslist@^4.20.3, browserslist@^4.21.2: version "4.21.2" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.2.tgz#59a400757465535954946a400b841ed37e2b4ecf" @@ -2899,6 +3273,11 @@ caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001366: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001370.tgz#0a30d4f20d38b9e108cc5ae7cc62df9fe66cd5ba" integrity sha512-3PDmaP56wz/qz7G508xzjx8C+MC2qEm4SYhSEzC9IBROo+dGXFWRuaXkWti0A9tuI00g+toiriVqxtWMgl350g== +canvas-roundrect-polyfill@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/canvas-roundrect-polyfill/-/canvas-roundrect-polyfill-0.0.1.tgz#70bf107ebe2037f26d839d7f809a26f4a95f5696" + integrity sha512-yWq+R3U3jE+coOeEb3a3GgE2j/0MMiDKM/QpLb6h9ihf5fGY9UXtvK9o4vNqjWXoZz7/3EaSVU3IX53TvFFUOw== + ccount@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" @@ -2931,6 +3310,11 @@ character-entities@^1.0.0: resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== +character-entities@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-2.0.2.tgz#2d09c2e72cd9523076ccb21157dff66ad43fcc22" + integrity sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ== + character-reference-invalid@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" @@ -3033,6 +3417,11 @@ clone-response@^1.0.2: dependencies: mimic-response "^1.0.0" +clsx@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" + integrity sha512-6/bPho624p3S2pMyvP5kKBPXnI3ufHLObBFCfgx+LkeR5lg2XYy2hqZqUf45ypD8COn2bhgGJSUE+l5dhNBieA== + clsx@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12" @@ -3087,6 +3476,11 @@ comma-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== +commander@7, commander@^7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" + integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== + commander@^2.20.0: version "2.20.3" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" @@ -3097,11 +3491,6 @@ commander@^5.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@^7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" - integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== - commander@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" @@ -3248,6 +3637,13 @@ core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== +cose-base@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" + integrity sha512-s9whTXInMSgAp/NVXVNuVxVKzGH2qck3aQlVHxDCdAEPgtMKwc4Wq6/QKhgdEdgbLSi9rBTAcPoRa6JpiG4ksg== + dependencies: + layout-base "^1.0.0" + cosmiconfig@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-6.0.0.tgz#da4fee853c52f6b1e6935f41c1a2fc50bd4a9982" @@ -3270,6 +3666,18 @@ cosmiconfig@^7.0.0, cosmiconfig@^7.0.1: path-type "^4.0.0" yaml "^1.10.0" +crc-32@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-0.3.0.tgz#6a3d3687f5baec41f7e9b99fe1953a2e5d19775e" + integrity sha512-kucVIjOmMc1f0tv53BJ/5WIX+MGLcKuoBhnGqQrgKJNqLByb/sVMWfW/Aw6hw0jgcqjJ2pi9E5y32zOIpaUlsA== + +cross-env@7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + cross-fetch@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.5.tgz#e1389f44d9e7ba767907f7af8454787952ab534f" @@ -3277,6 +3685,15 @@ cross-fetch@^3.1.5: dependencies: node-fetch "2.6.7" +cross-spawn@^7.0.1: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" @@ -3435,6 +3852,302 @@ csstype@^3.0.2: resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.0.tgz#4ddcac3718d787cf9df0d1b7d15033925c8f29f2" integrity sha512-uX1KG+x9h5hIJsaKR9xHUeUraxf8IODOwq9JLNPq6BwB04a/xgpq3rcx47l5BZu5zBPlgD342tdke3Hom/nJRA== +cytoscape-cose-bilkent@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cytoscape-cose-bilkent/-/cytoscape-cose-bilkent-4.1.0.tgz#762fa121df9930ffeb51a495d87917c570ac209b" + integrity sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ== + dependencies: + cose-base "^1.0.0" + +cytoscape@^3.28.1: + version "3.31.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.1.tgz#29b12cac715fbb2aacc50cdf5cf1467aadde9c00" + integrity sha512-Hx5Mtb1+hnmAKaZZ/7zL1Y5HTFYOjdDswZy/jD+1WINRU8KVi1B7+vlHdsTwY+VCFucTreoyu1RDzQJ9u0d2Hw== + +"d3-array@1 - 2": + version "2.12.1" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-2.12.1.tgz#e20b41aafcdffdf5d50928004ececf815a465e81" + integrity sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ== + dependencies: + internmap "^1.0.0" + +"d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3, d3-array@^3.2.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.2.4.tgz#15fec33b237f97ac5d7c986dc77da273a8ed0bb5" + integrity sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg== + dependencies: + internmap "1 - 2" + +d3-axis@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-3.0.0.tgz#c42a4a13e8131d637b745fc2973824cfeaf93322" + integrity sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw== + +d3-brush@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-3.0.0.tgz#6f767c4ed8dcb79de7ede3e1c0f89e63ef64d31c" + integrity sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "3" + d3-transition "3" + +d3-chord@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-chord/-/d3-chord-3.0.1.tgz#d156d61f485fce8327e6abf339cb41d8cbba6966" + integrity sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g== + dependencies: + d3-path "1 - 3" + +"d3-color@1 - 3", d3-color@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-3.1.0.tgz#395b2833dfac71507f12ac2f7af23bf819de24e2" + integrity sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA== + +d3-contour@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-contour/-/d3-contour-4.0.2.tgz#bb92063bc8c5663acb2422f99c73cbb6c6ae3bcc" + integrity sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA== + dependencies: + d3-array "^3.2.0" + +d3-delaunay@6: + version "6.0.4" + resolved "https://registry.yarnpkg.com/d3-delaunay/-/d3-delaunay-6.0.4.tgz#98169038733a0a5babbeda55054f795bb9e4a58b" + integrity sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A== + dependencies: + delaunator "5" + +"d3-dispatch@1 - 3", d3-dispatch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-3.0.1.tgz#5fc75284e9c2375c36c839411a0cf550cbfc4d5e" + integrity sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg== + +"d3-drag@2 - 3", d3-drag@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-3.0.0.tgz#994aae9cd23c719f53b5e10e3a0a6108c69607ba" + integrity sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg== + dependencies: + d3-dispatch "1 - 3" + d3-selection "3" + +"d3-dsv@1 - 3", d3-dsv@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-dsv/-/d3-dsv-3.0.1.tgz#c63af978f4d6a0d084a52a673922be2160789b73" + integrity sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q== + dependencies: + commander "7" + iconv-lite "0.6" + rw "1" + +"d3-ease@1 - 3", d3-ease@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-3.0.1.tgz#9658ac38a2140d59d346160f1f6c30fda0bd12f4" + integrity sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w== + +d3-fetch@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-fetch/-/d3-fetch-3.0.1.tgz#83141bff9856a0edb5e38de89cdcfe63d0a60a22" + integrity sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw== + dependencies: + d3-dsv "1 - 3" + +d3-force@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-force/-/d3-force-3.0.0.tgz#3e2ba1a61e70888fe3d9194e30d6d14eece155c4" + integrity sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg== + dependencies: + d3-dispatch "1 - 3" + d3-quadtree "1 - 3" + d3-timer "1 - 3" + +"d3-format@1 - 3", d3-format@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-3.1.0.tgz#9260e23a28ea5cb109e93b21a06e24e2ebd55641" + integrity sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA== + +d3-geo@3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/d3-geo/-/d3-geo-3.1.1.tgz#6027cf51246f9b2ebd64f99e01dc7c3364033a4d" + integrity sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q== + dependencies: + d3-array "2.5.0 - 3" + +d3-hierarchy@3: + version "3.1.2" + resolved "https://registry.yarnpkg.com/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz#b01cd42c1eed3d46db77a5966cf726f8c09160c6" + integrity sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA== + +"d3-interpolate@1 - 3", "d3-interpolate@1.2.0 - 3", d3-interpolate@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-interpolate/-/d3-interpolate-3.0.1.tgz#3c47aa5b32c5b3dfb56ef3fd4342078a632b400d" + integrity sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g== + dependencies: + d3-color "1 - 3" + +d3-path@1: + version "1.0.9" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-1.0.9.tgz#48c050bb1fe8c262493a8caf5524e3e9591701cf" + integrity sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg== + +"d3-path@1 - 3", d3-path@3, d3-path@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-3.1.0.tgz#22df939032fb5a71ae8b1800d61ddb7851c42526" + integrity sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ== + +d3-polygon@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-polygon/-/d3-polygon-3.0.1.tgz#0b45d3dd1c48a29c8e057e6135693ec80bf16398" + integrity sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg== + +"d3-quadtree@1 - 3", d3-quadtree@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-quadtree/-/d3-quadtree-3.0.1.tgz#6dca3e8be2b393c9a9d514dabbd80a92deef1a4f" + integrity sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw== + +d3-random@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-3.0.1.tgz#d4926378d333d9c0bfd1e6fa0194d30aebaa20f4" + integrity sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ== + +d3-sankey@^0.12.3: + version "0.12.3" + resolved "https://registry.yarnpkg.com/d3-sankey/-/d3-sankey-0.12.3.tgz#b3c268627bd72e5d80336e8de6acbfec9d15d01d" + integrity sha512-nQhsBRmM19Ax5xEIPLMY9ZmJ/cDvd1BG3UVvt5h3WRxKg5zGRbvnteTyWAbzeSvlh3tW7ZEmq4VwR5mB3tutmQ== + dependencies: + d3-array "1 - 2" + d3-shape "^1.2.0" + +d3-scale-chromatic@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz#34c39da298b23c20e02f1a4b239bd0f22e7f1314" + integrity sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ== + dependencies: + d3-color "1 - 3" + d3-interpolate "1 - 3" + +d3-scale@4: + version "4.0.2" + resolved "https://registry.yarnpkg.com/d3-scale/-/d3-scale-4.0.2.tgz#82b38e8e8ff7080764f8dcec77bd4be393689396" + integrity sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ== + dependencies: + d3-array "2.10.0 - 3" + d3-format "1 - 3" + d3-interpolate "1.2.0 - 3" + d3-time "2.1.1 - 3" + d3-time-format "2 - 4" + +"d3-selection@2 - 3", d3-selection@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-3.0.0.tgz#c25338207efa72cc5b9bd1458a1a41901f1e1b31" + integrity sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ== + +d3-shape@3: + version "3.2.0" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-3.2.0.tgz#a1a839cbd9ba45f28674c69d7f855bcf91dfc6a5" + integrity sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA== + dependencies: + d3-path "^3.1.0" + +d3-shape@^1.2.0: + version "1.3.7" + resolved "https://registry.yarnpkg.com/d3-shape/-/d3-shape-1.3.7.tgz#df63801be07bc986bc54f63789b4fe502992b5d7" + integrity sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw== + dependencies: + d3-path "1" + +"d3-time-format@2 - 4", d3-time-format@4: + version "4.1.0" + resolved "https://registry.yarnpkg.com/d3-time-format/-/d3-time-format-4.1.0.tgz#7ab5257a5041d11ecb4fe70a5c7d16a195bb408a" + integrity sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg== + dependencies: + d3-time "1 - 3" + +"d3-time@1 - 3", "d3-time@2.1.1 - 3", d3-time@3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-3.1.0.tgz#9310db56e992e3c0175e1ef385e545e48a9bb5c7" + integrity sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q== + dependencies: + d3-array "2 - 3" + +"d3-timer@1 - 3", d3-timer@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-3.0.1.tgz#6284d2a2708285b1abb7e201eda4380af35e63b0" + integrity sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA== + +"d3-transition@2 - 3", d3-transition@3: + version "3.0.1" + resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-3.0.1.tgz#6869fdde1448868077fdd5989200cb61b2a1645f" + integrity sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w== + dependencies: + d3-color "1 - 3" + d3-dispatch "1 - 3" + d3-ease "1 - 3" + d3-interpolate "1 - 3" + d3-timer "1 - 3" + +d3-zoom@3: + version "3.0.0" + resolved "https://registry.yarnpkg.com/d3-zoom/-/d3-zoom-3.0.0.tgz#d13f4165c73217ffeaa54295cd6969b3e7aee8f3" + integrity sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw== + dependencies: + d3-dispatch "1 - 3" + d3-drag "2 - 3" + d3-interpolate "1 - 3" + d3-selection "2 - 3" + d3-transition "2 - 3" + +d3@^7.4.0, d3@^7.8.2: + version "7.9.0" + resolved "https://registry.yarnpkg.com/d3/-/d3-7.9.0.tgz#579e7acb3d749caf8860bd1741ae8d371070cd5d" + integrity sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA== + dependencies: + d3-array "3" + d3-axis "3" + d3-brush "3" + d3-chord "3" + d3-color "3" + d3-contour "4" + d3-delaunay "6" + d3-dispatch "3" + d3-drag "3" + d3-dsv "3" + d3-ease "3" + d3-fetch "3" + d3-force "3" + d3-format "3" + d3-geo "3" + d3-hierarchy "3" + d3-interpolate "3" + d3-path "3" + d3-polygon "3" + d3-quadtree "3" + d3-random "3" + d3-scale "4" + d3-scale-chromatic "3" + d3-selection "3" + d3-shape "3" + d3-time "3" + d3-time-format "4" + d3-timer "3" + d3-transition "3" + d3-zoom "3" + +dagre-d3-es@7.0.10: + version "7.0.10" + resolved "https://registry.yarnpkg.com/dagre-d3-es/-/dagre-d3-es-7.0.10.tgz#19800d4be674379a3cd8c86a8216a2ac6827cadc" + integrity sha512-qTCQmEhcynucuaZgY5/+ti3X/rnszKZhEQH/ZdWdtP1tA/y3VoHJzcVrO9pjjJCNpigfscAtoUB5ONcd2wNn0A== + dependencies: + d3 "^7.8.2" + lodash-es "^4.17.21" + +dayjs@^1.11.7: + version "1.11.13" + resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.13.tgz#92430b0139055c3ebb60150aa13e860a4b5a366c" + integrity sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg== + debug@2.6.9, debug@^2.6.0: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" @@ -3442,6 +4155,13 @@ debug@2.6.9, debug@^2.6.0: dependencies: ms "2.0.0" +debug@^4.0.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + debug@^4.1.0, debug@^4.1.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -3449,6 +4169,13 @@ debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" +decode-named-character-reference@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/decode-named-character-reference/-/decode-named-character-reference-1.0.2.tgz#daabac9690874c394c81e4162a0304b35d824f0e" + integrity sha512-O8x12RzrUF8xyVcY0KJowWsmaJxQbmy0/EtnNtHRpsOcT7dFk5W598coHqBVpmWo1oQQfsCqfCmkZN5DJrZVdg== + dependencies: + character-entities "^2.0.0" + decompress-response@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" @@ -3505,6 +4232,13 @@ del@^6.1.1: rimraf "^3.0.2" slash "^3.0.0" +delaunator@5: + version "5.0.1" + resolved "https://registry.yarnpkg.com/delaunator/-/delaunator-5.0.1.tgz#39032b08053923e924d6094fe2cde1a99cc51278" + integrity sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw== + dependencies: + robust-predicates "^3.0.2" + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -3515,6 +4249,11 @@ depd@~1.1.2: resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ== +dequal@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be" + integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA== + destroy@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.2.0.tgz#4803735509ad8be552934c67df614f94e66fa015" @@ -3527,6 +4266,11 @@ detab@2.0.4: dependencies: repeat-string "^1.5.4" +detect-node-es@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493" + integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ== + detect-node@^2.0.4: version "2.1.0" resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.1.0.tgz#c9c70775a49c3d03bc2c06d9a73be550f978f8b1" @@ -3548,6 +4292,11 @@ detect-port@^1.3.0: address "^1.0.1" debug "^2.6.0" +diff@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -3633,6 +4382,11 @@ domhandler@^5.0.1, domhandler@^5.0.2, domhandler@^5.0.3: dependencies: domelementtype "^2.3.0" +"dompurify@^3.0.5 <3.1.7": + version "3.1.6" + resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.1.6.tgz#43c714a94c6a7b8801850f82e756685300a027e2" + integrity sha512-cTOAhc36AalkjtBpfG6O8JimdTMWNXjiePT2xQH/ppBGi/4uIpmj8eKyIkMJErXWARyINV/sB38yf8JCLF5pbQ== + domutils@^2.5.2, domutils@^2.8.0: version "2.8.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" @@ -3710,6 +4464,11 @@ electron-to-chromium@^1.4.188: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.199.tgz#e0384fde79fdda89880e8be58196a9153e04db3b" integrity sha512-WIGME0Cs7oob3mxsJwHbeWkH0tYkIE/sjkJ8ML2BYmuRcjhRl/q5kVDXG7W9LOOKwzPU5M0LBlXRq9rlSgnNlg== +elkjs@^0.9.0: + version "0.9.3" + resolved "https://registry.yarnpkg.com/elkjs/-/elkjs-0.9.3.tgz#16711f8ceb09f1b12b99e971b138a8384a529161" + integrity sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3772,6 +4531,11 @@ es-module-lexer@^0.9.0: resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es6-promise-pool@2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/es6-promise-pool/-/es6-promise-pool-2.5.0.tgz#147c612b36b47f105027f9d2bf54a598a99d9ccb" + integrity sha512-VHErXfzR/6r/+yyzPKeBvO0lgjfC5cbDCQWjWwMZWSb6YU39TGIl51OUmCfWCq4ylMdJSB8zkz2vIuIeIxXApA== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -4112,6 +4876,11 @@ fraction.js@^4.2.0: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.2.0.tgz#448e5109a313a3527f5a3ab2119ec4cf0e0e2950" integrity sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA== +fractional-indexing@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/fractional-indexing/-/fractional-indexing-3.2.0.tgz#1193e63d54ff4e0cbe0c79a9ed6cfbab25d91628" + integrity sha512-PcOxmqwYCW7O2ovKRU8OoQQj2yqTfEB/yeTYk4gPid6dN5ODRfU1hXd9tTVZzax/0NkO7AxpHykvZnT1aYp/BQ== + fresh@0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" @@ -4156,6 +4925,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +fuzzy@0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/fuzzy/-/fuzzy-0.1.3.tgz#4c76ec2ff0ac1a36a9dccf9a00df8623078d4ed8" + integrity sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w== + gensync@^1.0.0-beta.1, gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -4170,6 +4944,11 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.3" +get-nonce@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" + integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -4281,6 +5060,11 @@ globby@^13.1.1: merge2 "^1.4.1" slash "^4.0.0" +glur@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/glur/-/glur-1.1.2.tgz#f20ea36db103bfc292343921f1f91e83c3467689" + integrity sha512-l+8esYHTKOx2G/Aao4lEQ0bnHWg4fWtJbVoZZT9Knxi01pB8C80BR85nONLFwkkQoFRCmXY+BUcGZN3yZ2QsRA== + got@^9.6.0: version "9.6.0" resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85" @@ -4320,6 +5104,11 @@ gzip-size@^6.0.0: dependencies: duplexer "^0.1.2" +hachure-fill@^0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" + integrity sha512-3GKBOn+m2LX9iq+JC1064cSFprJY4jL1jCXTcpnfER5HYE2l/4EfWSGzkPa/ZDBmYI0ZOEj5VHV/eKnPGkHuOg== + handle-thing@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.1.tgz#857f79ce359580c340d43081cc648970d0bb234e" @@ -4588,6 +5377,13 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +iconv-lite@0.6: + version "0.6.3" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" + integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw== + dependencies: + safer-buffer ">= 2.1.2 < 3.0.0" + icss-utils@^5.0.0, icss-utils@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" @@ -4598,6 +5394,13 @@ ignore@^5.2.0: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== +image-blob-reduce@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/image-blob-reduce/-/image-blob-reduce-3.0.1.tgz#812be7655a552031635799ae64e846b106f7a489" + integrity sha512-/VmmWgIryG/wcn4TVrV7cC4mlfUC/oyiKIfSg5eVM3Ten/c1c34RJhMYKCWTnoSMHSqXLt3tsrBR4Q2HInvN+Q== + dependencies: + pica "^7.1.0" + image-size@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.0.2.tgz#d778b6d0ab75b2737c1556dd631652eb963bc486" @@ -4676,6 +5479,16 @@ inline-style-parser@0.1.1: resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== +"internmap@1 - 2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-2.0.3.tgz#6685f23755e43c524e251d29cbc97248e3061009" + integrity sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg== + +internmap@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" + integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== + interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" @@ -4916,6 +5729,16 @@ joi@^17.6.0: "@sideway/formula" "^3.0.0" "@sideway/pinpoint" "^2.0.0" +jotai-scope@0.7.2: + version "0.7.2" + resolved "https://registry.yarnpkg.com/jotai-scope/-/jotai-scope-0.7.2.tgz#3e9ec5b743bd9f36b08b32cf5151786049bfcce7" + integrity sha512-Gwed97f3dDObrO43++2lRcgOqw4O2sdr4JCjP/7eHK1oPACDJ7xKHGScpJX9XaflU+KBHXF+VhwECnzcaQiShg== + +jotai@2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/jotai/-/jotai-2.11.0.tgz#923f8351e0b2d721036af892c0ae25625049d120" + integrity sha512-zKfoBBD1uDw3rljwHkt0fWuja1B76R7CjznuBO+mSX6jpsO1EBeWNRKpeaQho9yPI/pvCv4recGfgOXGxwPZvQ== + "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -4980,6 +5803,13 @@ jsonfile@^6.0.1: optionalDependencies: graceful-fs "^4.1.6" +katex@^0.16.9: + version "0.16.21" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.21.tgz#8f63c659e931b210139691f2cc7bb35166b792a3" + integrity sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A== + dependencies: + commander "^8.3.0" + keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -4987,6 +5817,11 @@ keyv@^3.0.0: dependencies: json-buffer "3.0.0" +khroma@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" + integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== + kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.3" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" @@ -4997,6 +5832,11 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== +kleur@^4.0.3: + version "4.1.5" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + klona@^2.0.4, klona@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" @@ -5009,6 +5849,11 @@ latest-version@^5.1.0: dependencies: package-json "^6.3.0" +layout-base@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-1.0.2.tgz#1291e296883c322a9dd4c5dd82063721b53e26e2" + integrity sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg== + leven@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" @@ -5065,12 +5910,17 @@ locate-path@^6.0.0: dependencies: p-locate "^5.0.0" +lodash-es@^4.17.21: + version "4.17.21" + resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" + integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== + lodash.curry@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.curry/-/lodash.curry-4.1.1.tgz#248e36072ede906501d75966200a86dab8b23170" integrity sha512-/u14pXGviLaweY5JI0IUzgzF2J6Ne8INyzAZjImcryjgkZ+ebruBxy2/JaOOkTqScddcYtakjhSaeemV8lR0tA== -lodash.debounce@^4.0.8: +lodash.debounce@4.0.8, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== @@ -5085,6 +5935,11 @@ lodash.memoize@^4.1.2: resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== +lodash.throttle@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ== + lodash.uniq@4.5.0, lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -5159,6 +6014,24 @@ mdast-util-definitions@^4.0.0: dependencies: unist-util-visit "^2.0.0" +mdast-util-from-markdown@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/mdast-util-from-markdown/-/mdast-util-from-markdown-1.3.1.tgz#9421a5a247f10d31d2faed2a30df5ec89ceafcf0" + integrity sha512-4xTO/M8c82qBcnQc1tgpNtubGUW/Y1tBQ1B0i5CtSoelOLKFYlElIr3bvgREYYO5iRqbMY1YuqZng0GVOI8Qww== + dependencies: + "@types/mdast" "^3.0.0" + "@types/unist" "^2.0.0" + decode-named-character-reference "^1.0.0" + mdast-util-to-string "^3.1.0" + micromark "^3.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-decode-string "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + unist-util-stringify-position "^3.0.0" + uvu "^0.5.0" + mdast-util-to-hast@10.0.1: version "10.0.1" resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-10.0.1.tgz#0cfc82089494c52d46eb0e3edb7a4eb2aea021eb" @@ -5178,6 +6051,13 @@ mdast-util-to-string@^2.0.0: resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-2.0.0.tgz#b8cfe6a713e1091cb5b728fc48885a4767f8b97b" integrity sha512-AW4DRS3QbBayY/jJmD8437V1Gombjf8RSOUCMFBuo5iHi58AGEgVCKQ+ezHkZZDpAQS75hcBMpLqjpJTjtUL7w== +mdast-util-to-string@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-3.2.0.tgz#66f7bb6324756741c5f47a53557f0cbf16b6f789" + integrity sha512-V4Zn/ncyN1QNSqSBxTrMOLpjr+IKdHl2v3KVLoWmDPscP4r9GcCi71gjgvUV1SFSKh92AjAG4peFuBl2/YgCJg== + dependencies: + "@types/mdast" "^3.0.0" + mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -5215,11 +6095,231 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +mermaid@10.9.3: + version "10.9.3" + resolved "https://registry.yarnpkg.com/mermaid/-/mermaid-10.9.3.tgz#90bc6f15c33dbe5d9507fed31592cc0d88fee9f7" + integrity sha512-V80X1isSEvAewIL3xhmz/rVmc27CVljcsbWxkxlWJWY/1kQa4XOABqpDl2qQLGKzpKm6WbTfUEKImBlUfFYArw== + dependencies: + "@braintree/sanitize-url" "^6.0.1" + "@types/d3-scale" "^4.0.3" + "@types/d3-scale-chromatic" "^3.0.0" + cytoscape "^3.28.1" + cytoscape-cose-bilkent "^4.1.0" + d3 "^7.4.0" + d3-sankey "^0.12.3" + dagre-d3-es "7.0.10" + dayjs "^1.11.7" + dompurify "^3.0.5 <3.1.7" + elkjs "^0.9.0" + katex "^0.16.9" + khroma "^2.0.0" + lodash-es "^4.17.21" + mdast-util-from-markdown "^1.3.0" + non-layered-tidy-tree-layout "^2.0.2" + stylis "^4.1.3" + ts-dedent "^2.2.0" + uuid "^9.0.0" + web-worker "^1.2.0" + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== +micromark-core-commonmark@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-core-commonmark/-/micromark-core-commonmark-1.1.0.tgz#1386628df59946b2d39fb2edfd10f3e8e0a75bb8" + integrity sha512-BgHO1aRbolh2hcrzL2d1La37V0Aoz73ymF8rAcKnohLy93titmv62E0gP8Hrx9PKcKrqCZ1BbLGbP3bEhoXYlw== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-factory-destination "^1.0.0" + micromark-factory-label "^1.0.0" + micromark-factory-space "^1.0.0" + micromark-factory-title "^1.0.0" + micromark-factory-whitespace "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-classify-character "^1.0.0" + micromark-util-html-tag-name "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + +micromark-factory-destination@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-destination/-/micromark-factory-destination-1.1.0.tgz#eb815957d83e6d44479b3df640f010edad667b9f" + integrity sha512-XaNDROBgx9SgSChd69pjiGKbV+nfHGDPVYFs5dOoDd7ZnMAE+Cuu91BCpsY8RT2NP9vo/B8pds2VQNCLiu0zhg== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-label@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-label/-/micromark-factory-label-1.1.0.tgz#cc95d5478269085cfa2a7282b3de26eb2e2dec68" + integrity sha512-OLtyez4vZo/1NjxGhcpDSbHQ+m0IIGnT8BoPamh+7jVlzLJBH98zzuCoUeMxvM6WsNeh8wx8cKvqLiPHEACn0w== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-factory-space@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-space/-/micromark-factory-space-1.1.0.tgz#c8f40b0640a0150751d3345ed885a080b0d15faf" + integrity sha512-cRzEj7c0OL4Mw2v6nwzttyOZe8XY/Z8G0rzmWQZTBi/jjwyw/U4uqKtUORXQrR5bAZZnbTI/feRV/R7hc4jQYQ== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-title@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-title/-/micromark-factory-title-1.1.0.tgz#dd0fe951d7a0ac71bdc5ee13e5d1465ad7f50ea1" + integrity sha512-J7n9R3vMmgjDOCY8NPw55jiyaQnH5kBdV2/UXCtZIpnHH3P6nHUKaH7XXEYuWwx/xUJcawa8plLBEjMPU24HzQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-factory-whitespace@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-factory-whitespace/-/micromark-factory-whitespace-1.1.0.tgz#798fb7489f4c8abafa7ca77eed6b5745853c9705" + integrity sha512-v2WlmiymVSp5oMg+1Q0N1Lxmt6pMhIHD457whWM7/GUlEks1hI9xj5w3zbc4uuMKXGisksZk8DzP2UyGbGqNsQ== + dependencies: + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-character@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-character/-/micromark-util-character-1.2.0.tgz#4fedaa3646db249bc58caeb000eb3549a8ca5dcc" + integrity sha512-lXraTwcX3yH/vMDaFWCQJP1uIszLVebzUa3ZHdrgxr7KEU/9mL4mVgCpGbyhvNLNlauROiNUq7WN5u7ndbY6xg== + dependencies: + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-chunked@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-chunked/-/micromark-util-chunked-1.1.0.tgz#37a24d33333c8c69a74ba12a14651fd9ea8a368b" + integrity sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-classify-character@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-classify-character/-/micromark-util-classify-character-1.1.0.tgz#6a7f8c8838e8a120c8e3c4f2ae97a2bff9190e9d" + integrity sha512-SL0wLxtKSnklKSUplok1WQFoGhUdWYKggKUiqhX+Swala+BtptGCu5iPRc+xvzJ4PXE/hwM3FNXsfEVgoZsWbw== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-combine-extensions@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-combine-extensions/-/micromark-util-combine-extensions-1.1.0.tgz#192e2b3d6567660a85f735e54d8ea6e3952dbe84" + integrity sha512-Q20sp4mfNf9yEqDL50WwuWZHUrCO4fEyeDCnMGmG5Pr0Cz15Uo7KBs6jq+dq0EgX4DPwwrh9m0X+zPV1ypFvUA== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-types "^1.0.0" + +micromark-util-decode-numeric-character-reference@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-1.1.0.tgz#b1e6e17009b1f20bc652a521309c5f22c85eb1c6" + integrity sha512-m9V0ExGv0jB1OT21mrWcuf4QhP46pH1KkfWy9ZEezqHKAxkj4mPCy3nIH1rkbdMlChLHX531eOrymlwyZIf2iw== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-decode-string@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-decode-string/-/micromark-util-decode-string-1.1.0.tgz#dc12b078cba7a3ff690d0203f95b5d5537f2809c" + integrity sha512-YphLGCK8gM1tG1bd54azwyrQRjCFcmgj2S2GoJDNnh4vYtnL38JS8M4gpxzOPNyHdNEpheyWXCTnnTDY3N+NVQ== + dependencies: + decode-named-character-reference "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-encode/-/micromark-util-encode-1.1.0.tgz#92e4f565fd4ccb19e0dcae1afab9a173bbeb19a5" + integrity sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw== + +micromark-util-html-tag-name@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-html-tag-name/-/micromark-util-html-tag-name-1.2.0.tgz#48fd7a25826f29d2f71479d3b4e83e94829b3588" + integrity sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q== + +micromark-util-normalize-identifier@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-1.1.0.tgz#7a73f824eb9f10d442b4d7f120fecb9b38ebf8b7" + integrity sha512-N+w5vhqrBihhjdpM8+5Xsxy71QWqGn7HYNUvch71iV2PM7+E3uWGox1Qp90loa1ephtCxG2ftRV/Conitc6P2Q== + dependencies: + micromark-util-symbol "^1.0.0" + +micromark-util-resolve-all@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-resolve-all/-/micromark-util-resolve-all-1.1.0.tgz#4652a591ee8c8fa06714c9b54cd6c8e693671188" + integrity sha512-b/G6BTMSg+bX+xVCshPTPyAu2tmA0E4X98NSR7eIbeC6ycCqCeE7wjfDIgzEbkzdEVJXRtOG4FbEm/uGbCRouA== + dependencies: + micromark-util-types "^1.0.0" + +micromark-util-sanitize-uri@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-1.2.0.tgz#613f738e4400c6eedbc53590c67b197e30d7f90d" + integrity sha512-QO4GXv0XZfWey4pYFndLUKEAktKkG5kZTdUNaTAkzbuJxn2tNBOr+QtxR2XpWaMhbImT2dPzyLrPXLlPhph34A== + dependencies: + micromark-util-character "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-symbol "^1.0.0" + +micromark-util-subtokenize@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-subtokenize/-/micromark-util-subtokenize-1.1.0.tgz#941c74f93a93eaf687b9054aeb94642b0e92edb1" + integrity sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A== + dependencies: + micromark-util-chunked "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.0" + uvu "^0.5.0" + +micromark-util-symbol@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-symbol/-/micromark-util-symbol-1.1.0.tgz#813cd17837bdb912d069a12ebe3a44b6f7063142" + integrity sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag== + +micromark-util-types@^1.0.0, micromark-util-types@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/micromark-util-types/-/micromark-util-types-1.1.0.tgz#e6676a8cae0bb86a2171c498167971886cb7e283" + integrity sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg== + +micromark@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/micromark/-/micromark-3.2.0.tgz#1af9fef3f995ea1ea4ac9c7e2f19c48fd5c006e9" + integrity sha512-uD66tJj54JLYq0De10AhWycZWGQNUvDI55xPgk2sQM5kn1JYlhbCMTtEeT27+vAhW2FBQxLlOmS3pmA7/2z4aA== + dependencies: + "@types/debug" "^4.0.0" + debug "^4.0.0" + decode-named-character-reference "^1.0.0" + micromark-core-commonmark "^1.0.1" + micromark-factory-space "^1.0.0" + micromark-util-character "^1.0.0" + micromark-util-chunked "^1.0.0" + micromark-util-combine-extensions "^1.0.0" + micromark-util-decode-numeric-character-reference "^1.0.0" + micromark-util-encode "^1.0.0" + micromark-util-normalize-identifier "^1.0.0" + micromark-util-resolve-all "^1.0.0" + micromark-util-sanitize-uri "^1.0.0" + micromark-util-subtokenize "^1.0.0" + micromark-util-symbol "^1.0.0" + micromark-util-types "^1.0.1" + uvu "^0.5.0" + micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" @@ -5306,6 +6406,11 @@ minimist@^1.2.0, minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44" integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q== +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + mrmime@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" @@ -5321,7 +6426,7 @@ ms@2.1.2: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@2.1.3: +ms@2.1.3, ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5334,6 +6439,24 @@ multicast-dns@^7.2.5: dns-packet "^5.2.2" thunky "^1.0.2" +multimath@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/multimath/-/multimath-2.0.0.tgz#0d37acf67c328f30e3d8c6b0d3209e6082710302" + integrity sha512-toRx66cAMJ+Ccz7pMIg38xSIrtnbozk0dchXezwQDMgQmbGpfxjtv68H+L00iFL8hxDaVjrmwAFSb3I6bg8Q2g== + dependencies: + glur "^1.1.2" + object-assign "^4.1.1" + +nanoid@3.3.3: + version "3.3.3" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.3.tgz#fd8e8b7aa761fe807dba2d1b98fb7241bb724a25" + integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w== + +nanoid@4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-4.0.2.tgz#140b3c5003959adbebf521c170f282c5e7f9fb9e" + integrity sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw== + nanoid@^3.3.4: version "3.3.4" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" @@ -5381,6 +6504,11 @@ node-releases@^2.0.6: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== +non-layered-tidy-tree-layout@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/non-layered-tidy-tree-layout/-/non-layered-tidy-tree-layout-2.0.2.tgz#57d35d13c356643fc296a55fb11ac15e74da7804" + integrity sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -5476,6 +6604,11 @@ onetime@^5.1.2: dependencies: mimic-fn "^2.1.0" +open-color@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/open-color/-/open-color-1.9.1.tgz#a6e6328f60eff7aa60e3e8fcfa50f53ff3eece35" + integrity sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw== + open@^8.0.9, open@^8.4.0: version "8.4.0" resolved "https://registry.yarnpkg.com/open/-/open-8.4.0.tgz#345321ae18f8138f82565a910fdc6b39e8c244f8" @@ -5565,6 +6698,11 @@ package-json@^6.3.0: registry-url "^5.0.0" semver "^6.2.0" +pako@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43" + integrity sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw== + param-case@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/param-case/-/param-case-3.0.4.tgz#7d17fe4aa12bde34d4a77d91acfb6219caad01c5" @@ -5640,6 +6778,11 @@ pascal-case@^3.1.2: no-case "^3.0.4" tslib "^2.0.3" +path-data-parser@0.1.0, path-data-parser@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" + integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== + path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -5692,6 +6835,22 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +perfect-freehand@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/perfect-freehand/-/perfect-freehand-1.2.0.tgz#706a0f854544f6175772440c51d3b0563eb3988a" + integrity sha512-h/0ikF1M3phW7CwpZ5MMvKnfpHficWoOEyr//KVNTxV4F6deRK1eYMtHyBKEAKFK0aXIEUK9oBvlF6PNXMDsAw== + +pica@7.1.1, pica@^7.1.0: + version "7.1.1" + resolved "https://registry.yarnpkg.com/pica/-/pica-7.1.1.tgz#c68b42f5cfa6cc26eaec5cfa10cc0a5299ef3b7a" + integrity sha512-WY73tMvNzXWEld2LicT9Y260L43isrZ85tPuqRyvtkljSDLmnNFQmZICt4xUJMVulmcc6L9O7jbBrtx3DOz/YQ== + dependencies: + glur "^1.1.2" + inherits "^2.0.3" + multimath "^2.0.0" + object-assign "^4.1.1" + webworkify "^1.5.0" + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -5716,6 +6875,44 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +png-chunk-text@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/png-chunk-text/-/png-chunk-text-1.0.0.tgz#1c6006d8e34ba471d38e1c9c54b3f53e1085e18f" + integrity sha512-DEROKU3SkkLGWNMzru3xPVgxyd48UGuMSZvioErCure6yhOc/pRH2ZV+SEn7nmaf7WNf3NdIpH+UTrRdKyq9Lw== + +png-chunks-encode@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/png-chunks-encode/-/png-chunks-encode-1.0.0.tgz#d9ea5e35caeeed782658c1ab7bafa7a5edb1a878" + integrity sha512-J1jcHgbQRsIIgx5wxW9UmCymV3wwn4qCCJl6KYgEU/yHCh/L2Mwq/nMOkRPtmV79TLxRZj5w3tH69pvygFkDqA== + dependencies: + crc-32 "^0.3.0" + sliced "^1.0.1" + +png-chunks-extract@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/png-chunks-extract/-/png-chunks-extract-1.0.0.tgz#fad4a905e66652197351c65e35b92c64311e472d" + integrity sha512-ZiVwF5EJ0DNZyzAqld8BP1qyJBaGOFaq9zl579qfbkcmOwWLLO4I9L8i2O4j3HkI6/35i0nKG2n+dZplxiT89Q== + dependencies: + crc-32 "^0.3.0" + +points-on-curve@0.2.0, points-on-curve@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/points-on-curve/-/points-on-curve-0.2.0.tgz#7dbb98c43791859434284761330fa893cb81b4d1" + integrity sha512-0mYKnYYe9ZcqMCWhUjItv/oHjvgEsfKvnUTg8sAtnHr3GVy7rGkXCb6d5cSyqrWqL4k81b9CPg3urd+T7aop3A== + +points-on-curve@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/points-on-curve/-/points-on-curve-1.0.1.tgz#03fcdc08e48e3bfdc7e8bd1d7ccd4d5f11e132c6" + integrity sha512-3nmX4/LIiyuwGLwuUrfhTlDeQFlAhi7lyK/zcRNGhalwapDWgAGR82bUpmn2mA03vII3fvNCG8jAONzKXwpxAg== + +points-on-path@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/points-on-path/-/points-on-path-0.2.1.tgz#553202b5424c53bed37135b318858eacff85dd52" + integrity sha512-25ClnWWuw7JbWZcgqY/gJ4FQWadKxGWk+3kR/7kD0tCaDtPPMj7oHu2ToLaVhfpnHrZzYby2w6tUA0eOIuUg8g== + dependencies: + path-data-parser "0.1.0" + points-on-curve "0.2.0" + postcss-calc@^8.2.3: version "8.2.4" resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" @@ -6108,6 +7305,11 @@ pure-color@^1.2.0: resolved "https://registry.yarnpkg.com/pure-color/-/pure-color-1.3.0.tgz#1fe064fb0ac851f0de61320a8bf796836422f33e" integrity sha512-QFADYnsVoBMw1srW7OVKEYjG+MbIa49s54w1MA1EDY6r2r/sTcKKYqRX1f4GYvnXP7eN/Pe9HFcX+hwzmrXRHA== +pwacompat@2.0.17: + version "2.0.17" + resolved "https://registry.yarnpkg.com/pwacompat/-/pwacompat-2.0.17.tgz#707959ff97f239bf1fe7b260b63aeea416a15eab" + integrity sha512-6Du7IZdIy7cHiv7AhtDy4X2QRM8IAD5DII69mt5qWibC2d15ZU8DmBG1WdZKekG11cChSu4zkSUGPF9sweOl6w== + qs@6.10.3: version "6.10.3" resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" @@ -6281,6 +7483,25 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: "@types/react" "*" prop-types "^15.6.2" +react-remove-scroll-bar@^2.3.3: + version "2.3.8" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" + integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== + dependencies: + react-style-singleton "^2.2.2" + tslib "^2.0.0" + +react-remove-scroll@2.5.5: + version "2.5.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" + integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== + dependencies: + react-remove-scroll-bar "^2.3.3" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.0" + use-sidecar "^1.1.2" + react-router-config@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" @@ -6322,6 +7543,14 @@ react-simple-code-editor@^0.10.0: resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz#73e7ac550a928069715482aeb33ccba36efe2373" integrity sha512-bL5W5mAxSW6+cLwqqVWY47Silqgy2DKDTR4hDBrLrUqC5BXc29YVx17l2IZk5v36VcDEq1Bszu2oHm1qBwKqBA== +react-style-singleton@^2.2.1, react-style-singleton@^2.2.2: + version "2.2.3" + resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" + integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== + dependencies: + get-nonce "^1.0.0" + tslib "^2.0.0" + react-textarea-autosize@^8.3.2: version "8.3.4" resolved "https://registry.yarnpkg.com/react-textarea-autosize/-/react-textarea-autosize-8.3.4.tgz#270a343de7ad350534141b02c9cb78903e553524" @@ -6410,6 +7639,11 @@ regenerator-runtime@^0.13.4: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" integrity sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA== +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + regenerator-transform@^0.15.0: version "0.15.0" resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.15.0.tgz#cbd9ead5d77fae1a48d957cf889ad0586adb6537" @@ -6615,6 +7849,21 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +robust-predicates@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" + integrity sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg== + +roughjs@4.6.4: + version "4.6.4" + resolved "https://registry.yarnpkg.com/roughjs/-/roughjs-4.6.4.tgz#b6f39b44645854a6e0a4a28b078368701eb7f939" + integrity sha512-s6EZ0BntezkFYMf/9mGn7M8XGIoaav9QQBCnJROWB3brUWQ683Q2LbRD/hq0Z3bAJ/9NVpU/5LpiTWvQMyLDhw== + dependencies: + hachure-fill "^0.5.2" + path-data-parser "^0.1.0" + points-on-curve "^0.2.0" + points-on-path "^0.2.1" + rtl-detect@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/rtl-detect/-/rtl-detect-1.0.4.tgz#40ae0ea7302a150b96bc75af7d749607392ecac6" @@ -6637,6 +7886,11 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" +rw@1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" + integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== + rxjs@^7.5.4: version "7.5.6" resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.6.tgz#0446577557862afd6903517ce7cae79ecb9662bc" @@ -6644,6 +7898,13 @@ rxjs@^7.5.4: dependencies: tslib "^2.1.0" +sade@^1.7.3: + version "1.8.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.8.1.tgz#0a78e81d658d394887be57d2a409bf703a3b2701" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -6654,7 +7915,7 @@ safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -"safer-buffer@>= 2.1.2 < 3": +"safer-buffer@>= 2.1.2 < 3", "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== @@ -6670,6 +7931,15 @@ sass-loader@^10.1.1: schema-utils "^3.0.0" semver "^7.3.2" +sass@1.51.0: + version "1.51.0" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.51.0.tgz#25ea36cf819581fe1fe8329e8c3a4eaaf70d2845" + integrity sha512-haGdpTgywJTvHC2b91GSq+clTKGbtkkZmVAb82jZQN/wTy6qs8DdFm2lhEQbEwrY0QDRgSQ3xDurqM977C3noA== + dependencies: + chokidar ">=3.0.0 <4.0.0" + immutable "^4.0.0" + source-map-js ">=0.6.2 <2.0.0" + sass@1.57.1: version "1.57.1" resolved "https://registry.yarnpkg.com/sass/-/sass-1.57.1.tgz#dfafd46eb3ab94817145e8825208ecf7281119b5" @@ -6941,6 +8211,11 @@ slash@^4.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-4.0.0.tgz#2422372176c4c6c5addb5e2ada885af984b396a7" integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew== +sliced@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/sliced/-/sliced-1.0.1.tgz#0b3a662b5d04c3177b1926bea82b03f837a2ef41" + integrity sha512-VZBmZP8WU3sMOZm1bdgTadsQbcscK0UM8oKxKVBs4XAhUo2Xxzm/OFMGBkPusxw9xL3Uy8LrzEqGqJhclsr0yA== + sockjs@^0.3.24: version "0.3.24" resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.24.tgz#c9bc8995f33a111bea0395ec30aa3206bdb5ccce" @@ -7131,6 +8406,11 @@ stylehacks@^5.1.0: browserslist "^4.16.6" postcss-selector-parser "^6.0.4" +stylis@^4.1.3: + version "4.3.6" + resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" + integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -7273,11 +8553,28 @@ trough@^1.0.0: resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== +ts-dedent@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" + integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== + +tslib@^2.0.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^2.0.3, tslib@^2.1.0, tslib@^2.4.0: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== +tunnel-rat@0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tunnel-rat/-/tunnel-rat-0.1.2.tgz#1717efbc474ea2d8aa05a91622457a6e201c0aeb" + integrity sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ== + dependencies: + zustand "^4.3.2" + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" @@ -7423,6 +8720,13 @@ unist-util-stringify-position@^2.0.0: dependencies: "@types/unist" "^2.0.2" +unist-util-stringify-position@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-3.0.3.tgz#03ad3348210c2d930772d64b489580c13a7db39d" + integrity sha512-k5GzIBZ/QatR8N5X2y+drfpWG8IDBzdnVj6OInRNWm1oXrzydiaAT2OQiA8DPRRZyAKb9b6I2a6PxYklZD0gKg== + dependencies: + "@types/unist" "^2.0.0" + unist-util-visit-parents@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.1.1.tgz#65a6ce698f78a6b0f56aa0e88f13801886cdaef6" @@ -7501,6 +8805,13 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" +use-callback-ref@^1.3.0: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== + dependencies: + tslib "^2.0.0" + use-composed-ref@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/use-composed-ref/-/use-composed-ref-1.3.0.tgz#3d8104db34b7b264030a9d916c5e94fbe280dbda" @@ -7518,6 +8829,19 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" +use-sidecar@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" + integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== + dependencies: + detect-node-es "^1.1.0" + tslib "^2.0.0" + +use-sync-external-store@^1.2.2: + version "1.4.0" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" + integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -7543,6 +8867,21 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.0: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + +uvu@^0.5.0: + version "0.5.6" + resolved "https://registry.yarnpkg.com/uvu/-/uvu-0.5.6.tgz#2754ca20bcb0bb59b64e9985e84d2e81058502df" + integrity sha512-+g8ENReyr8YsOc6fv/NVJs2vFdHBnBNdfE49rshrTzDWOlUx4Gq7KOS2GD8eqhy2j+Ejq29+SbKH8yjkAqXqoA== + dependencies: + dequal "^2.0.0" + diff "^5.0.0" + kleur "^4.0.3" + sade "^1.7.3" + value-equal@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" @@ -7612,6 +8951,11 @@ web-namespaces@^1.0.0: resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +web-worker@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/web-worker/-/web-worker-1.5.0.tgz#71b2b0fbcc4293e8f0aa4f6b8a3ffebff733dcc5" + integrity sha512-RiMReJrTAiA+mBjGONMnjVDP2u3p9R1vkcGz6gDIrOMT3oGuYwX2WRMYI9ipkphSuE5XKEhydbhNEJh4NY9mlw== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -7745,6 +9089,11 @@ websocket-extensions@>=0.1.1: resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== +webworkify@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/webworkify/-/webworkify-1.5.0.tgz#734ad87a774de6ebdd546e1d3e027da5b8f4a42c" + integrity sha512-AMcUeyXAhbACL8S2hqqdqOLqvJ8ylmIbNwUIqQujRSouf4+eUFaXbG6F1Rbu+srlJMmxQWsiU7mOJi0nMBfM1g== + whatwg-url@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" @@ -7861,6 +9210,13 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +zustand@^4.3.2: + version "4.5.6" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.6.tgz#6857d52af44874a79fb3408c9473f78367255c96" + integrity sha512-ibr/n1hBzLLj5Y+yUcU7dYw8p6WnIVzdJbnX+1YpaScvZVF2ziugqHs+LAmHw4lWO9c/zRj+K1ncgWDQuthEdQ== + dependencies: + use-sync-external-store "^1.2.2" + zwitch@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" diff --git a/examples/excalidraw/package.json b/examples/excalidraw/package.json deleted file mode 100644 index 0d720b537..000000000 --- a/examples/excalidraw/package.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "name": "examples", - "version": "1.0.0", - "private": true, - "dependencies": { - "react": "19.0.0", - "react-dom": "19.0.0", - "@excalidraw/excalidraw": "*" - }, - "devDependencies": { - "typescript": "^5" - } -} diff --git a/examples/excalidraw/tsconfig.json b/examples/excalidraw/tsconfig.json deleted file mode 100644 index 41716a7dd..000000000 --- a/examples/excalidraw/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "../../tsconfig" -} diff --git a/examples/excalidraw/with-script-in-browser/vite.config.mts b/examples/excalidraw/with-script-in-browser/vite.config.mts deleted file mode 100644 index e2e5e19ac..000000000 --- a/examples/excalidraw/with-script-in-browser/vite.config.mts +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from "vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - server: { - port: 3001, - // open the browser - open: true, - }, - publicDir: "public", -}); diff --git a/examples/excalidraw/yarn.lock b/examples/excalidraw/yarn.lock deleted file mode 100644 index 1eb584205..000000000 --- a/examples/excalidraw/yarn.lock +++ /dev/null @@ -1,313 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@esbuild/aix-ppc64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.11.tgz#2acd20be6d4f0458bc8c784103495ff24f13b1d3" - integrity sha512-FnzU0LyE3ySQk7UntJO4+qIiQgI7KoODnZg5xzXIrFJlKd2P2gwHsHY4927xj9y5PJmJSzULiUCWmv7iWnNa7g== - -"@esbuild/android-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.11.tgz#b45d000017385c9051a4f03e17078abb935be220" - integrity sha512-aiu7K/5JnLj//KOnOfEZ0D90obUkRzDMyqd/wNAUQ34m4YUPVhRZpnqKV9uqDGxT7cToSDnIHsGooyIczu9T+Q== - -"@esbuild/android-arm@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.11.tgz#f46f55414e1c3614ac682b29977792131238164c" - integrity sha512-5OVapq0ClabvKvQ58Bws8+wkLCV+Rxg7tUVbo9xu034Nm536QTII4YzhaFriQ7rMrorfnFKUsArD2lqKbFY4vw== - -"@esbuild/android-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.11.tgz#bfc01e91740b82011ef503c48f548950824922b2" - integrity sha512-eccxjlfGw43WYoY9QgB82SgGgDbibcqyDTlk3l3C0jOVHKxrjdc9CTwDUQd0vkvYg5um0OH+GpxYvp39r+IPOg== - -"@esbuild/darwin-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.11.tgz#533fb7f5a08c37121d82c66198263dcc1bed29bf" - integrity sha512-ETp87DRWuSt9KdDVkqSoKoLFHYTrkyz2+65fj9nfXsaV3bMhTCjtQfw3y+um88vGRKRiF7erPrh/ZuIdLUIVxQ== - -"@esbuild/darwin-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.11.tgz#62f3819eff7e4ddc656b7c6815a31cf9a1e7d98e" - integrity sha512-fkFUiS6IUK9WYUO/+22omwetaSNl5/A8giXvQlcinLIjVkxwTLSktbF5f/kJMftM2MJp9+fXqZ5ezS7+SALp4g== - -"@esbuild/freebsd-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.11.tgz#d478b4195aa3ca44160272dab85ef8baf4175b4a" - integrity sha512-lhoSp5K6bxKRNdXUtHoNc5HhbXVCS8V0iZmDvyWvYq9S5WSfTIHU2UGjcGt7UeS6iEYp9eeymIl5mJBn0yiuxA== - -"@esbuild/freebsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.11.tgz#7bdcc1917409178257ca6a1a27fe06e797ec18a2" - integrity sha512-JkUqn44AffGXitVI6/AbQdoYAq0TEullFdqcMY/PCUZ36xJ9ZJRtQabzMA+Vi7r78+25ZIBosLTOKnUXBSi1Kw== - -"@esbuild/linux-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.11.tgz#58ad4ff11685fcc735d7ff4ca759ab18fcfe4545" - integrity sha512-LneLg3ypEeveBSMuoa0kwMpCGmpu8XQUh+mL8XXwoYZ6Be2qBnVtcDI5azSvh7vioMDhoJFZzp9GWp9IWpYoUg== - -"@esbuild/linux-arm@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.11.tgz#ce82246d873b5534d34de1e5c1b33026f35e60e3" - integrity sha512-3CRkr9+vCV2XJbjwgzjPtO8T0SZUmRZla+UL1jw+XqHZPkPgZiyWvbDvl9rqAN8Zl7qJF0O/9ycMtjU67HN9/Q== - -"@esbuild/linux-ia32@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.11.tgz#cbae1f313209affc74b80f4390c4c35c6ab83fa4" - integrity sha512-caHy++CsD8Bgq2V5CodbJjFPEiDPq8JJmBdeyZ8GWVQMjRD0sU548nNdwPNvKjVpamYYVL40AORekgfIubwHoA== - -"@esbuild/linux-loong64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.11.tgz#5f32aead1c3ec8f4cccdb7ed08b166224d4e9121" - integrity sha512-ppZSSLVpPrwHccvC6nQVZaSHlFsvCQyjnvirnVjbKSHuE5N24Yl8F3UwYUUR1UEPaFObGD2tSvVKbvR+uT1Nrg== - -"@esbuild/linux-mips64el@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.11.tgz#38eecf1cbb8c36a616261de858b3c10d03419af9" - integrity sha512-B5x9j0OgjG+v1dF2DkH34lr+7Gmv0kzX6/V0afF41FkPMMqaQ77pH7CrhWeR22aEeHKaeZVtZ6yFwlxOKPVFyg== - -"@esbuild/linux-ppc64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.11.tgz#9c5725a94e6ec15b93195e5a6afb821628afd912" - integrity sha512-MHrZYLeCG8vXblMetWyttkdVRjQlQUb/oMgBNurVEnhj4YWOr4G5lmBfZjHYQHHN0g6yDmCAQRR8MUHldvvRDA== - -"@esbuild/linux-riscv64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.11.tgz#2dc4486d474a2a62bbe5870522a9a600e2acb916" - integrity sha512-f3DY++t94uVg141dozDu4CCUkYW+09rWtaWfnb3bqe4w5NqmZd6nPVBm+qbz7WaHZCoqXqHz5p6CM6qv3qnSSQ== - -"@esbuild/linux-s390x@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.11.tgz#4ad8567df48f7dd4c71ec5b1753b6f37561a65a8" - integrity sha512-A5xdUoyWJHMMlcSMcPGVLzYzpcY8QP1RtYzX5/bS4dvjBGVxdhuiYyFwp7z74ocV7WDc0n1harxmpq2ePOjI0Q== - -"@esbuild/linux-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.11.tgz#b7390c4d5184f203ebe7ddaedf073df82a658766" - integrity sha512-grbyMlVCvJSfxFQUndw5mCtWs5LO1gUlwP4CDi4iJBbVpZcqLVT29FxgGuBJGSzyOxotFG4LoO5X+M1350zmPA== - -"@esbuild/netbsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.11.tgz#d633c09492a1721377f3bccedb2d821b911e813d" - integrity sha512-13jvrQZJc3P230OhU8xgwUnDeuC/9egsjTkXN49b3GcS5BKvJqZn86aGM8W9pd14Kd+u7HuFBMVtrNGhh6fHEQ== - -"@esbuild/openbsd-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.11.tgz#17388c76e2f01125bf831a68c03a7ffccb65d1a2" - integrity sha512-ysyOGZuTp6SNKPE11INDUeFVVQFrhcNDVUgSQVDzqsqX38DjhPEPATpid04LCoUr2WXhQTEZ8ct/EgJCUDpyNw== - -"@esbuild/sunos-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.11.tgz#e320636f00bb9f4fdf3a80e548cb743370d41767" - integrity sha512-Hf+Sad9nVwvtxy4DXCZQqLpgmRTQqyFyhT3bZ4F2XlJCjxGmRFF0Shwn9rzhOYRB61w9VMXUkxlBy56dk9JJiQ== - -"@esbuild/win32-arm64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.11.tgz#c778b45a496e90b6fc373e2a2bb072f1441fe0ee" - integrity sha512-0P58Sbi0LctOMOQbpEOvOL44Ne0sqbS0XWHMvvrg6NE5jQ1xguCSSw9jQeUk2lfrXYsKDdOe6K+oZiwKPilYPQ== - -"@esbuild/win32-ia32@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.11.tgz#481a65fee2e5cce74ec44823e6b09ecedcc5194c" - integrity sha512-6YOrWS+sDJDmshdBIQU+Uoyh7pQKrdykdefC1avn76ss5c+RN6gut3LZA4E2cH5xUEp5/cA0+YxRaVtRAb0xBg== - -"@esbuild/win32-x64@0.19.11": - version "0.19.11" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.11.tgz#a5d300008960bb39677c46bf16f53ec70d8dee04" - integrity sha512-vfkhltrjCAb603XaFhqhAF4LGDi2M4OrCRrFusyQ+iTLQ/o60QQXxc9cZC/FFpihBI9N1Grn6SMKVJ4KP7Fuiw== - -"@rollup/rollup-android-arm-eabi@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.5.tgz#b752b6c88a14ccfcbdf3f48c577ccc3a7f0e66b9" - integrity sha512-idWaG8xeSRCfRq9KpRysDHJ/rEHBEXcHuJ82XY0yYFIWnLMjZv9vF/7DOq8djQ2n3Lk6+3qfSH8AqlmHlmi1MA== - -"@rollup/rollup-android-arm64@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.5.tgz#33757c3a448b9ef77b6f6292d8b0ec45c87e9c1a" - integrity sha512-f14d7uhAMtsCGjAYwZGv6TwuS3IFaM4ZnGMUn3aCBgkcHAYErhV1Ad97WzBvS2o0aaDv4mVz+syiN0ElMyfBPg== - -"@rollup/rollup-darwin-arm64@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.5.tgz#5234ba62665a3f443143bc8bcea9df2cc58f55fb" - integrity sha512-ndoXeLx455FffL68OIUrVr89Xu1WLzAG4n65R8roDlCoYiQcGGg6MALvs2Ap9zs7AHg8mpHtMpwC8jBBjZrT/w== - -"@rollup/rollup-darwin-x64@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.5.tgz#981256c054d3247b83313724938d606798a919d1" - integrity sha512-UmElV1OY2m/1KEEqTlIjieKfVwRg0Zwg4PLgNf0s3glAHXBN99KLpw5A5lrSYCa1Kp63czTpVll2MAqbZYIHoA== - -"@rollup/rollup-linux-arm-gnueabihf@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.5.tgz#120678a5a2b3a283a548dbb4d337f9187a793560" - integrity sha512-Q0LcU61v92tQB6ae+udZvOyZ0wfpGojtAKrrpAaIqmJ7+psq4cMIhT/9lfV6UQIpeItnq/2QDROhNLo00lOD1g== - -"@rollup/rollup-linux-arm64-gnu@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.5.tgz#c99d857e2372ece544b6f60b85058ad259f64114" - integrity sha512-dkRscpM+RrR2Ee3eOQmRWFjmV/payHEOrjyq1VZegRUa5OrZJ2MAxBNs05bZuY0YCtpqETDy1Ix4i/hRqX98cA== - -"@rollup/rollup-linux-arm64-musl@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.5.tgz#3064060f568a5718c2a06858cd6e6d24f2ff8632" - integrity sha512-QaKFVOzzST2xzY4MAmiDmURagWLFh+zZtttuEnuNn19AiZ0T3fhPyjPPGwLNdiDT82ZE91hnfJsUiDwF9DClIQ== - -"@rollup/rollup-linux-riscv64-gnu@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.5.tgz#987d30b5d2b992fff07d055015991a57ff55fbad" - integrity sha512-HeGqmRJuyVg6/X6MpE2ur7GbymBPS8Np0S/vQFHDmocfORT+Zt76qu+69NUoxXzGqVP1pzaY6QIi0FJWLC3OPA== - -"@rollup/rollup-linux-x64-gnu@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.5.tgz#85946ee4d068bd12197aeeec2c6f679c94978a49" - integrity sha512-Dq1bqBdLaZ1Gb/l2e5/+o3B18+8TI9ANlA1SkejZqDgdU/jK/ThYaMPMJpVMMXy2uRHvGKbkz9vheVGdq3cJfA== - -"@rollup/rollup-linux-x64-musl@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.5.tgz#fe0b20f9749a60eb1df43d20effa96c756ddcbd4" - integrity sha512-ezyFUOwldYpj7AbkwyW9AJ203peub81CaAIVvckdkyH8EvhEIoKzaMFJj0G4qYJ5sw3BpqhFrsCc30t54HV8vg== - -"@rollup/rollup-win32-arm64-msvc@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.5.tgz#422661ef0e16699a234465d15b2c1089ef963b2a" - integrity sha512-aHSsMnUw+0UETB0Hlv7B/ZHOGY5bQdwMKJSzGfDfvyhnpmVxLMGnQPGNE9wgqkLUs3+gbG1Qx02S2LLfJ5GaRQ== - -"@rollup/rollup-win32-ia32-msvc@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.5.tgz#7b73a145891c202fbcc08759248983667a035d85" - integrity sha512-AiqiLkb9KSf7Lj/o1U3SEP9Zn+5NuVKgFdRIZkvd4N0+bYrTOovVd0+LmYCPQGbocT4kvFyK+LXCDiXPBF3fyA== - -"@rollup/rollup-win32-x64-msvc@4.9.5": - version "4.9.5" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.5.tgz#10491ccf4f63c814d4149e0316541476ea603602" - integrity sha512-1q+mykKE3Vot1kaFJIDoUFv5TuW+QQVaf2FmTT9krg86pQrGStOSJJ0Zil7CFagyxDuouTepzt5Y5TVzyajOdQ== - -"@types/estree@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" - integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== - -esbuild@^0.19.3: - version "0.19.11" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.11.tgz#4a02dca031e768b5556606e1b468fe72e3325d96" - integrity sha512-HJ96Hev2hX/6i5cDVwcqiJBBtuo9+FeIJOtZ9W1kA5M6AMJRHUZlpYZ1/SbEwtO0ioNAW8rUooVpC/WehY2SfA== - optionalDependencies: - "@esbuild/aix-ppc64" "0.19.11" - "@esbuild/android-arm" "0.19.11" - "@esbuild/android-arm64" "0.19.11" - "@esbuild/android-x64" "0.19.11" - "@esbuild/darwin-arm64" "0.19.11" - "@esbuild/darwin-x64" "0.19.11" - "@esbuild/freebsd-arm64" "0.19.11" - "@esbuild/freebsd-x64" "0.19.11" - "@esbuild/linux-arm" "0.19.11" - "@esbuild/linux-arm64" "0.19.11" - "@esbuild/linux-ia32" "0.19.11" - "@esbuild/linux-loong64" "0.19.11" - "@esbuild/linux-mips64el" "0.19.11" - "@esbuild/linux-ppc64" "0.19.11" - "@esbuild/linux-riscv64" "0.19.11" - "@esbuild/linux-s390x" "0.19.11" - "@esbuild/linux-x64" "0.19.11" - "@esbuild/netbsd-x64" "0.19.11" - "@esbuild/openbsd-x64" "0.19.11" - "@esbuild/sunos-x64" "0.19.11" - "@esbuild/win32-arm64" "0.19.11" - "@esbuild/win32-ia32" "0.19.11" - "@esbuild/win32-x64" "0.19.11" - -fsevents@~2.3.2, fsevents@~2.3.3: - version "2.3.3" - resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" - integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== - -loose-envify@^1.1.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -nanoid@^3.3.7: - version "3.3.7" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" - integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== - -picocolors@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" - integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== - -postcss@^8.4.32: - version "8.4.33" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" - integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== - dependencies: - nanoid "^3.3.7" - picocolors "^1.0.0" - source-map-js "^1.0.2" - -react-dom@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d" - integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g== - dependencies: - loose-envify "^1.1.0" - scheduler "^0.23.0" - -react@18.2.0: - version "18.2.0" - resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5" - integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ== - dependencies: - loose-envify "^1.1.0" - -rollup@^4.2.0: - version "4.9.5" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.5.tgz#62999462c90f4c8b5d7c38fc7161e63b29101b05" - integrity sha512-E4vQW0H/mbNMw2yLSqJyjtkHY9dslf/p0zuT1xehNRqUTBOFMqEjguDvqhXr7N7r/4ttb2jr4T41d3dncmIgbQ== - dependencies: - "@types/estree" "1.0.5" - optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.9.5" - "@rollup/rollup-android-arm64" "4.9.5" - "@rollup/rollup-darwin-arm64" "4.9.5" - "@rollup/rollup-darwin-x64" "4.9.5" - "@rollup/rollup-linux-arm-gnueabihf" "4.9.5" - "@rollup/rollup-linux-arm64-gnu" "4.9.5" - "@rollup/rollup-linux-arm64-musl" "4.9.5" - "@rollup/rollup-linux-riscv64-gnu" "4.9.5" - "@rollup/rollup-linux-x64-gnu" "4.9.5" - "@rollup/rollup-linux-x64-musl" "4.9.5" - "@rollup/rollup-win32-arm64-msvc" "4.9.5" - "@rollup/rollup-win32-ia32-msvc" "4.9.5" - "@rollup/rollup-win32-x64-msvc" "4.9.5" - fsevents "~2.3.2" - -scheduler@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe" - integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw== - dependencies: - loose-envify "^1.1.0" - -source-map-js@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" - integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== - -vite@5.0.6: - version "5.0.6" - resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.6.tgz#f9e13503a4c5ccd67312c67803dec921f3bdea7c" - integrity sha512-MD3joyAEBtV7QZPl2JVVUai6zHms3YOmLR+BpMzLlX2Yzjfcc4gTgNi09d/Rua3F4EtC8zdwPU8eQYyib4vVMQ== - dependencies: - esbuild "^0.19.3" - postcss "^8.4.32" - rollup "^4.2.0" - optionalDependencies: - fsevents "~2.3.3" diff --git a/examples/excalidraw/with-nextjs/.gitignore b/examples/with-nextjs/.gitignore similarity index 100% rename from examples/excalidraw/with-nextjs/.gitignore rename to examples/with-nextjs/.gitignore diff --git a/examples/excalidraw/with-nextjs/README.md b/examples/with-nextjs/README.md similarity index 100% rename from examples/excalidraw/with-nextjs/README.md rename to examples/with-nextjs/README.md diff --git a/examples/excalidraw/with-nextjs/next.config.js b/examples/with-nextjs/next.config.js similarity index 100% rename from examples/excalidraw/with-nextjs/next.config.js rename to examples/with-nextjs/next.config.js diff --git a/examples/excalidraw/with-nextjs/package.json b/examples/with-nextjs/package.json similarity index 84% rename from examples/excalidraw/with-nextjs/package.json rename to examples/with-nextjs/package.json index 9d96becdd..ee8e55581 100644 --- a/examples/excalidraw/with-nextjs/package.json +++ b/examples/with-nextjs/package.json @@ -4,14 +4,13 @@ "private": true, "scripts": { "build:workspace": "yarn workspace @excalidraw/excalidraw run build:esm && yarn copy:assets", - "copy:assets": "cp -r ../../../packages/excalidraw/dist/prod/fonts ./public", + "copy:assets": "cp -r ../../packages/excalidraw/dist/prod/fonts ./public", "dev": "yarn build:workspace && next dev -p 3005", "build": "yarn build:workspace && next build", "start": "next start -p 3006", "lint": "next lint" }, "dependencies": { - "@excalidraw/excalidraw": "*", "next": "14.1", "react": "19.0.0", "react-dom": "19.0.0" diff --git a/examples/excalidraw/with-nextjs/public/images/doremon.png b/examples/with-nextjs/public/images/doremon.png similarity index 100% rename from examples/excalidraw/with-nextjs/public/images/doremon.png rename to examples/with-nextjs/public/images/doremon.png diff --git a/examples/excalidraw/with-nextjs/public/images/excalibot.png b/examples/with-nextjs/public/images/excalibot.png similarity index 100% rename from examples/excalidraw/with-nextjs/public/images/excalibot.png rename to examples/with-nextjs/public/images/excalibot.png diff --git a/examples/excalidraw/with-nextjs/public/images/pika.jpeg b/examples/with-nextjs/public/images/pika.jpeg similarity index 100% rename from examples/excalidraw/with-nextjs/public/images/pika.jpeg rename to examples/with-nextjs/public/images/pika.jpeg diff --git a/examples/excalidraw/with-nextjs/public/images/rocket.jpeg b/examples/with-nextjs/public/images/rocket.jpeg similarity index 100% rename from examples/excalidraw/with-nextjs/public/images/rocket.jpeg rename to examples/with-nextjs/public/images/rocket.jpeg diff --git a/examples/excalidraw/with-nextjs/src/app/favicon.ico b/examples/with-nextjs/src/app/favicon.ico similarity index 100% rename from examples/excalidraw/with-nextjs/src/app/favicon.ico rename to examples/with-nextjs/src/app/favicon.ico diff --git a/examples/excalidraw/with-nextjs/src/app/layout.tsx b/examples/with-nextjs/src/app/layout.tsx similarity index 100% rename from examples/excalidraw/with-nextjs/src/app/layout.tsx rename to examples/with-nextjs/src/app/layout.tsx diff --git a/examples/excalidraw/with-nextjs/src/app/page.tsx b/examples/with-nextjs/src/app/page.tsx similarity index 100% rename from examples/excalidraw/with-nextjs/src/app/page.tsx rename to examples/with-nextjs/src/app/page.tsx diff --git a/examples/excalidraw/with-nextjs/src/common.scss b/examples/with-nextjs/src/common.scss similarity index 100% rename from examples/excalidraw/with-nextjs/src/common.scss rename to examples/with-nextjs/src/common.scss diff --git a/examples/excalidraw/with-nextjs/src/excalidrawWrapper.tsx b/examples/with-nextjs/src/excalidrawWrapper.tsx similarity index 87% rename from examples/excalidraw/with-nextjs/src/excalidrawWrapper.tsx rename to examples/with-nextjs/src/excalidrawWrapper.tsx index e9fa3bb23..b4c45fa7d 100644 --- a/examples/excalidraw/with-nextjs/src/excalidrawWrapper.tsx +++ b/examples/with-nextjs/src/excalidrawWrapper.tsx @@ -1,7 +1,7 @@ "use client"; import * as excalidrawLib from "@excalidraw/excalidraw"; import { Excalidraw } from "@excalidraw/excalidraw"; -import App from "../../components/ExampleApp"; +import App from "../../with-script-in-browser/components/ExampleApp"; import "@excalidraw/excalidraw/index.css"; diff --git a/examples/excalidraw/with-nextjs/src/pages/excalidraw-in-pages.tsx b/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx similarity index 100% rename from examples/excalidraw/with-nextjs/src/pages/excalidraw-in-pages.tsx rename to examples/with-nextjs/src/pages/excalidraw-in-pages.tsx diff --git a/examples/excalidraw/with-nextjs/tsconfig.json b/examples/with-nextjs/tsconfig.json similarity index 100% rename from examples/excalidraw/with-nextjs/tsconfig.json rename to examples/with-nextjs/tsconfig.json diff --git a/examples/excalidraw/with-nextjs/vercel.json b/examples/with-nextjs/vercel.json similarity index 100% rename from examples/excalidraw/with-nextjs/vercel.json rename to examples/with-nextjs/vercel.json diff --git a/examples/excalidraw/with-nextjs/yarn.lock b/examples/with-nextjs/yarn.lock similarity index 100% rename from examples/excalidraw/with-nextjs/yarn.lock rename to examples/with-nextjs/yarn.lock diff --git a/examples/with-script-in-browser/.codesandbox/Dockerfile b/examples/with-script-in-browser/.codesandbox/Dockerfile new file mode 100644 index 000000000..fd5b38d1e --- /dev/null +++ b/examples/with-script-in-browser/.codesandbox/Dockerfile @@ -0,0 +1,5 @@ +FROM node:18-bullseye + +# Vite wants to open the browser using `open`, so we +# need to install those utils. +RUN apt update -y && apt install -y xdg-utils diff --git a/examples/with-script-in-browser/.codesandbox/tasks.json b/examples/with-script-in-browser/.codesandbox/tasks.json new file mode 100644 index 000000000..990c21a3c --- /dev/null +++ b/examples/with-script-in-browser/.codesandbox/tasks.json @@ -0,0 +1,35 @@ +{ + // These tasks will run in order when initializing your CodeSandbox project. + "setupTasks": [ + { + "name": "Install Dependencies", + "command": "yarn install" + } + ], + + // These tasks can be run from CodeSandbox. Running one will open a log in the app. + "tasks": { + "build": { + "name": "Build", + "command": "yarn build", + "runAtStart": false + }, + "start": { + "name": "Start Example", + "command": "yarn start", + "runAtStart": true, + "preview": { + "port": 3001 + } + }, + "install-deps": { + "name": "Install Dependencies", + "command": "yarn install", + "restartOn": { + "files": ["yarn.lock"], + "branch": false, + "resume": false + } + } + } +} diff --git a/examples/excalidraw/with-script-in-browser/.gitignore b/examples/with-script-in-browser/.gitignore similarity index 100% rename from examples/excalidraw/with-script-in-browser/.gitignore rename to examples/with-script-in-browser/.gitignore diff --git a/examples/excalidraw/components/CustomFooter.tsx b/examples/with-script-in-browser/components/CustomFooter.tsx similarity index 98% rename from examples/excalidraw/components/CustomFooter.tsx rename to examples/with-script-in-browser/components/CustomFooter.tsx index 30d51ecf0..72fd199f6 100644 --- a/examples/excalidraw/components/CustomFooter.tsx +++ b/examples/with-script-in-browser/components/CustomFooter.tsx @@ -1,5 +1,6 @@ +import React from "react"; import type * as TExcalidraw from "@excalidraw/excalidraw"; -import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/dist/excalidraw/types"; +import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; const COMMENT_SVG = ( React App - +
- + +``` + +#### Deprecated `excalidraw-assets` and `excalidraw-assets-dev` folders [#8012](https://github.com/excalidraw/excalidraw/pull/8012), [#9127](https://github.com/excalidraw/excalidraw/pull/9127) + +The `excalidraw-assets` and `excalidraw-assets-dev` folders, which contained locales and fonts, are no longer used and have been deprecated. + +##### Locales + +Locales are no longer treated as static `.json` assets, but are transpiled with `esbuild` dirrectly to the `.js` as ES modules. Note that some build tools (i.e. Vite) may require setting `es2022` as a build target, in order to support "Arbitrary module namespace identifier names", e.g. `export { english as "en-us" } )`. + +```js +// vite.config.js +optimizeDeps: { + esbuildOptions: { + // Bumping to 2022 due to "Arbitrary module namespace identifier names" not being + // supported in Vite's default browser target https://github.com/vitejs/vite/issues/13556 + target: "es2022", + // Tree shaking is optional, but recommended + treeShaking: true, + }, +} +``` + +##### Fonts + +New fonts, which we've added, are automatically loaded from the CDN. For self-hosting purposes, you'll have to copy the content of the folder `node_modules/@excalidraw/excalidraw/dist/prod/fonts` to the path where your assets should be served from (i.e. `public/` directory in your project). In that case, you should also set `window.EXCALIDRAW_ASSET_PATH` to the very same path, i.e. `/` in case it's in the root: + +```js + +``` + +or, if you serve your assets from the root of your CDN, you would do: + +```js + +``` + +or, if you prefer the path to be dynamicly set based on the `location.origin`, you could do the following: + +```jsx +// Next.js + +``` + +#### Deprecated `commitToHistory` in favor of `captureUpdate` in `updateScene` API [#7348](https://github.com/excalidraw/excalidraw/pull/7348), [#7898](https://github.com/excalidraw/excalidraw/pull//7898) + +```js +// before +updateScene({ elements, appState, commitToHistory: true }); // A +updateScene({ elements, appState, commitToHistory: false }); // B + +// after +import { CaptureUpdateAction } from "@excalidraw/excalidraw"; +updateScene({ + elements, + appState, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, +}); // A +updateScene({ + elements, + appState, + captureUpdate: CaptureUpdateAction.NEVER, +}); // B +``` + +The `updateScene` API has changed due to the added `Store` component, as part of multiplayer undo / redo initiative. Specifically, optional `sceneData` parameter `commitToHistory: boolean` was replaced with optional `captureUpdate: CaptureUpdateActionType` parameter. Therefore, make sure to update all instances of `updateScene`, which use `commitToHistory` parameter according to the _before / after_ table below. + +> **Note**: Some updates are not observed by the store / history - i.e. updates to `collaborators` object or parts of `AppState` which are not observed (not `ObservedAppState`). Such updates will never make it to the undo / redo stacks, regardless of the passed `captureUpdate` value. + +| Undo behaviour | `commitToHistory` (before) | `captureUpdate` (after) | Notes | | --- | --- | --- | --- | -| _Immediately undoable_ | `true` | `"capture"` | As before, use for all updates which should be recorded by the store & history. Should be used for the most of the local updates. These updates will _immediately_ make it to the local undo / redo stacks. | -| _Eventually undoable_ | `false` | `"none"` | Similar to before, use for all updates which should not be recorded immediately (likely exceptions which are part of some async multi-step process) or those not meant to be recorded at all (i.e. updates to `collaborators` object, parts of `AppState` which are not observed by the store & history - not `ObservedAppState`).

**IMPORTANT** It's likely you should switch to `"update"` in all the other cases. Otherwise, all such updates would end up being recorded with the next `"capture"` - triggered either by the next `updateScene` or internally by the editor. These updates will _eventually_ make it to the local undo / redo stacks. | -| _Never undoable_ | n/a | `"update"` | **NEW**: previously there was no equivalent for this value. Now, it's recommended to use `"update"` for all remote updates (from the other clients), scene initialization, or those updates, which should not be locally "undoable". These updates will _never_ make it to the local undo / redo stacks. | +| _Immediately undoable_ | `true` | `CaptureUpdateAction.IMMEDIATELY` | Use for updates which should be captured. Should be used for most of the local updates. These updates will _immediately_ make it to the local undo / redo stacks. | +| _Eventually undoable_ | `false` (default) | `CaptureUpdateAction.EVENTUALLY` (default) | Use for updates which should not be captured immediately - likely exceptions which are part of some async multi-step process. Otherwise, all such updates would end up being captured with the next `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene` or internally by the editor. These updates will _eventually_ make it to the local undo / redo stacks. | +| _Never undoable_ | n/a | `CaptureUpdateAction.NEVER` | **NEW**: Previously there was no equivalent for this value. Now, it's recommended to use `CaptureUpdateAction.NEVER` for updates which should never be recorded, such as remote updates or scene initialization. These updates will _never_ make it to the local undo / redo stacks. | + +#### Other + +- `ExcalidrawTextElement.baseline` was removed and replaced with a vertical offset computation based on font metrics, performed on each text element re-render. In case of custom font usage, extend the `FONT_METRICS` object with the related properties. [#7693](https://github.com/excalidraw/excalidraw/pull/7693) - `ExcalidrawEmbeddableElement.validated` was removed and moved to private editor state. This should largely not affect your apps unless you were reading from this attribute. We keep validating embeddable urls internally, and the public [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateembeddable) still applies. [#7539](https://github.com/excalidraw/excalidraw/pull/7539) -- `ExcalidrawTextElement.baseline` was removed and replaced with a vertical offset computation based on font metrics, performed on each text element re-render. In case of custom font usage, extend the `FONT_METRICS` object with the related properties. +- Stats container CSS has changed, so if you're using `renderCustomStats`, you may need to adjust your styles to retain the same layout. [#8361](https://github.com/excalidraw/excalidraw/pull/8361) -- Create an `ESM` build for `@excalidraw/excalidraw`. The API is in progress and subject to change before stable release. There are some changes on how the package will be consumed +- `` triggers are now always merged with host app triggers, rendered through ``. `` no longer accepts any props other than children. [#8498](https://github.com/excalidraw/excalidraw/pull/8498) - #### Bundler +### Features - - CSS needs to be imported so you will need to import the css along with the excalidraw component +- Prefer user defined coordinates and dimensions when creating a frame using [`convertToExcalidrawElements`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/excalidraw-element-skeleton#converttoexcalidrawelements) [#8517](https://github.com/excalidraw/excalidraw/pull/8517) - ```js - import { Excalidraw } from "@excalidraw/excalidraw"; - import "@excalidraw/excalidraw/index.css"; - ``` +- `props.initialData` can now be a function that returns `ExcalidrawInitialDataState` or `Promise` [#8107](https://github.com/excalidraw/excalidraw/pull/8135) - - The `types` path is updated +- `MainMenu.DefaultItems.ToggleTheme` now supports `onSelect(theme: string)` callback, and optionally `allowSystemTheme: boolean` alongside `theme: string` to indicate you want to allow users to set to system theme (you need to handle this yourself) [#7853](https://github.com/excalidraw/excalidraw/pull/7853) - Instead of importing from `@excalidraw/excalidraw/types/`, you will need to import from `@excalidraw/excalidraw/dist/excalidraw` or `@excalidraw/excalidraw/dist/utils` depending on the types you are using. +- Add `useHandleLibrary`'s `opts.adapter` as the new recommended pattern to handle library initialization and persistence on library updates [#7655](https://github.com/excalidraw/excalidraw/pull/7655) - However this we will be fixing before stable release, so in case you want to try it out you will need to update the types for now. +- Add `useHandleLibrary`'s `opts.migrationAdapter` adapter to handle library migration during init, when migrating from one data store to another (e.g. from LocalStorage to IndexedDB) [#7655](https://github.com/excalidraw/excalidraw/pull/7655) - #### Browser +- Add `onPointerUp` prop [#7638](https://github.com/excalidraw/excalidraw/pull/7638) - - Since its `ESM` so now script type `module` can be used to load it and css needs to be loaded as well. +- Expose `getVisibleSceneBounds` helper to get scene bounds of visible canvas area [#7450](https://github.com/excalidraw/excalidraw/pull/7450) - ```html - - - ``` +- Soft-deprecate `useHandleLibrary`'s `opts.getInitialLibraryItems` in favor of `opts.adapter`. [#7655](https://github.com/excalidraw/excalidraw/pull/7655) -- `appState.openDialog` type was changed from `null | string` to `null | { name: string }`. [#7336](https://github.com/excalidraw/excalidraw/pull/7336) +- Extended `window.EXCALIDRAW_ASSET_PATH` to accept array of paths `string[]` as a value, allowing to specify multiple base `URL` fallbacks. [#8286](https://github.com/excalidraw/excalidraw/pull/8286) + +- Custom text metrics provider [#9121](https://github.com/excalidraw/excalidraw/pull/9121) + +- Add `props.onDuplicate` [#9117](https://github.com/excalidraw/excalidraw/pull/9117) + +- Change empty arrowhead icon [#9100](https://github.com/excalidraw/excalidraw/pull/9100) + +- Tweak slider colors to be more muted [#9076](https://github.com/excalidraw/excalidraw/pull/9076) + +- Improve library sidebar performance [#9060](https://github.com/excalidraw/excalidraw/pull/9060) + +- Implement custom Range component for opacity control [#9009](https://github.com/excalidraw/excalidraw/pull/9009) + +- Box select frame & children to allow resizing at the same time [#9031](https://github.com/excalidraw/excalidraw/pull/9031) + +- Allow installing libs from excal github [#9041](https://github.com/excalidraw/excalidraw/pull/9041) + +- Update jotai [#9015](https://github.com/excalidraw/excalidraw/pull/9015) + +- Do not delete frame children on frame delete [#9011](https://github.com/excalidraw/excalidraw/pull/9011) + +- Add action to wrap selected items in a frame [#9005](https://github.com/excalidraw/excalidraw/pull/9005) + +- Reintroduce `.excalidraw.png` default when embedding scene [#8979](https://github.com/excalidraw/excalidraw/pull/8979) + +- Add mimeTypes on file save [#8946](https://github.com/excalidraw/excalidraw/pull/8946) + +- Add crowfoot to arrowheads [#8942](https://github.com/excalidraw/excalidraw/pull/8942) + +- Make HTML attribute sanitization stricter [#8977](https://github.com/excalidraw/excalidraw/pull/8977) + +- Validate library install urls [#8976](https://github.com/excalidraw/excalidraw/pull/8976) + +- Cleanup svg export and move payload to `` [#8975](https://github.com/excalidraw/excalidraw/pull/8975) + +- Use stats panel to crop [#8848](https://github.com/excalidraw/excalidraw/pull/8848) + +- Snap when cropping as well [#8831](https://github.com/excalidraw/excalidraw/pull/8831) + +- Update blog url [#8767](https://github.com/excalidraw/excalidraw/pull/8767) + +- Export scene to e+ on workspace creation/redemption [#8514](https://github.com/excalidraw/excalidraw/pull/8514) + +- Added sitemap & fixed robot txt [#8699](https://github.com/excalidraw/excalidraw/pull/8699) + +- Do not strip unknown element properties on restore [#8682](https://github.com/excalidraw/excalidraw/pull/8682) + +- Added reddit links as embeddable [#8099](https://github.com/excalidraw/excalidraw/pull/8099) + +- Self-hosting existing google fonts [#8540](https://github.com/excalidraw/excalidraw/pull/8540) + +- Flip arrowheads if only arrow(s) selected [#8525](https://github.com/excalidraw/excalidraw/pull/8525) + +- Common elbow mid segments [#8440](https://github.com/excalidraw/excalidraw/pull/8440) + +- Merge search sidebar back to default sidebar [#8497](https://github.com/excalidraw/excalidraw/pull/8497) + +- Smarter zooming when scrolling to match & only match on search/switch [#8488](https://github.com/excalidraw/excalidraw/pull/8488) + +- Reset copyStatus on export dialog settings change [#8443](https://github.com/excalidraw/excalidraw/pull/8443) + +- Tweak copy button success animation [#8441](https://github.com/excalidraw/excalidraw/pull/8441) + +- Enable panning/zoom while in wysiwyg [#8437](https://github.com/excalidraw/excalidraw/pull/8437) + +- Visual debugger [#8344](https://github.com/excalidraw/excalidraw/pull/8344) + +- Improve elbow arrow keyboard move [#8392](https://github.com/excalidraw/excalidraw/pull/8392) + +- Rewrite d2c to not require token [#8269](https://github.com/excalidraw/excalidraw/pull/8269) + +- Split `gridSize` from enabled state & support custom `gridStep` [#8364](https://github.com/excalidraw/excalidraw/pull/8364) + +- Improve zoom-to-content when creating flowchart [#8368](https://github.com/excalidraw/excalidraw/pull/8368) + +- Stats popup style tweaks [#8361](https://github.com/excalidraw/excalidraw/pull/8361) + +- Remove automatic frame naming [#8302](https://github.com/excalidraw/excalidraw/pull/8302) + +- Ability to debug the state of fractional indices [#8235](https://github.com/excalidraw/excalidraw/pull/8235) + +- Improve mermaid detection on paste [#8287](https://github.com/excalidraw/excalidraw/pull/8287) + +- Upgrade mermaid-to-excalidraw to v1.1.0 [#8226](https://github.com/excalidraw/excalidraw/pull/8226) + +- Bump max file size [#8220](https://github.com/excalidraw/excalidraw/pull/8220) + +- Smarter preferred lang detection [#8205](https://github.com/excalidraw/excalidraw/pull/8205) + +- Support Stats bound text `fontSize` editing [#8187](https://github.com/excalidraw/excalidraw/pull/8187) + +- Paste as mermaid if applicable [#8116](https://github.com/excalidraw/excalidraw/pull/8116) + +- Stop autoselecting text on text edit on mobile [#8076](https://github.com/excalidraw/excalidraw/pull/8076) + +- Create new text with width [#8038](https://github.com/excalidraw/excalidraw/pull/8038) + +- Wrap long text when pasting [#8026](https://github.com/excalidraw/excalidraw/pull/8026) + +- Upgrade to mermaid-to-excalidraw v1 🚀 [#8022](https://github.com/excalidraw/excalidraw/pull/8022) + +- Rerender canvas on focus [#8035](https://github.com/excalidraw/excalidraw/pull/8035) + +- Add missing `type="button"` [#8030](https://github.com/excalidraw/excalidraw/pull/8030) + +- Add install-PWA to command palette [#7935](https://github.com/excalidraw/excalidraw/pull/7935) + +- Tweak a few icons & add line editor button to side panel [#7990](https://github.com/excalidraw/excalidraw/pull/7990) + +- Allow binding only via linear element ends [#7946](https://github.com/excalidraw/excalidraw/pull/7946) + +- Resize elements from the sides [#7855](https://github.com/excalidraw/excalidraw/pull/7855) + +- Record freedraw tool selection to history [#7949](https://github.com/excalidraw/excalidraw/pull/7949) + +- Export reconciliation [#7917](https://github.com/excalidraw/excalidraw/pull/7917) + +- Add "toggle grid" to command palette [#7887](https://github.com/excalidraw/excalidraw/pull/7887) + +- Fractional indexing [#7359](https://github.com/excalidraw/excalidraw/pull/7359) + +- Show firefox-compatible command palette shortcut alias [#7825](https://github.com/excalidraw/excalidraw/pull/7825) + +- Upgrade mermaid-to-excalidraw to 0.3.0 [#7819](https://github.com/excalidraw/excalidraw/pull/7819) + +- Support to not render remote cursor & username [#7130](https://github.com/excalidraw/excalidraw/pull/7130) + +- Expose more collaborator status icons [#7777](https://github.com/excalidraw/excalidraw/pull/7777) + +- Close dropdown on escape [#7750](https://github.com/excalidraw/excalidraw/pull/7750) + +- Text measurements based on font metrics [#7693](https://github.com/excalidraw/excalidraw/pull/7693) + +- Improve collab error notification [#7741](https://github.com/excalidraw/excalidraw/pull/7741) + +- Grouped together Undo and Redo buttons on mobile [#9109](https://github.com/excalidraw/excalidraw/pull/9109) + +- Load old library if migration fails + +- Change LibraryPersistenceAdapter `load()` `source` -> `priority` + +### Fixes + +- Fix inconsistency in resizing while maintaining aspect ratio [#9116](https://github.com/excalidraw/excalidraw/pull/9116) + +- IFrame and elbow arrow interaction fix [#9101](https://github.com/excalidraw/excalidraw/pull/9101) + +- Duplicating/removing frame while children selected [#9079](https://github.com/excalidraw/excalidraw/pull/9079) + +- Elbow arrow z-index binding [#9067](https://github.com/excalidraw/excalidraw/pull/9067) + +- Library item checkbox style regression [#9080](https://github.com/excalidraw/excalidraw/pull/9080) + +- Elbow arrow orthogonality [#9073](https://github.com/excalidraw/excalidraw/pull/9073) + +- Button bg CSS variable leaking into other styles [#9075](https://github.com/excalidraw/excalidraw/pull/9075) + +- Fonts not loading on export (again) [#9064](https://github.com/excalidraw/excalidraw/pull/9064) + +- Merge server-side fonts with liberation sans [#9052](https://github.com/excalidraw/excalidraw/pull/9052) + +- Hyperlinks html entities [#9063](https://github.com/excalidraw/excalidraw/pull/9063) + +- Remove flushSync to fix flickering [#9057](https://github.com/excalidraw/excalidraw/pull/9057) + +- Excalidraw issue #9045 flowcharts: align attributes of new node [#9047](https://github.com/excalidraw/excalidraw/pull/9047) + +- Align arrows bound to elements excalidraw#8833 [#8998](https://github.com/excalidraw/excalidraw/pull/8998) + +- Update elbow arrow on font size change #8798 [#9002](https://github.com/excalidraw/excalidraw/pull/9002) + +- Undo for elbow arrows create incorrect routing [#9046](https://github.com/excalidraw/excalidraw/pull/9046) + +- Flowchart clones the current arrowhead [#8581](https://github.com/excalidraw/excalidraw/pull/8581) + +- Adding partial group to frame [#9014](https://github.com/excalidraw/excalidraw/pull/9014) + +- Do not refocus element link input on unrelated updates [#9037](https://github.com/excalidraw/excalidraw/pull/9037) + +- Arrow binding behaving unexpectedly on pointerup [#9010](https://github.com/excalidraw/excalidraw/pull/9010) + +- Change cursor by tool change immediately [#8212](https://github.com/excalidraw/excalidraw/pull/8212) + +- Package build fails on worker chunks [#8990](https://github.com/excalidraw/excalidraw/pull/8990) + +- Z-index clash in mobile UI [#8985](https://github.com/excalidraw/excalidraw/pull/8985) + +- Elbow arrows do not work within frames (issue: #8964) [#8969](https://github.com/excalidraw/excalidraw/pull/8969) + +- NormalizeSVG width and height from viewbox when size includes decimal points [#8939](https://github.com/excalidraw/excalidraw/pull/8939) + +- Make arrow binding area adapt to zoom levels [#8927](https://github.com/excalidraw/excalidraw/pull/8927) + +- Robust `state.editingFrame` teardown [#8941](https://github.com/excalidraw/excalidraw/pull/8941) + +- Regression on dragging a selected frame by its name [#8924](https://github.com/excalidraw/excalidraw/pull/8924) + +- Right-click paste for images in clipboard (Issue #8826) [#8845](https://github.com/excalidraw/excalidraw/pull/8845) + +- Fixed image transparency by adding alpha option to preserve image alpha channel [#8895](https://github.com/excalidraw/excalidraw/pull/8895) + +- Flush pending DOM updates before .focus() [#8901](https://github.com/excalidraw/excalidraw/pull/8901) + +- Normalize svg using only absolute sizing [#8854](https://github.com/excalidraw/excalidraw/pull/8854) + +- Element link selector dialog z-index & positioning [#8853](https://github.com/excalidraw/excalidraw/pull/8853) + +- Update old blog links & add canonical url [#8846](https://github.com/excalidraw/excalidraw/pull/8846) + +- Optimize frameToHighlight state change and snapLines state change [#8763](https://github.com/excalidraw/excalidraw/pull/8763) + +- Make some events expllicitly active to avoid console warnings [#8757](https://github.com/excalidraw/excalidraw/pull/8757) + +- Unify binding update options for `updateBoundElements()` [#8832](https://github.com/excalidraw/excalidraw/pull/8832) + +- Cleanup scripts and support upto node 22 [#8794](https://github.com/excalidraw/excalidraw/pull/8794) + +- Usage of `node12 which is deprecated` [#8791](https://github.com/excalidraw/excalidraw/pull/8791) + +- Remove manifest.json [#8783](https://github.com/excalidraw/excalidraw/pull/8783) + +- Load env vars correctly and set debug and linter flags to false explicitly in prod mode [#8770](https://github.com/excalidraw/excalidraw/pull/8770) + +- Console error in dev mode due to missing font path in non-prod [#8756](https://github.com/excalidraw/excalidraw/pull/8756) + +- Text pushes UI due to padding [#8745](https://github.com/excalidraw/excalidraw/pull/8745) + +- Fix trailing line whitespaces layout shift [#8714](https://github.com/excalidraw/excalidraw/pull/8714) + +- Load font faces in Safari manually [#8693](https://github.com/excalidraw/excalidraw/pull/8693) + +- Restore svg image DataURL dimensions [#8730](https://github.com/excalidraw/excalidraw/pull/8730) + +- Image cropping svg + compat mode [#8710](https://github.com/excalidraw/excalidraw/pull/8710) + +- Usage of `node12 which is deprecated` [#8709](https://github.com/excalidraw/excalidraw/pull/8709) + +- Image render perf [#8697](https://github.com/excalidraw/excalidraw/pull/8697) + +- Undo/redo action for international keyboard layouts [#8649](https://github.com/excalidraw/excalidraw/pull/8649) + +- Comic Shanns issues, new fonts structure [#8641](https://github.com/excalidraw/excalidraw/pull/8641) + +- Remove export-to-clip-as-svg shortcut for now [#8660](https://github.com/excalidraw/excalidraw/pull/8660) + +- Text disappearing on edit [#8558](https://github.com/excalidraw/excalidraw/pull/8558) (#8624) + +- Elbow arrow fixedpoint flipping now properly flips on inverted resize and flip action [#8324](https://github.com/excalidraw/excalidraw/pull/8324) + +- Svg and png frame clipping cases [#8515](https://github.com/excalidraw/excalidraw/pull/8515) + +- Re-route elbow arrows when pasted [#8448](https://github.com/excalidraw/excalidraw/pull/8448) + +- Buffer dependency [#8474](https://github.com/excalidraw/excalidraw/pull/8474) + +- Linear element complete button disabled [#8492](https://github.com/excalidraw/excalidraw/pull/8492) + +- Aspect ratio of distorted images are not preserved in SVG exports [#8061](https://github.com/excalidraw/excalidraw/pull/8061) + +- WYSIWYG editor padding is not normalized with zoom.value [#8481](https://github.com/excalidraw/excalidraw/pull/8481) + +- Improve canvas search scroll behavior further [#8491](https://github.com/excalidraw/excalidraw/pull/8491) + +- AddFiles clears the whole image cache when each file is added - regression from #8471 [#8490](https://github.com/excalidraw/excalidraw/pull/8490) + +- `select` instead of `focus` search input [#8483](https://github.com/excalidraw/excalidraw/pull/8483) + +- Image rendering issue when passed in `initialData` [#8471](https://github.com/excalidraw/excalidraw/pull/8471) + +- Add partial mocking [#8473](https://github.com/excalidraw/excalidraw/pull/8473) + +- PropertiesPopover maxWidth changing fixed units to relative units [#8456](https://github.com/excalidraw/excalidraw/pull/8456) + +- View mode wheel zooming does not work [#8452](https://github.com/excalidraw/excalidraw/pull/8452) + +- Fixed copy to clipboard button [#8426](https://github.com/excalidraw/excalidraw/pull/8426) + +- Context menu does not work after after dragging on StatsDragInput [#8386](https://github.com/excalidraw/excalidraw/pull/8386) + +- Perf regression in `getCommonBounds` [#8429](https://github.com/excalidraw/excalidraw/pull/8429) + +- Object snapping not working [#8381](https://github.com/excalidraw/excalidraw/pull/8381) + +- Reimplement rectangle intersection [#8367](https://github.com/excalidraw/excalidraw/pull/8367) + +- Round coordinates and sizes for rectangle intersection [#8366](https://github.com/excalidraw/excalidraw/pull/8366) + +- Text content with tab characters act different in view/edit [#8336](https://github.com/excalidraw/excalidraw/pull/8336) + +- Drawing from 0-dimension canvas [#8356](https://github.com/excalidraw/excalidraw/pull/8356) + +- Disable flowchart keybindings inside inputs [#8353](https://github.com/excalidraw/excalidraw/pull/8353) + +- Yet more patching of intersect code [#8352](https://github.com/excalidraw/excalidraw/pull/8352) + +- Missing `act()` in flowchart tests [#8354](https://github.com/excalidraw/excalidraw/pull/8354) + +- Z-index change by one causes app to freeze [#8314](https://github.com/excalidraw/excalidraw/pull/8314) + +- Patch over intersection calculation issue [#8350](https://github.com/excalidraw/excalidraw/pull/8350) + +- Point duplication in LEE on ALT+click [#8347](https://github.com/excalidraw/excalidraw/pull/8347) + +- Do not allow resizing unbound elbow arrows either [#8333](https://github.com/excalidraw/excalidraw/pull/8333) + +- Docker build in CI [#8312](https://github.com/excalidraw/excalidraw/pull/8312) + +- Duplicating arrow without bound elements throws error [#8316](https://github.com/excalidraw/excalidraw/pull/8316) + +- CVE-2023-45133 [#7988](https://github.com/excalidraw/excalidraw/pull/7988) + +- Throttle fractional indices validation [#8306](https://github.com/excalidraw/excalidraw/pull/8306) + +- Allow binding elbow arrows to frame children [#8309](https://github.com/excalidraw/excalidraw/pull/8309) + +- Skip registering font faces for local fonts [#8303](https://github.com/excalidraw/excalidraw/pull/8303) + +- Load fonts for `exportToCanvas` [#8298](https://github.com/excalidraw/excalidraw/pull/8298) + +- Re-add Cascadia Code with ligatures [#8291](https://github.com/excalidraw/excalidraw/pull/8291) + +- Linear elements not selected on pointer up from hitting its bound text [#8285](https://github.com/excalidraw/excalidraw/pull/8285) + +- Revert default element canvas padding change [#8266](https://github.com/excalidraw/excalidraw/pull/8266) + +- Freedraw jittering [#8238](https://github.com/excalidraw/excalidraw/pull/8238) + +- Messed up env variable [#8231](https://github.com/excalidraw/excalidraw/pull/8231) + +- Log allowed events [#8224](https://github.com/excalidraw/excalidraw/pull/8224) + +- Memory leak - scene.destroy() and window.launchQueue [#8198](https://github.com/excalidraw/excalidraw/pull/8198) + +- Stop updating text versions on init [#8191](https://github.com/excalidraw/excalidraw/pull/8191) + +- Add binding update to manual stat changes [#8183](https://github.com/excalidraw/excalidraw/pull/8183) + +- Binding after duplicating is now applied for both the old and duplicate shapes [#8185](https://github.com/excalidraw/excalidraw/pull/8185) + +- Incorrect point offsetting in LinearElementEditor.movePoints() [#8145](https://github.com/excalidraw/excalidraw/pull/8145) + +- Stats state leaking & race conds [#8177](https://github.com/excalidraw/excalidraw/pull/8177) + +- Only bind arrow [#8152](https://github.com/excalidraw/excalidraw/pull/8152) + +- Repair invalid binding on restore & fix type check [#8133](https://github.com/excalidraw/excalidraw/pull/8133) + +- Wysiwyg blur-submit on mobile [#8075](https://github.com/excalidraw/excalidraw/pull/8075) + +- Restore linear dimensions from points [#8062](https://github.com/excalidraw/excalidraw/pull/8062) + +- Lp plus url [#8056](https://github.com/excalidraw/excalidraw/pull/8056) + +- Fix twitter og image [#8050](https://github.com/excalidraw/excalidraw/pull/8050) + +- Flaky snapshot tests with floating point precision issues [#8049](https://github.com/excalidraw/excalidraw/pull/8049) + +- Always re-generate index of defined moved elements [#8040](https://github.com/excalidraw/excalidraw/pull/8040) + +- Undo/redo when exiting view mode [#8024](https://github.com/excalidraw/excalidraw/pull/8024) + +- Two finger panning is slow [#7849](https://github.com/excalidraw/excalidraw/pull/7849) + +- Compatible safari layers button svg [#8020](https://github.com/excalidraw/excalidraw/pull/8020) + +- Correctly resolve the package version [#8016](https://github.com/excalidraw/excalidraw/pull/8016) + +- Re-introduce wysiwyg width offset [#8014](https://github.com/excalidraw/excalidraw/pull/8014) + +- Font not rendered correctly on init [#8002](https://github.com/excalidraw/excalidraw/pull/8002) + +- Command palette filter [#7981](https://github.com/excalidraw/excalidraw/pull/7981) + +- Remove unused param from drawImagePlaceholder [#7991](https://github.com/excalidraw/excalidraw/pull/7991) + +- Docker build of Excalidraw app [#7430](https://github.com/excalidraw/excalidraw/pull/7430) + +- Typo in doc api [#7466](https://github.com/excalidraw/excalidraw/pull/7466) + +- Use Reflect API instead of Object.hasOwn [#7958](https://github.com/excalidraw/excalidraw/pull/7958) + +- CTRL/CMD & arrow point drag unbinds both sides [#6459](https://github.com/excalidraw/excalidraw/pull/6459) (#7877) + +- Z-index for laser pointer to be able to draw on embeds and such [#7918](https://github.com/excalidraw/excalidraw/pull/7918) + +- Double text rendering on edit [#7904](https://github.com/excalidraw/excalidraw/pull/7904) + +- Collision regressions from vector geometry rewrite [#7902](https://github.com/excalidraw/excalidraw/pull/7902) + +- Correct unit from 'eg' to 'deg' [#7891](https://github.com/excalidraw/excalidraw/pull/7891) + +- Allow same origin for all necessary domains [#7889](https://github.com/excalidraw/excalidraw/pull/7889) + +- Always make sure we render bound text above containers [#7880](https://github.com/excalidraw/excalidraw/pull/7880) + +- Parse embeddable srcdoc urls strictly [#7884](https://github.com/excalidraw/excalidraw/pull/7884) + +- Hit test for closed sharp curves [#7881](https://github.com/excalidraw/excalidraw/pull/7881) + +- Gist embed allowing unsafe html [#7883](https://github.com/excalidraw/excalidraw/pull/7883) + +- Command palette tweaks and fixes [#7876](https://github.com/excalidraw/excalidraw/pull/7876) + +- Include borders when testing insides of a shape [#7865](https://github.com/excalidraw/excalidraw/pull/7865) + +- External link not opening [#7859](https://github.com/excalidraw/excalidraw/pull/7859) + +- Add safe check for arrow points length in tranformToExcalidrawElements [#7863](https://github.com/excalidraw/excalidraw/pull/7863) + +- Import [#7869](https://github.com/excalidraw/excalidraw/pull/7869) + +- Theme toggle shortcut `event.code` [#7868](https://github.com/excalidraw/excalidraw/pull/7868) + +- Remove incorrect check from index.html [#7867](https://github.com/excalidraw/excalidraw/pull/7867) + +- Stop using lookbehind for backwards compat [#7824](https://github.com/excalidraw/excalidraw/pull/7824) + +- Ejs support in html files [#7822](https://github.com/excalidraw/excalidraw/pull/7822) + +- `excalidrawAPI.toggleSidebar` not switching between tabs correctly [#7821](https://github.com/excalidraw/excalidraw/pull/7821) + +- Correcting Assistant metrics [#7758](https://github.com/excalidraw/excalidraw/pull/7758) + +- Add missing font metrics for Assistant [#7752](https://github.com/excalidraw/excalidraw/pull/7752) + +- Export utils from excalidraw package in excalidraw library [#7731](https://github.com/excalidraw/excalidraw/pull/7731) + +- Split renderScene so that locales aren't imported unnecessarily [#7718](https://github.com/excalidraw/excalidraw/pull/7718) + +- Remove dependency of t in blob.ts [#7717](https://github.com/excalidraw/excalidraw/pull/7717) + +- Remove dependency of t from clipboard and image [#7712](https://github.com/excalidraw/excalidraw/pull/7712) + +- Remove scene hack from export.ts & remove pass elementsMap to getContainingFrame [#7713](https://github.com/excalidraw/excalidraw/pull/7713) + +- Decouple pure functions from hyperlink to prevent mermaid bundling [#7710](https://github.com/excalidraw/excalidraw/pull/7710) + +- Make bounds independent of scene [#7679](https://github.com/excalidraw/excalidraw/pull/7679) + +- Make LinearElementEditor independent of scene [#7670](https://github.com/excalidraw/excalidraw/pull/7670) + +- Remove scene from getElementAbsoluteCoords and dependent functions and use elementsMap [#7663](https://github.com/excalidraw/excalidraw/pull/7663) + +- Remove t from getDefaultAppState and allow name to be nullable [#7666](https://github.com/excalidraw/excalidraw/pull/7666) + +- Stop using structuredClone [#9128](https://github.com/excalidraw/excalidraw/pull/9128) + +### Refactor + +- Remove `defaultProps` [#9035](https://github.com/excalidraw/excalidraw/pull/9035) + +- Separate resizing logic from pointer [#8155](https://github.com/excalidraw/excalidraw/pull/8155) + +- `point()` -> `pointFrom()` to fix compiler issue [#8578](https://github.com/excalidraw/excalidraw/pull/8578) + +- Rename example `App.tsx` -> `ExampleApp.tsx` [#8501](https://github.com/excalidraw/excalidraw/pull/8501) + +- Remove unused env variable [#8457](https://github.com/excalidraw/excalidraw/pull/8457) + +- Rename `draggingElement` -> `newElement` [#8294](https://github.com/excalidraw/excalidraw/pull/8294) + +- Update collision from ga to vector geometry [#7636](https://github.com/excalidraw/excalidraw/pull/7636) + +### Performance + +- Improved pointer events related performance when the sidebar is docked with a large library open [#9086](https://github.com/excalidraw/excalidraw/pull/9086) + +- Reduce unnecessary frame clippings [#8980](https://github.com/excalidraw/excalidraw/pull/8980) + +- Improve new element drawing [#8340](https://github.com/excalidraw/excalidraw/pull/8340) + +- Cache the temp canvas created for labeled arrows [#8267](https://github.com/excalidraw/excalidraw/pull/8267) + +### Build + +- Set PWA flag in dev to false [#8788](https://github.com/excalidraw/excalidraw/pull/8788) + +- Add a flag VITE_APP_ENABLE_PWA for enabling pwa in dev environment [#8784](https://github.com/excalidraw/excalidraw/pull/8784) + +- Upgrade vite to 5.4.x, vitest to 2.x and related vite packages [#8459](https://github.com/excalidraw/excalidraw/pull/8459) + +- Add example apps `public` and vite `dev-dist` to eslintignore [#8326](https://github.com/excalidraw/excalidraw/pull/8326) + +- Add `rm:build`, `rm:node_modules` & `clean-install` scripts [#8323](https://github.com/excalidraw/excalidraw/pull/8323) + +- Update release script to build esm [#8308](https://github.com/excalidraw/excalidraw/pull/8308) + +- Run tests on master branch [#8072](https://github.com/excalidraw/excalidraw/pull/8072) + +- Specify `packageManager` field [#8010](https://github.com/excalidraw/excalidraw/pull/8010) + +- Enable consistent type imports eslint rule [#7992](https://github.com/excalidraw/excalidraw/pull/7992) + +- Export types for @excalidraw/utils [#7736](https://github.com/excalidraw/excalidraw/pull/7736) + +- Create ESM build for utils package 🥳 [#7500](https://github.com/excalidraw/excalidraw/pull/7500) + +- Upgrade to react@19 [#9182](https://github.com/excalidraw/excalidraw/pull/9182) ## 0.17.3 (2024-02-09) @@ -215,6 +845,8 @@ define: { ### Fixes +- `appState.openDialog` type was changed from `null | string` to `null | { name: string }`. [#7336](https://github.com/excalidraw/excalidraw/pull/7336) + - Image insertion bugs [#7278](https://github.com/excalidraw/excalidraw/pull/7278) - ExportToSvg to honor frameRendering also for name not only for frame itself [#7270](https://github.com/excalidraw/excalidraw/pull/7270) diff --git a/packages/excalidraw/README.md b/packages/excalidraw/README.md index 3e2f8efc6..a24b305fd 100644 --- a/packages/excalidraw/README.md +++ b/packages/excalidraw/README.md @@ -1,49 +1,45 @@ # Excalidraw -**Excalidraw** is exported as a component to directly embed in your projects. +**Excalidraw** is exported as a component to be directly embedded in your project. ## Installation -You can use `npm` +Use `npm` or `yarn` to install the package. ```bash npm install react react-dom @excalidraw/excalidraw -``` - -or via `yarn` - -```bash +# or yarn add react react-dom @excalidraw/excalidraw ``` -After installation you will see a folder `excalidraw-assets` and `excalidraw-assets-dev` in `dist` directory which contains the assets needed for this app in prod and dev mode respectively. +> **Note**: If you don't want to wait for the next stable release and try out the unreleased changes, use `@excalidraw/excalidraw@next`. -Move the folder `excalidraw-assets` and `excalidraw-assets-dev` to the path where your assets are served. +#### Self-hosting fonts -By default it will try to load the files from [`https://unpkg.com/@excalidraw/excalidraw/dist/`](https://unpkg.com/@excalidraw/excalidraw/dist) +By default, Excalidraw will try to download all the used fonts from the [CDN](https://esm.run/@excalidraw/excalidraw/dist/prod). -If you want to load assets from a different path you can set a variable `window.EXCALIDRAW_ASSET_PATH` depending on environment (for example if you have different URL's for dev and prod) to the url from where you want to load the assets. +For self-hosting purposes, you'll have to copy the content of the folder `node_modules/@excalidraw/excalidraw/dist/prod/fonts` to the path where your assets should be served from (i.e. `public/` directory in your project). In that case, you should also set `window.EXCALIDRAW_ASSET_PATH` to the very same path, i.e. `/` in case it's in the root: -#### Note +```js + +``` -**If you don't want to wait for the next stable release and try out the unreleased changes you can use `@excalidraw/excalidraw@next`.** - -## Dimensions of Excalidraw +### Dimensions of Excalidraw Excalidraw takes _100%_ of `width` and `height` of the containing block so make sure the container in which you render Excalidraw has non zero dimensions. -### Demo +## Demo -[Try here](https://codesandbox.io/s/excalidraw-ehlz3). +Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. ## Integration -Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/integration) +Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/integration). ## API -Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api) +Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api). ## Contributing -Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/contributing) +Head over to the [docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/contributing). diff --git a/packages/excalidraw/actions/actionAddToLibrary.ts b/packages/excalidraw/actions/actionAddToLibrary.ts index 93fddf0c4..3186e3bcb 100644 --- a/packages/excalidraw/actions/actionAddToLibrary.ts +++ b/packages/excalidraw/actions/actionAddToLibrary.ts @@ -3,7 +3,7 @@ import { deepCopyElement } from "../element/newElement"; import { randomId } from "../random"; import { t } from "../i18n"; import { LIBRARY_DISABLED_TYPES } from "../constants"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionAddToLibrary = register({ name: "addToLibrary", @@ -18,7 +18,7 @@ export const actionAddToLibrary = register({ for (const type of LIBRARY_DISABLED_TYPES) { if (selectedElements.some((element) => element.type === type)) { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: t(`errors.libraryElementTypeError.${type}`), @@ -42,7 +42,7 @@ export const actionAddToLibrary = register({ }) .then(() => { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, toast: { message: t("toast.addedToLibrary") }, @@ -51,7 +51,7 @@ export const actionAddToLibrary = register({ }) .catch((error) => { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: error.message, diff --git a/packages/excalidraw/actions/actionAlign.tsx b/packages/excalidraw/actions/actionAlign.tsx index 2acc12bfe..53e8e618b 100644 --- a/packages/excalidraw/actions/actionAlign.tsx +++ b/packages/excalidraw/actions/actionAlign.tsx @@ -16,7 +16,7 @@ import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import type { AppClassProperties, AppState, UIAppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; import { register } from "./register"; @@ -72,7 +72,7 @@ export const actionAlignTop = register({ position: "start", axis: "y", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -106,7 +106,7 @@ export const actionAlignBottom = register({ position: "end", axis: "y", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -140,7 +140,7 @@ export const actionAlignLeft = register({ position: "start", axis: "x", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -174,7 +174,7 @@ export const actionAlignRight = register({ position: "end", axis: "x", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -208,7 +208,7 @@ export const actionAlignVerticallyCentered = register({ position: "center", axis: "y", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData, app }) => ( @@ -238,7 +238,7 @@ export const actionAlignHorizontallyCentered = register({ position: "center", axis: "x", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData, app }) => ( diff --git a/packages/excalidraw/actions/actionBoundText.tsx b/packages/excalidraw/actions/actionBoundText.tsx index d6386ab27..b72ddee64 100644 --- a/packages/excalidraw/actions/actionBoundText.tsx +++ b/packages/excalidraw/actions/actionBoundText.tsx @@ -33,7 +33,7 @@ import type { Mutable } from "../utility-types"; import { arrayToMap, getFontString } from "../utils"; import { register } from "./register"; import { syncMovedIndices } from "../fractionalIndex"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { measureText } from "../element/textMeasurements"; export const actionUnbindText = register({ @@ -86,7 +86,7 @@ export const actionUnbindText = register({ return { elements, appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); @@ -163,7 +163,7 @@ export const actionBindText = register({ return { elements: pushTextAboveContainer(elements, container, textElement), appState: { ...appState, selectedElementIds: { [container.id]: true } }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); @@ -323,7 +323,7 @@ export const actionWrapTextInContainer = register({ ...appState, selectedElementIds: containerIds, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); diff --git a/packages/excalidraw/actions/actionCanvas.tsx b/packages/excalidraw/actions/actionCanvas.tsx index 3b3a12b98..903a6d84a 100644 --- a/packages/excalidraw/actions/actionCanvas.tsx +++ b/packages/excalidraw/actions/actionCanvas.tsx @@ -37,8 +37,8 @@ import { import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors"; import type { SceneBounds } from "../element/bounds"; import { setCursor } from "../cursor"; -import { StoreAction } from "../store"; -import { clamp, roundToStep } from "../../math"; +import { CaptureUpdateAction } from "../store"; +import { clamp, roundToStep } from "@excalidraw/math"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", @@ -54,9 +54,9 @@ export const actionChangeViewBackgroundColor = register({ perform: (_, appState, value) => { return { appState: { ...appState, ...value }, - storeAction: !!value.viewBackgroundColor - ? StoreAction.CAPTURE - : StoreAction.NONE, + captureUpdate: !!value.viewBackgroundColor + ? CaptureUpdateAction.IMMEDIATELY + : CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ elements, appState, updateData, appProps }) => { @@ -115,7 +115,7 @@ export const actionClearCanvas = register({ ? { ...appState.activeTool, type: "selection" } : appState.activeTool, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); @@ -140,7 +140,7 @@ export const actionZoomIn = register({ ), userToFollow: null, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ updateData, appState }) => ( @@ -181,7 +181,7 @@ export const actionZoomOut = register({ ), userToFollow: null, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ updateData, appState }) => ( @@ -222,7 +222,7 @@ export const actionResetZoom = register({ ), userToFollow: null, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ updateData, appState }) => ( @@ -341,7 +341,7 @@ export const zoomToFitBounds = ({ scrollY: centerScroll.scrollY, zoom: { value: newZoomValue }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }; @@ -472,7 +472,7 @@ export const actionToggleTheme = register({ theme: value || (appState.theme === THEME.LIGHT ? THEME.DARK : THEME.LIGHT), }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, keyTest: (event) => event.altKey && event.shiftKey && event.code === CODES.D, @@ -510,7 +510,7 @@ export const actionToggleEraserTool = register({ activeEmbeddable: null, activeTool, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => event.key === KEYS.E, @@ -549,7 +549,7 @@ export const actionToggleHandTool = register({ activeEmbeddable: null, activeTool, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/actionClipboard.tsx b/packages/excalidraw/actions/actionClipboard.tsx index c030b8150..fffe7b377 100644 --- a/packages/excalidraw/actions/actionClipboard.tsx +++ b/packages/excalidraw/actions/actionClipboard.tsx @@ -14,7 +14,7 @@ import { getTextFromElements, isTextElement } from "../element"; import { t } from "../i18n"; import { isFirefox } from "../constants"; import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionCopy = register({ name: "copy", @@ -32,7 +32,7 @@ export const actionCopy = register({ await copyToClipboard(elementsToCopy, app.files, event); } catch (error: any) { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: error.message, @@ -41,7 +41,7 @@ export const actionCopy = register({ } return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, // don't supply a shortcut since we handle this conditionally via onCopy event @@ -67,7 +67,7 @@ export const actionPaste = register({ if (isFirefox) { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: t("hints.firefox_clipboard_write"), @@ -76,7 +76,7 @@ export const actionPaste = register({ } return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: t("errors.asyncPasteFailedOnRead"), @@ -89,7 +89,7 @@ export const actionPaste = register({ } catch (error: any) { console.error(error); return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, errorMessage: t("errors.asyncPasteFailedOnParse"), @@ -98,7 +98,7 @@ export const actionPaste = register({ } return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, // don't supply a shortcut since we handle this conditionally via onCopy event @@ -125,7 +125,7 @@ export const actionCopyAsSvg = register({ perform: async (elements, appState, _data, app) => { if (!app.canvas) { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } @@ -167,7 +167,7 @@ export const actionCopyAsSvg = register({ }), }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } catch (error: any) { console.error(error); @@ -175,7 +175,7 @@ export const actionCopyAsSvg = register({ appState: { errorMessage: error.message, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } }, @@ -193,7 +193,7 @@ export const actionCopyAsPng = register({ perform: async (elements, appState, _data, app) => { if (!app.canvas) { return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } const selectedElements = app.scene.getSelectedElements({ @@ -227,7 +227,7 @@ export const actionCopyAsPng = register({ }), }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } catch (error: any) { console.error(error); @@ -236,7 +236,7 @@ export const actionCopyAsPng = register({ ...appState, errorMessage: error.message, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } }, @@ -263,7 +263,7 @@ export const copyText = register({ throw new Error(t("errors.copyToSystemClipboardFailed")); } return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, predicate: (elements, appState, _, app) => { diff --git a/packages/excalidraw/actions/actionCropEditor.tsx b/packages/excalidraw/actions/actionCropEditor.tsx index 24b64783b..643f666ba 100644 --- a/packages/excalidraw/actions/actionCropEditor.tsx +++ b/packages/excalidraw/actions/actionCropEditor.tsx @@ -1,6 +1,6 @@ import { register } from "./register"; import { cropIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; import { isImageElement } from "../element/typeChecks"; @@ -25,7 +25,7 @@ export const actionToggleCropEditor = register({ isCropping: false, croppingElementId: selectedElement.id, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, predicate: (elements, appState, _, app) => { diff --git a/packages/excalidraw/actions/actionDeleteSelected.tsx b/packages/excalidraw/actions/actionDeleteSelected.tsx index c66b2c024..c640f9256 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.tsx @@ -17,7 +17,7 @@ import { } from "../element/typeChecks"; import { updateActiveTool } from "../utils"; import { TrashIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { getContainerElement } from "../element/textElement"; import { getFrameChildren } from "../frame"; @@ -233,7 +233,7 @@ export const actionDeleteSelected = register({ ...nextAppState, editingLinearElement: null, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } @@ -265,7 +265,7 @@ export const actionDeleteSelected = register({ : [0], }, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } @@ -287,12 +287,12 @@ export const actionDeleteSelected = register({ multiElement: null, activeEmbeddable: null, }, - storeAction: isSomeElementSelected( + captureUpdate: isSomeElementSelected( getNonDeletedElements(elements), appState, ) - ? StoreAction.CAPTURE - : StoreAction.NONE, + ? CaptureUpdateAction.IMMEDIATELY + : CaptureUpdateAction.EVENTUALLY, }; }, keyTest: (event, appState, elements) => diff --git a/packages/excalidraw/actions/actionDistribute.tsx b/packages/excalidraw/actions/actionDistribute.tsx index 4b4166a7e..15d33b1f1 100644 --- a/packages/excalidraw/actions/actionDistribute.tsx +++ b/packages/excalidraw/actions/actionDistribute.tsx @@ -12,7 +12,7 @@ import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { CODES, KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import type { AppClassProperties, AppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; import { register } from "./register"; @@ -60,7 +60,7 @@ export const distributeHorizontally = register({ space: "between", axis: "x", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -91,7 +91,7 @@ export const distributeVertically = register({ space: "between", axis: "y", }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index 28dddd640..b28e831c8 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -42,7 +42,7 @@ import { excludeElementsInFramesFromSelection, getSelectedElements, } from "../scene/selection"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionDuplicateSelection = register({ name: "duplicateSelection", @@ -62,7 +62,7 @@ export const actionDuplicateSelection = register({ return { elements, appState: newAppState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } catch { return false; @@ -83,7 +83,7 @@ export const actionDuplicateSelection = register({ return { ...nextState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.D, diff --git a/packages/excalidraw/actions/actionElementLink.ts b/packages/excalidraw/actions/actionElementLink.ts index 504ad14fb..91469fd63 100644 --- a/packages/excalidraw/actions/actionElementLink.ts +++ b/packages/excalidraw/actions/actionElementLink.ts @@ -7,7 +7,7 @@ import { } from "../element/elementLink"; import { t } from "../i18n"; import { getSelectedElements } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { register } from "./register"; export const actionCopyElementLink = register({ @@ -42,14 +42,14 @@ export const actionCopyElementLink = register({ closable: true, }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } return { appState, elements, app, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } } catch (error: any) { @@ -60,7 +60,7 @@ export const actionCopyElementLink = register({ appState, elements, app, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, predicate: (elements, appState) => @@ -78,7 +78,12 @@ export const actionLinkToElement = register({ selectedElements.length !== 1 || !canCreateLinkFromElements(selectedElements) ) { - return { elements, appState, app, storeAction: StoreAction.NONE }; + return { + elements, + appState, + app, + captureUpdate: CaptureUpdateAction.EVENTUALLY, + }; } return { @@ -89,7 +94,7 @@ export const actionLinkToElement = register({ sourceElementId: getSelectedElements(elements, appState)[0].id, }, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, predicate: (elements, appState, appProps, app) => { diff --git a/packages/excalidraw/actions/actionElementLock.ts b/packages/excalidraw/actions/actionElementLock.ts index 5e5a91f5d..eba21f240 100644 --- a/packages/excalidraw/actions/actionElementLock.ts +++ b/packages/excalidraw/actions/actionElementLock.ts @@ -4,7 +4,7 @@ import { isFrameLikeElement } from "../element/typeChecks"; import type { ExcalidrawElement } from "../element/types"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { arrayToMap } from "../utils"; import { register } from "./register"; @@ -67,7 +67,7 @@ export const actionToggleElementLock = register({ ? null : appState.selectedLinearElement, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event, appState, elements, app) => { @@ -112,7 +112,7 @@ export const actionUnlockAllElements = register({ lockedElements.map((el) => [el.id, true]), ), }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, label: "labels.elementLock.unlockAll", diff --git a/packages/excalidraw/actions/actionExport.tsx b/packages/excalidraw/actions/actionExport.tsx index 224edf473..8d18acd89 100644 --- a/packages/excalidraw/actions/actionExport.tsx +++ b/packages/excalidraw/actions/actionExport.tsx @@ -19,7 +19,7 @@ import { nativeFileSystemSupported } from "../data/filesystem"; import type { Theme } from "../element/types"; import "../components/ToolIcon.scss"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionChangeProjectName = register({ name: "changeProjectName", @@ -28,7 +28,7 @@ export const actionChangeProjectName = register({ perform: (_elements, appState, value) => { return { appState: { ...appState, name: value }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ appState, updateData, appProps, data, app }) => ( @@ -48,7 +48,7 @@ export const actionChangeExportScale = register({ perform: (_elements, appState, value) => { return { appState: { ...appState, exportScale: value }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ elements: allElements, appState, updateData }) => { @@ -98,7 +98,7 @@ export const actionChangeExportBackground = register({ perform: (_elements, appState, value) => { return { appState: { ...appState, exportBackground: value }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ appState, updateData }) => ( @@ -118,7 +118,7 @@ export const actionChangeExportEmbedScene = register({ perform: (_elements, appState, value) => { return { appState: { ...appState, exportEmbedScene: value }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ appState, updateData }) => ( @@ -160,7 +160,7 @@ export const actionSaveToActiveFile = register({ : await saveAsJSON(elements, appState, app.files, app.getName()); return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, fileHandle, @@ -182,7 +182,7 @@ export const actionSaveToActiveFile = register({ } else { console.warn(error); } - return { storeAction: StoreAction.NONE }; + return { captureUpdate: CaptureUpdateAction.EVENTUALLY }; } }, keyTest: (event) => @@ -207,7 +207,7 @@ export const actionSaveFileToDisk = register({ app.getName(), ); return { - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, appState: { ...appState, openDialog: null, @@ -221,7 +221,7 @@ export const actionSaveFileToDisk = register({ } else { console.warn(error); } - return { storeAction: StoreAction.NONE }; + return { captureUpdate: CaptureUpdateAction.EVENTUALLY }; } }, keyTest: (event) => @@ -260,7 +260,7 @@ export const actionLoadScene = register({ elements: loadedElements, appState: loadedAppState, files, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } catch (error: any) { if (error?.name === "AbortError") { @@ -271,7 +271,7 @@ export const actionLoadScene = register({ elements, appState: { ...appState, errorMessage: error.message }, files: app.files, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } }, @@ -285,7 +285,7 @@ export const actionExportWithDarkMode = register({ perform: (_elements, appState, value) => { return { appState: { ...appState, exportWithDarkMode: value }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ appState, updateData }) => ( diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index 0637e304f..f2d8c0158 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -14,8 +14,8 @@ import { import { isBindingElement, isLinearElement } from "../element/typeChecks"; import type { AppState } from "../types"; import { resetCursor } from "../cursor"; -import { StoreAction } from "../store"; -import { pointFrom } from "../../math"; +import { CaptureUpdateAction } from "../store"; +import { pointFrom } from "@excalidraw/math"; import { isPathALoop } from "../shapes"; export const actionFinalize = register({ @@ -52,7 +52,7 @@ export const actionFinalize = register({ cursorButton: "up", editingLinearElement: null, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } } @@ -199,7 +199,7 @@ export const actionFinalize = register({ pendingImageElementId: null, }, // TODO: #7348 we should not capture everything, but if we don't, it leads to incosistencies -> revisit - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event, appState) => diff --git a/packages/excalidraw/actions/actionFlip.test.tsx b/packages/excalidraw/actions/actionFlip.test.tsx index 475aee71e..94e4721dd 100644 --- a/packages/excalidraw/actions/actionFlip.test.tsx +++ b/packages/excalidraw/actions/actionFlip.test.tsx @@ -2,7 +2,7 @@ import React from "react"; import { Excalidraw } from "../index"; import { render } from "../tests/test-utils"; import { API } from "../tests/helpers/api"; -import { pointFrom } from "../../math"; +import { pointFrom } from "@excalidraw/math"; import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip"; const { h } = window; diff --git a/packages/excalidraw/actions/actionFlip.ts b/packages/excalidraw/actions/actionFlip.ts index 34acc01bf..80149b877 100644 --- a/packages/excalidraw/actions/actionFlip.ts +++ b/packages/excalidraw/actions/actionFlip.ts @@ -18,7 +18,7 @@ import { } from "../element/binding"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { flipHorizontal, flipVertical } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { isArrowElement, isElbowArrow, @@ -47,7 +47,7 @@ export const actionFlipHorizontal = register({ app, ), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => event.shiftKey && event.code === CODES.H, @@ -72,7 +72,7 @@ export const actionFlipVertical = register({ app, ), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/actionFrame.ts b/packages/excalidraw/actions/actionFrame.ts index 4ff8243fc..ce05b533b 100644 --- a/packages/excalidraw/actions/actionFrame.ts +++ b/packages/excalidraw/actions/actionFrame.ts @@ -9,7 +9,7 @@ import { setCursorForShape } from "../cursor"; import { register } from "./register"; import { isFrameLikeElement } from "../element/typeChecks"; import { frameToolIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { getSelectedElements } from "../scene"; import { newFrameElement } from "../element/newElement"; import { getElementsInGroup } from "../groups"; @@ -49,14 +49,14 @@ export const actionSelectAllElementsInFrame = register({ return acc; }, {} as Record), }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } return { elements, appState, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, predicate: (elements, appState, _, app) => @@ -80,14 +80,14 @@ export const actionRemoveAllElementsFromFrame = register({ [selectedElement.id]: true, }, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; } return { elements, appState, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, predicate: (elements, appState, _, app) => @@ -109,7 +109,7 @@ export const actionupdateFrameRendering = register({ enabled: !appState.frameRendering.enabled, }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState: AppState) => appState.frameRendering.enabled, @@ -139,7 +139,7 @@ export const actionSetFrameAsActiveTool = register({ type: "frame", }), }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, keyTest: (event) => @@ -208,7 +208,7 @@ export const actionWrapSelectionInFrame = register({ appState: { selectedElementIds: { [frame.id]: true }, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); diff --git a/packages/excalidraw/actions/actionGroup.tsx b/packages/excalidraw/actions/actionGroup.tsx index f61986f82..4e98c59c7 100644 --- a/packages/excalidraw/actions/actionGroup.tsx +++ b/packages/excalidraw/actions/actionGroup.tsx @@ -34,7 +34,7 @@ import { replaceAllElementsInFrame, } from "../frame"; import { syncMovedIndices } from "../fractionalIndex"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; const allElementsInSameGroup = (elements: readonly ExcalidrawElement[]) => { if (elements.length >= 2) { @@ -84,7 +84,11 @@ export const actionGroup = register({ ); if (selectedElements.length < 2) { // nothing to group - return { appState, elements, storeAction: StoreAction.NONE }; + return { + appState, + elements, + captureUpdate: CaptureUpdateAction.EVENTUALLY, + }; } // if everything is already grouped into 1 group, there is nothing to do const selectedGroupIds = getSelectedGroupIds(appState); @@ -104,7 +108,11 @@ export const actionGroup = register({ ]); if (combinedSet.size === elementIdsInGroup.size) { // no incremental ids in the selected ids - return { appState, elements, storeAction: StoreAction.NONE }; + return { + appState, + elements, + captureUpdate: CaptureUpdateAction.EVENTUALLY, + }; } } @@ -170,7 +178,7 @@ export const actionGroup = register({ ), }, elements: reorderedElements, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, predicate: (elements, appState, _, app) => @@ -200,7 +208,11 @@ export const actionUngroup = register({ const elementsMap = arrayToMap(elements); if (groupIds.length === 0) { - return { appState, elements, storeAction: StoreAction.NONE }; + return { + appState, + elements, + captureUpdate: CaptureUpdateAction.EVENTUALLY, + }; } let nextElements = [...elements]; @@ -273,7 +285,7 @@ export const actionUngroup = register({ return { appState: { ...appState, ...updateAppState }, elements: nextElements, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/actionHistory.tsx b/packages/excalidraw/actions/actionHistory.tsx index eb52381ce..299a09f3d 100644 --- a/packages/excalidraw/actions/actionHistory.tsx +++ b/packages/excalidraw/actions/actionHistory.tsx @@ -10,7 +10,7 @@ import { arrayToMap } from "../utils"; import { isWindows } from "../constants"; import type { SceneElementsMap } from "../element/types"; import type { Store } from "../store"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { useEmitter } from "../hooks/useEmitter"; const executeHistoryAction = ( @@ -30,7 +30,7 @@ const executeHistoryAction = ( const result = updater(); if (!result) { - return { storeAction: StoreAction.NONE }; + return { captureUpdate: CaptureUpdateAction.EVENTUALLY }; } const [nextElementsMap, nextAppState] = result; @@ -39,11 +39,11 @@ const executeHistoryAction = ( return { appState: nextAppState, elements: nextElements, - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }; } - return { storeAction: StoreAction.NONE }; + return { captureUpdate: CaptureUpdateAction.EVENTUALLY }; }; type ActionCreator = (history: History, store: Store) => Action; diff --git a/packages/excalidraw/actions/actionLinearEditor.tsx b/packages/excalidraw/actions/actionLinearEditor.tsx index acde9b1e5..1f05755b5 100644 --- a/packages/excalidraw/actions/actionLinearEditor.tsx +++ b/packages/excalidraw/actions/actionLinearEditor.tsx @@ -2,7 +2,7 @@ import { DEFAULT_CATEGORIES } from "../components/CommandPalette/CommandPalette" import { LinearElementEditor } from "../element/linearElementEditor"; import { isElbowArrow, isLinearElement } from "../element/typeChecks"; import type { ExcalidrawLinearElement } from "../element/types"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { register } from "./register"; import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; @@ -51,7 +51,7 @@ export const actionToggleLinearEditor = register({ ...appState, editingLinearElement, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ appState, updateData, app }) => { diff --git a/packages/excalidraw/actions/actionLink.tsx b/packages/excalidraw/actions/actionLink.tsx index ae6197486..beb95d2c1 100644 --- a/packages/excalidraw/actions/actionLink.tsx +++ b/packages/excalidraw/actions/actionLink.tsx @@ -5,7 +5,7 @@ import { isEmbeddableElement } from "../element/typeChecks"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { getShortcutKey } from "../utils"; import { register } from "./register"; @@ -25,7 +25,7 @@ export const actionLink = register({ showHyperlinkPopup: "editor", openMenu: null, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, trackEvent: { category: "hyperlink", action: "click" }, diff --git a/packages/excalidraw/actions/actionMenu.tsx b/packages/excalidraw/actions/actionMenu.tsx index 84a5d1be4..9e71fe255 100644 --- a/packages/excalidraw/actions/actionMenu.tsx +++ b/packages/excalidraw/actions/actionMenu.tsx @@ -4,7 +4,7 @@ import { t } from "../i18n"; import { showSelectedShapeActions, getNonDeletedElements } from "../element"; import { register } from "./register"; import { KEYS } from "../keys"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionToggleCanvasMenu = register({ name: "toggleCanvasMenu", @@ -15,7 +15,7 @@ export const actionToggleCanvasMenu = register({ ...appState, openMenu: appState.openMenu === "canvas" ? null : "canvas", }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }), PanelComponent: ({ appState, updateData }) => ( ( event.key === KEYS.QUESTION_MARK, diff --git a/packages/excalidraw/actions/actionNavigate.tsx b/packages/excalidraw/actions/actionNavigate.tsx index c577e975f..48037200c 100644 --- a/packages/excalidraw/actions/actionNavigate.tsx +++ b/packages/excalidraw/actions/actionNavigate.tsx @@ -7,7 +7,7 @@ import { microphoneMutedIcon, } from "../components/icons"; import { t } from "../i18n"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import type { Collaborator } from "../types"; import { register } from "./register"; import clsx from "clsx"; @@ -28,7 +28,7 @@ export const actionGoToCollaborator = register({ ...appState, userToFollow: null, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } @@ -42,7 +42,7 @@ export const actionGoToCollaborator = register({ // Close mobile menu openMenu: appState.openMenu === "canvas" ? null : appState.openMenu, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ updateData, data, appState }) => { diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 1552fc0c8..0c2ad3bab 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useRef, useState } from "react"; import type { AppClassProperties, AppState, Primitive } from "../types"; -import type { StoreActionType } from "../store"; +import type { CaptureUpdateActionType } from "../store"; import { DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS, @@ -109,7 +109,7 @@ import { tupleToCoors, } from "../utils"; import { register } from "./register"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { Fonts, getLineHeight } from "../fonts"; import { bindLinearElement, @@ -119,8 +119,8 @@ import { updateBoundElements, } from "../element/binding"; import { LinearElementEditor } from "../element/linearElementEditor"; -import type { LocalPoint } from "../../math"; -import { pointFrom } from "../../math"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; import { Range } from "../components/Range"; const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1; @@ -271,7 +271,7 @@ const changeFontSize = ( ? [...newFontSizes][0] : fallbackValue ?? appState.currentItemFontSize, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }; @@ -301,9 +301,9 @@ export const actionChangeStrokeColor = register({ ...appState, ...value, }, - storeAction: !!value.currentItemStrokeColor - ? StoreAction.CAPTURE - : StoreAction.NONE, + captureUpdate: !!value.currentItemStrokeColor + ? CaptureUpdateAction.IMMEDIATELY + : CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ elements, appState, updateData, appProps }) => ( @@ -347,9 +347,9 @@ export const actionChangeBackgroundColor = register({ ...appState, ...value, }, - storeAction: !!value.currentItemBackgroundColor - ? StoreAction.CAPTURE - : StoreAction.NONE, + captureUpdate: !!value.currentItemBackgroundColor + ? CaptureUpdateAction.IMMEDIATELY + : CaptureUpdateAction.EVENTUALLY, }; }, PanelComponent: ({ elements, appState, updateData, appProps }) => ( @@ -393,7 +393,7 @@ export const actionChangeFillStyle = register({ }), ), appState: { ...appState, currentItemFillStyle: value }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => { @@ -466,7 +466,7 @@ export const actionChangeStrokeWidth = register({ }), ), appState: { ...appState, currentItemStrokeWidth: value }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => ( @@ -521,7 +521,7 @@ export const actionChangeSloppiness = register({ }), ), appState: { ...appState, currentItemRoughness: value }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => ( @@ -572,7 +572,7 @@ export const actionChangeStrokeStyle = register({ }), ), appState: { ...appState, currentItemStrokeStyle: value }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => ( @@ -627,7 +627,7 @@ export const actionChangeOpacity = register({ true, ), appState: { ...appState, currentItemOpacity: value }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => ( @@ -802,22 +802,23 @@ export const actionChangeFontFamily = register({ ...appState, ...nextAppState, }, - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }; } const { currentItemFontFamily, currentHoveredFontFamily } = value; - let nexStoreAction: StoreActionType = StoreAction.NONE; + let nextCaptureUpdateAction: CaptureUpdateActionType = + CaptureUpdateAction.EVENTUALLY; let nextFontFamily: FontFamilyValues | undefined; let skipOnHoverRender = false; if (currentItemFontFamily) { nextFontFamily = currentItemFontFamily; - nexStoreAction = StoreAction.CAPTURE; + nextCaptureUpdateAction = CaptureUpdateAction.IMMEDIATELY; } else if (currentHoveredFontFamily) { nextFontFamily = currentHoveredFontFamily; - nexStoreAction = StoreAction.NONE; + nextCaptureUpdateAction = CaptureUpdateAction.EVENTUALLY; const selectedTextElements = getSelectedElements(elements, appState, { includeBoundTextElement: true, @@ -850,7 +851,7 @@ export const actionChangeFontFamily = register({ ...appState, ...nextAppState, }, - storeAction: nexStoreAction, + captureUpdate: nextCaptureUpdateAction, }; if (nextFontFamily && !skipOnHoverRender) { @@ -1175,7 +1176,7 @@ export const actionChangeTextAlign = register({ ...appState, currentItemTextAlign: value, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData, app }) => { @@ -1265,7 +1266,7 @@ export const actionChangeVerticalAlign = register({ appState: { ...appState, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData, app }) => { @@ -1350,7 +1351,7 @@ export const actionChangeRoundness = register({ ...appState, currentItemRoundness: value, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => { @@ -1509,7 +1510,7 @@ export const actionChangeArrowhead = register({ ? "currentItemStartArrowhead" : "currentItemEndArrowhead"]: value.type, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => { @@ -1721,7 +1722,7 @@ export const actionChangeArrowType = register({ return { elements: newElements, appState: newState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, PanelComponent: ({ elements, appState, updateData }) => { diff --git a/packages/excalidraw/actions/actionSelectAll.ts b/packages/excalidraw/actions/actionSelectAll.ts index f8f9b775f..61c278053 100644 --- a/packages/excalidraw/actions/actionSelectAll.ts +++ b/packages/excalidraw/actions/actionSelectAll.ts @@ -6,7 +6,7 @@ import type { ExcalidrawElement } from "../element/types"; import { isLinearElement } from "../element/typeChecks"; import { LinearElementEditor } from "../element/linearElementEditor"; import { selectAllIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionSelectAll = register({ name: "selectAll", @@ -50,7 +50,7 @@ export const actionSelectAll = register({ ? new LinearElementEditor(elements[0]) : null, }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => event[KEYS.CTRL_OR_CMD] && event.key === KEYS.A, diff --git a/packages/excalidraw/actions/actionStyles.ts b/packages/excalidraw/actions/actionStyles.ts index 1a17bf9de..01f804062 100644 --- a/packages/excalidraw/actions/actionStyles.ts +++ b/packages/excalidraw/actions/actionStyles.ts @@ -23,7 +23,7 @@ import { import { getSelectedElements } from "../scene"; import type { ExcalidrawTextElement } from "../element/types"; import { paintIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { getLineHeight } from "../fonts"; // `copiedStyles` is exported only for tests. @@ -53,7 +53,7 @@ export const actionCopyStyles = register({ ...appState, toast: { message: t("toast.copyStyles") }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, keyTest: (event) => @@ -70,7 +70,7 @@ export const actionPasteStyles = register({ const pastedElement = elementsCopied[0]; const boundTextElement = elementsCopied[1]; if (!isExcalidrawElement(pastedElement)) { - return { elements, storeAction: StoreAction.NONE }; + return { elements, captureUpdate: CaptureUpdateAction.EVENTUALLY }; } const selectedElements = getSelectedElements(elements, appState, { @@ -159,7 +159,7 @@ export const actionPasteStyles = register({ } return element; }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/actionTextAutoResize.ts b/packages/excalidraw/actions/actionTextAutoResize.ts index cbf9684e4..29f54c9a7 100644 --- a/packages/excalidraw/actions/actionTextAutoResize.ts +++ b/packages/excalidraw/actions/actionTextAutoResize.ts @@ -2,7 +2,7 @@ import { isTextElement } from "../element"; import { newElementWith } from "../element/mutateElement"; import { measureText } from "../element/textMeasurements"; import { getSelectedElements } from "../scene"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import type { AppClassProperties } from "../types"; import { getFontString } from "../utils"; import { register } from "./register"; @@ -42,7 +42,7 @@ export const actionTextAutoResize = register({ } return element; }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, }); diff --git a/packages/excalidraw/actions/actionToggleGridMode.tsx b/packages/excalidraw/actions/actionToggleGridMode.tsx index 3ab4c4ff9..69d657057 100644 --- a/packages/excalidraw/actions/actionToggleGridMode.tsx +++ b/packages/excalidraw/actions/actionToggleGridMode.tsx @@ -2,7 +2,7 @@ import { CODES, KEYS } from "../keys"; import { register } from "./register"; import type { AppState } from "../types"; import { gridIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionToggleGridMode = register({ name: "gridMode", @@ -21,7 +21,7 @@ export const actionToggleGridMode = register({ gridModeEnabled: !this.checked!(appState), objectsSnapModeEnabled: false, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState: AppState) => appState.gridModeEnabled, diff --git a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx index e27decf46..1ae3cbe0b 100644 --- a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx +++ b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx @@ -1,6 +1,6 @@ import { magnetIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { register } from "./register"; export const actionToggleObjectsSnapMode = register({ @@ -19,7 +19,7 @@ export const actionToggleObjectsSnapMode = register({ objectsSnapModeEnabled: !this.checked!(appState), gridModeEnabled: false, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState) => appState.objectsSnapModeEnabled, diff --git a/packages/excalidraw/actions/actionToggleSearchMenu.ts b/packages/excalidraw/actions/actionToggleSearchMenu.ts index 02a58cd2b..9261e79c4 100644 --- a/packages/excalidraw/actions/actionToggleSearchMenu.ts +++ b/packages/excalidraw/actions/actionToggleSearchMenu.ts @@ -2,7 +2,7 @@ import { KEYS } from "../keys"; import { register } from "./register"; import type { AppState } from "../types"; import { searchIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants"; export const actionToggleSearchMenu = register({ @@ -29,7 +29,7 @@ export const actionToggleSearchMenu = register({ if (searchInput?.matches(":focus")) { return { appState: { ...appState, openSidebar: null }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; } @@ -44,7 +44,7 @@ export const actionToggleSearchMenu = register({ openSidebar: { name: DEFAULT_SIDEBAR.name, tab: CANVAS_SEARCH_TAB }, openDialog: null, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState: AppState) => appState.gridModeEnabled, diff --git a/packages/excalidraw/actions/actionToggleStats.tsx b/packages/excalidraw/actions/actionToggleStats.tsx index 45402e8ad..e28d099ae 100644 --- a/packages/excalidraw/actions/actionToggleStats.tsx +++ b/packages/excalidraw/actions/actionToggleStats.tsx @@ -1,7 +1,7 @@ import { register } from "./register"; import { CODES, KEYS } from "../keys"; import { abacusIcon } from "../components/icons"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionToggleStats = register({ name: "stats", @@ -17,7 +17,7 @@ export const actionToggleStats = register({ ...appState, stats: { ...appState.stats, open: !this.checked!(appState) }, }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState) => appState.stats.open, diff --git a/packages/excalidraw/actions/actionToggleViewMode.tsx b/packages/excalidraw/actions/actionToggleViewMode.tsx index 87dbb94ea..cae3b095e 100644 --- a/packages/excalidraw/actions/actionToggleViewMode.tsx +++ b/packages/excalidraw/actions/actionToggleViewMode.tsx @@ -1,6 +1,6 @@ import { eyeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { register } from "./register"; export const actionToggleViewMode = register({ @@ -19,7 +19,7 @@ export const actionToggleViewMode = register({ ...appState, viewModeEnabled: !this.checked!(appState), }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState) => appState.viewModeEnabled, diff --git a/packages/excalidraw/actions/actionToggleZenMode.tsx b/packages/excalidraw/actions/actionToggleZenMode.tsx index 86261443f..31afd3f3a 100644 --- a/packages/excalidraw/actions/actionToggleZenMode.tsx +++ b/packages/excalidraw/actions/actionToggleZenMode.tsx @@ -1,6 +1,6 @@ import { coffeeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; import { register } from "./register"; export const actionToggleZenMode = register({ @@ -19,7 +19,7 @@ export const actionToggleZenMode = register({ ...appState, zenModeEnabled: !this.checked!(appState), }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, checked: (appState) => appState.zenModeEnabled, diff --git a/packages/excalidraw/actions/actionZindex.tsx b/packages/excalidraw/actions/actionZindex.tsx index 261b4ab78..4097b2df1 100644 --- a/packages/excalidraw/actions/actionZindex.tsx +++ b/packages/excalidraw/actions/actionZindex.tsx @@ -15,7 +15,7 @@ import { SendToBackIcon, } from "../components/icons"; import { isDarwin } from "../constants"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; export const actionSendBackward = register({ name: "sendBackward", @@ -27,7 +27,7 @@ export const actionSendBackward = register({ return { elements: moveOneLeft(elements, appState), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyPriority: 40, @@ -57,7 +57,7 @@ export const actionBringForward = register({ return { elements: moveOneRight(elements, appState), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyPriority: 40, @@ -87,7 +87,7 @@ export const actionSendToBack = register({ return { elements: moveAllLeft(elements, appState), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => @@ -125,7 +125,7 @@ export const actionBringToFront = register({ return { elements: moveAllRight(elements, appState), appState, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, keyTest: (event) => diff --git a/packages/excalidraw/actions/types.ts b/packages/excalidraw/actions/types.ts index 1627b2fca..71ac9f4ab 100644 --- a/packages/excalidraw/actions/types.ts +++ b/packages/excalidraw/actions/types.ts @@ -10,7 +10,7 @@ import type { BinaryFiles, UIAppState, } from "../types"; -import type { StoreActionType } from "../store"; +import type { CaptureUpdateActionType } from "../store"; export type ActionSource = | "ui" @@ -25,7 +25,7 @@ export type ActionResult = elements?: readonly ExcalidrawElement[] | null; appState?: Partial | null; files?: BinaryFiles | null; - storeAction: StoreActionType; + captureUpdate: CaptureUpdateActionType; replaceFiles?: boolean; } | false; diff --git a/packages/excalidraw/charts.ts b/packages/excalidraw/charts.ts index 6e379c30a..65d17e228 100644 --- a/packages/excalidraw/charts.ts +++ b/packages/excalidraw/charts.ts @@ -1,5 +1,5 @@ -import type { Radians } from "../math"; -import { pointFrom } from "../math"; +import type { Radians } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; import { COLOR_PALETTE, DEFAULT_CHART_COLOR_INDEX, diff --git a/packages/excalidraw/clients.ts b/packages/excalidraw/clients.ts index afff1eeb6..29d240011 100644 --- a/packages/excalidraw/clients.ts +++ b/packages/excalidraw/clients.ts @@ -3,6 +3,7 @@ import { COLOR_VOICE_CALL, COLOR_WHITE, THEME, + UserIdleState, } from "./constants"; import { roundRect } from "./renderer/roundRect"; import type { InteractiveCanvasRenderConfig } from "./scene/types"; @@ -11,7 +12,6 @@ import type { InteractiveCanvasAppState, SocketId, } from "./types"; -import { UserIdleState } from "./types"; function hashToInteger(id: string) { let hash = 0; diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 326203359..15dabb5fa 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -236,8 +236,8 @@ import { getElementShape, isPathALoop, } from "../shapes"; -import { getSelectionBoxShape } from "../../utils/geometry/shape"; -import { isPointInShape } from "../../utils/collision"; +import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape"; +import { isPointInShape } from "@excalidraw/utils/collision"; import type { AppClassProperties, AppProps, @@ -412,7 +412,7 @@ import { COLOR_PALETTE } from "../colors"; import { ElementCanvasButton } from "./MagicButton"; import { MagicIcon, copyIcon, fullscreenIcon } from "./icons"; import FollowMode from "./FollowMode/FollowMode"; -import { Store, StoreAction } from "../store"; +import { Store, CaptureUpdateAction } from "../store"; import { AnimationFrameHandler } from "../animation-frame-handler"; import { AnimatedTrail } from "../animated-trail"; import { LaserTrails } from "../laser-trails"; @@ -441,7 +441,7 @@ import { getLinkDirectionFromKey, } from "../element/flowchart"; import { searchItemInFocusAtom } from "./SearchMenu"; -import type { LocalPoint, Radians } from "../../math"; +import type { LocalPoint, Radians } from "@excalidraw/math"; import { clamp, pointFrom, @@ -453,7 +453,7 @@ import { vectorSubtract, vectorDot, vectorNormalize, -} from "../../math"; +} from "@excalidraw/math"; import { cropElement } from "../element/cropElement"; import { wrapText } from "../element/textWrapping"; import { actionCopyElementLink } from "../actions/actionElementLink"; @@ -2097,12 +2097,12 @@ class App extends React.Component { if (shouldUpdateStrokeColor) { this.syncActionResult({ appState: { ...this.state, currentItemStrokeColor: color }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); } else { this.syncActionResult({ appState: { ...this.state, currentItemBackgroundColor: color }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); } } else { @@ -2116,7 +2116,7 @@ class App extends React.Component { } return el; }), - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); } }, @@ -2137,9 +2137,9 @@ class App extends React.Component { return; } - if (actionResult.storeAction === StoreAction.UPDATE) { + if (actionResult.captureUpdate === CaptureUpdateAction.NEVER) { this.store.shouldUpdateSnapshot(); - } else if (actionResult.storeAction === StoreAction.CAPTURE) { + } else if (actionResult.captureUpdate === CaptureUpdateAction.IMMEDIATELY) { this.store.shouldCaptureIncrement(); } @@ -2214,7 +2214,10 @@ class App extends React.Component { didUpdate = true; } - if (!didUpdate && actionResult.storeAction !== StoreAction.NONE) { + if ( + !didUpdate && + actionResult.captureUpdate !== CaptureUpdateAction.EVENTUALLY + ) { this.scene.triggerUpdate(); } }); @@ -2342,7 +2345,7 @@ class App extends React.Component { this.resetHistory(); this.syncActionResult({ ...scene, - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // clear the shape and image cache so that any images in initialData @@ -2822,7 +2825,7 @@ class App extends React.Component { this.state.editingLinearElement && !this.state.selectedElementIds[this.state.editingLinearElement.elementId] ) { - // defer so that the storeAction flag isn't reset via current update + // defer so that the shouldCaptureIncrement flag isn't reset via current update setTimeout(() => { // execute only if the condition still holds when the deferred callback // executes (it can be scheduled multiple times depending on how @@ -3883,12 +3886,25 @@ class App extends React.Component { elements?: SceneData["elements"]; appState?: Pick | null; collaborators?: SceneData["collaborators"]; - /** @default StoreAction.NONE */ - storeAction?: SceneData["storeAction"]; + /** + * Controls which updates should be captured by the `Store`. Captured updates are emmitted and listened to by other components, such as `History` for undo / redo purposes. + * + * - `CaptureUpdateAction.IMMEDIATELY`: Updates are immediately undoable. Use for most local updates. + * - `CaptureUpdateAction.NEVER`: Updates never make it to undo/redo stack. Use for remote updates or scene initialization. + * - `CaptureUpdateAction.EVENTUALLY`: Updates will be eventually be captured as part of a future increment. + * + * Check [API docs](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props/excalidraw-api#captureUpdate) for more details. + * + * @default CaptureUpdateAction.EVENTUALLY + */ + captureUpdate?: SceneData["captureUpdate"]; }) => { const nextElements = syncInvalidIndices(sceneData.elements ?? []); - if (sceneData.storeAction && sceneData.storeAction !== StoreAction.NONE) { + if ( + sceneData.captureUpdate && + sceneData.captureUpdate !== CaptureUpdateAction.EVENTUALLY + ) { const prevCommittedAppState = this.store.snapshot.appState; const prevCommittedElements = this.store.snapshot.elements; @@ -3905,12 +3921,12 @@ class App extends React.Component { // WARN: store action always performs deep clone of changed elements, for ephemeral remote updates (i.e. remote dragging, resizing, drawing) we might consider doing something smarter // do NOT schedule store actions (execute after re-render), as it might cause unexpected concurrency issues if not handled well - if (sceneData.storeAction === StoreAction.CAPTURE) { + if (sceneData.captureUpdate === CaptureUpdateAction.IMMEDIATELY) { this.store.captureIncrement( nextCommittedElements, nextCommittedAppState, ); - } else if (sceneData.storeAction === StoreAction.UPDATE) { + } else if (sceneData.captureUpdate === CaptureUpdateAction.NEVER) { this.store.updateSnapshot( nextCommittedElements, nextCommittedAppState, @@ -4590,7 +4606,9 @@ class App extends React.Component { if (!event.altKey) { if (this.flowChartNavigator.isExploring) { this.flowChartNavigator.clear(); - this.syncActionResult({ storeAction: StoreAction.CAPTURE }); + this.syncActionResult({ + captureUpdate: CaptureUpdateAction.IMMEDIATELY, + }); } } @@ -4637,7 +4655,9 @@ class App extends React.Component { } this.flowChartCreator.clear(); - this.syncActionResult({ storeAction: StoreAction.CAPTURE }); + this.syncActionResult({ + captureUpdate: CaptureUpdateAction.IMMEDIATELY, + }); } } }); @@ -6376,10 +6396,10 @@ class App extends React.Component { this.state, ), }, - storeAction: + captureUpdate: this.state.openDialog?.name === "elementLinkSelector" - ? StoreAction.NONE - : StoreAction.UPDATE, + ? CaptureUpdateAction.EVENTUALLY + : CaptureUpdateAction.NEVER, }); return; } @@ -9042,7 +9062,7 @@ class App extends React.Component { appState: { newElement: null, }, - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); return; @@ -9212,7 +9232,7 @@ class App extends React.Component { elements: this.scene .getElementsIncludingDeleted() .filter((el) => el.id !== resizingElement.id), - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); } @@ -10183,7 +10203,7 @@ class App extends React.Component { isLoading: false, }, replaceFiles: true, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); return; } catch (error: any) { @@ -10312,7 +10332,7 @@ class App extends React.Component { isLoading: false, }, replaceFiles: true, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); } else if (ret.type === MIME_TYPES.excalidrawlib) { await this.library diff --git a/packages/excalidraw/components/ImageExportDialog.tsx b/packages/excalidraw/components/ImageExportDialog.tsx index 8c225ab54..d06f4a842 100644 --- a/packages/excalidraw/components/ImageExportDialog.tsx +++ b/packages/excalidraw/components/ImageExportDialog.tsx @@ -23,7 +23,7 @@ import { nativeFileSystemSupported } from "../data/filesystem"; import type { NonDeletedExcalidrawElement } from "../element/types"; import { t } from "../i18n"; import { isSomeElementSelected } from "../scene"; -import { exportToCanvas } from "../../utils/export"; +import { exportToCanvas } from "@excalidraw/utils/export"; import { copyIcon, downloadIcon, helpIcon } from "./icons"; import { Dialog } from "./Dialog"; diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index 69bd398cb..ecd032bcd 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -1,12 +1,7 @@ import clsx from "clsx"; import React from "react"; import type { ActionManager } from "../actions/manager"; -import { - CLASSES, - DEFAULT_SIDEBAR, - LIBRARY_SIDEBAR_WIDTH, - TOOL_TYPE, -} from "../constants"; +import { CLASSES, DEFAULT_SIDEBAR, TOOL_TYPE } from "../constants"; import { showSelectedShapeActions } from "../element"; import type { NonDeletedExcalidrawElement } from "../element/types"; import type { Language } from "../i18n"; @@ -531,7 +526,7 @@ const LayerUI = ({ appState.openSidebar && isSidebarDocked && device.editor.canFitSidebar - ? { width: `calc(100% - ${LIBRARY_SIDEBAR_WIDTH}px)` } + ? { width: `calc(100% - var(--right-sidebar-width)px)` } : {} } > diff --git a/packages/excalidraw/components/PublishLibrary.tsx b/packages/excalidraw/components/PublishLibrary.tsx index f3d0fe1b4..fe68f880d 100644 --- a/packages/excalidraw/components/PublishLibrary.tsx +++ b/packages/excalidraw/components/PublishLibrary.tsx @@ -7,7 +7,7 @@ import { t } from "../i18n"; import Trans from "./Trans"; import type { LibraryItems, LibraryItem, UIAppState } from "../types"; -import { exportToCanvas, exportToSvg } from "../../utils/export"; +import { exportToCanvas, exportToSvg } from "@excalidraw/utils/export"; import { EDITOR_LS_KEYS, EXPORT_DATA_TYPES, diff --git a/packages/excalidraw/components/SearchMenu.tsx b/packages/excalidraw/components/SearchMenu.tsx index f9b3143f3..873de5adb 100644 --- a/packages/excalidraw/components/SearchMenu.tsx +++ b/packages/excalidraw/components/SearchMenu.tsx @@ -3,7 +3,7 @@ import { collapseDownIcon, upIcon, searchIcon } from "./icons"; import { TextField } from "./TextField"; import { Button } from "./Button"; import { useApp, useExcalidrawSetAppState } from "./App"; -import { debounce } from "lodash"; +import debounce from "lodash.debounce"; import type { AppClassProperties } from "../types"; import { isTextElement, newTextElement } from "../element"; import type { ExcalidrawTextElement } from "../element/types"; @@ -18,7 +18,7 @@ import { CLASSES, EVENT } from "../constants"; import { useStable } from "../hooks/useStable"; import "./SearchMenu.scss"; -import { round } from "../../math"; +import { round } from "@excalidraw/math"; import { measureText } from "../element/textMeasurements"; const searchQueryAtom = atom(""); diff --git a/packages/excalidraw/components/Sidebar/Sidebar.scss b/packages/excalidraw/components/Sidebar/Sidebar.scss index 2571d128f..c7776d1c6 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.scss +++ b/packages/excalidraw/components/Sidebar/Sidebar.scss @@ -30,7 +30,7 @@ overflow: hidden; border-radius: 0; - width: calc(#{$right-sidebar-width} - var(--space-factor) * 2); + width: calc(var(--right-sidebar-width) - var(--space-factor) * 2); border-left: 1px solid var(--sidebar-border-color); diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index 7c747d2f4..ad6c9fe41 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -136,6 +136,9 @@ export const SidebarInner = forwardRef( diff --git a/packages/excalidraw/components/Stats/Angle.tsx b/packages/excalidraw/components/Stats/Angle.tsx index b7a98a437..409476ada 100644 --- a/packages/excalidraw/components/Stats/Angle.tsx +++ b/packages/excalidraw/components/Stats/Angle.tsx @@ -8,8 +8,8 @@ import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable, updateBindings } from "./utils"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import type { Degrees } from "../../../math"; -import { degreesToRadians, radiansToDegrees } from "../../../math"; +import type { Degrees } from "@excalidraw/math"; +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface AngleProps { element: ExcalidrawElement; diff --git a/packages/excalidraw/components/Stats/Dimension.tsx b/packages/excalidraw/components/Stats/Dimension.tsx index 4e5a3825d..ce096d280 100644 --- a/packages/excalidraw/components/Stats/Dimension.tsx +++ b/packages/excalidraw/components/Stats/Dimension.tsx @@ -12,7 +12,7 @@ import { getUncroppedWidthAndHeight, } from "../../element/cropElement"; import { mutateElement } from "../../element/mutateElement"; -import { clamp, round } from "../../../math"; +import { clamp, round } from "@excalidraw/math"; interface DimensionDragInputProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/DragInput.tsx b/packages/excalidraw/components/Stats/DragInput.tsx index 77cc942cf..82d6419c0 100644 --- a/packages/excalidraw/components/Stats/DragInput.tsx +++ b/packages/excalidraw/components/Stats/DragInput.tsx @@ -8,7 +8,7 @@ import { useApp } from "../App"; import { InlineIcon } from "../InlineIcon"; import type { StatsInputProperty } from "./utils"; import { SMALLEST_DELTA } from "./utils"; -import { StoreAction } from "../../store"; +import { CaptureUpdateAction } from "../../store"; import type Scene from "../../scene/Scene"; import "./DragInput.scss"; @@ -132,7 +132,9 @@ const StatsDragInput = < originalAppState: appState, setInputValue: (value) => setInputValue(String(value)), }); - app.syncActionResult({ storeAction: StoreAction.CAPTURE }); + app.syncActionResult({ + captureUpdate: CaptureUpdateAction.IMMEDIATELY, + }); } }; @@ -276,7 +278,9 @@ const StatsDragInput = < false, ); - app.syncActionResult({ storeAction: StoreAction.CAPTURE }); + app.syncActionResult({ + captureUpdate: CaptureUpdateAction.IMMEDIATELY, + }); lastPointer = null; accumulatedChange = 0; diff --git a/packages/excalidraw/components/Stats/MultiAngle.tsx b/packages/excalidraw/components/Stats/MultiAngle.tsx index 6297cfe16..d9a78825a 100644 --- a/packages/excalidraw/components/Stats/MultiAngle.tsx +++ b/packages/excalidraw/components/Stats/MultiAngle.tsx @@ -9,8 +9,8 @@ import DragInput from "./DragInput"; import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable } from "./utils"; import type { AppState } from "../../types"; -import type { Degrees } from "../../../math"; -import { degreesToRadians, radiansToDegrees } from "../../../math"; +import type { Degrees } from "@excalidraw/math"; +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface MultiAngleProps { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Stats/MultiDimension.tsx b/packages/excalidraw/components/Stats/MultiDimension.tsx index c02e87089..04f193747 100644 --- a/packages/excalidraw/components/Stats/MultiDimension.tsx +++ b/packages/excalidraw/components/Stats/MultiDimension.tsx @@ -23,7 +23,7 @@ import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; import { getElementsInAtomicUnit } from "./utils"; import type { AtomicUnit } from "./utils"; import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; -import { pointFrom, type GlobalPoint } from "../../../math"; +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; interface MultiDimensionProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/MultiPosition.tsx b/packages/excalidraw/components/Stats/MultiPosition.tsx index 3b5db064e..8a29aa66d 100644 --- a/packages/excalidraw/components/Stats/MultiPosition.tsx +++ b/packages/excalidraw/components/Stats/MultiPosition.tsx @@ -13,7 +13,7 @@ import { useMemo } from "react"; import { getElementsInAtomicUnit, moveElement } from "./utils"; import type { AtomicUnit } from "./utils"; import type { AppState } from "../../types"; -import { pointFrom, pointRotateRads } from "../../../math"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; interface MultiPositionProps { property: "x" | "y"; diff --git a/packages/excalidraw/components/Stats/Position.tsx b/packages/excalidraw/components/Stats/Position.tsx index c2307cd6d..038e58ebc 100644 --- a/packages/excalidraw/components/Stats/Position.tsx +++ b/packages/excalidraw/components/Stats/Position.tsx @@ -4,7 +4,7 @@ import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, moveElement } from "./utils"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { clamp, pointFrom, pointRotateRads, round } from "../../../math"; +import { clamp, pointFrom, pointRotateRads, round } from "@excalidraw/math"; import { isImageElement } from "../../element/typeChecks"; import { getFlipAdjustedCropPosition, diff --git a/packages/excalidraw/components/Stats/index.tsx b/packages/excalidraw/components/Stats/index.tsx index 88a05f7df..2ccd93ca2 100644 --- a/packages/excalidraw/components/Stats/index.tsx +++ b/packages/excalidraw/components/Stats/index.tsx @@ -9,7 +9,7 @@ import type { } from "../../types"; import { CloseIcon } from "../icons"; import { Island } from "../Island"; -import { throttle } from "lodash"; +import throttle from "lodash.throttle"; import Dimension from "./Dimension"; import Angle from "./Angle"; import FontSize from "./FontSize"; @@ -30,7 +30,7 @@ import clsx from "clsx"; import "./Stats.scss"; import { isGridModeEnabled } from "../../snapping"; import { getUncroppedWidthAndHeight } from "../../element/cropElement"; -import { round } from "../../../math"; +import { round } from "@excalidraw/math"; import { frameAndChildrenSelectedTogether } from "../../frame"; interface StatsProps { diff --git a/packages/excalidraw/components/Stats/stats.test.tsx b/packages/excalidraw/components/Stats/stats.test.tsx index fc981ce6c..49d6a625f 100644 --- a/packages/excalidraw/components/Stats/stats.test.tsx +++ b/packages/excalidraw/components/Stats/stats.test.tsx @@ -24,8 +24,8 @@ import { getCommonBounds, isTextElement } from "../../element"; import { API } from "../../tests/helpers/api"; import { actionGroup } from "../../actions"; import { isInGroup } from "../../groups"; -import type { Degrees } from "../../../math"; -import { degreesToRadians, pointFrom, pointRotateRads } from "../../../math"; +import type { Degrees } from "@excalidraw/math"; +import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/components/Stats/utils.ts b/packages/excalidraw/components/Stats/utils.ts index 46c8cb982..61555baeb 100644 --- a/packages/excalidraw/components/Stats/utils.ts +++ b/packages/excalidraw/components/Stats/utils.ts @@ -1,5 +1,5 @@ -import type { Radians } from "../../../math"; -import { pointFrom, pointRotateRads } from "../../../math"; +import type { Radians } from "@excalidraw/math"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; import { bindOrUnbindLinearElements, updateBoundElements, diff --git a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx index a683d80ce..c77dfbf68 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx @@ -29,7 +29,7 @@ import { atom, useAtom } from "../../editor-jotai"; import { trackEvent } from "../../analytics"; import { InlineIcon } from "../InlineIcon"; import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; -import { isFiniteNumber } from "../../../math"; +import { isFiniteNumber } from "@excalidraw/math"; const MIN_PROMPT_LENGTH = 3; const MAX_PROMPT_LENGTH = 1000; diff --git a/packages/excalidraw/components/hyperlink/Hyperlink.tsx b/packages/excalidraw/components/hyperlink/Hyperlink.tsx index da187ef8d..4d3dce640 100644 --- a/packages/excalidraw/components/hyperlink/Hyperlink.tsx +++ b/packages/excalidraw/components/hyperlink/Hyperlink.tsx @@ -34,7 +34,7 @@ import { trackEvent } from "../../analytics"; import { useAppProps, useDevice, useExcalidrawAppState } from "../App"; import { isEmbeddableElement } from "../../element/typeChecks"; import { getLinkHandleFromCoords } from "./helpers"; -import { pointFrom, type GlobalPoint } from "../../../math"; +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; import { isElementLink } from "../../element/elementLink"; import "./Hyperlink.scss"; diff --git a/packages/excalidraw/components/hyperlink/helpers.ts b/packages/excalidraw/components/hyperlink/helpers.ts index 15c06a9f4..75c5dad9c 100644 --- a/packages/excalidraw/components/hyperlink/helpers.ts +++ b/packages/excalidraw/components/hyperlink/helpers.ts @@ -1,5 +1,5 @@ -import type { GlobalPoint, Radians } from "../../../math"; -import { pointFrom, pointRotateRads } from "../../../math"; +import type { GlobalPoint, Radians } from "@excalidraw/math"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; import { MIME_TYPES } from "../../constants"; import type { Bounds } from "../../element/bounds"; import { getElementAbsoluteCoords } from "../../element/bounds"; diff --git a/packages/excalidraw/constants.ts b/packages/excalidraw/constants.ts index b01dc98ee..616ced1a7 100644 --- a/packages/excalidraw/constants.ts +++ b/packages/excalidraw/constants.ts @@ -1,4 +1,3 @@ -import cssVariables from "./css/variables.module.scss"; import type { AppProps, AppState } from "./types"; import type { ExcalidrawElement, FontFamilyValues } from "./element/types"; import { COLOR_PALETTE } from "./colors"; @@ -269,7 +268,8 @@ export const IDLE_THRESHOLD = 60_000; // Report a user active each ACTIVE_THRESHOLD milliseconds export const ACTIVE_THRESHOLD = 3_000; -export const THEME_FILTER = cssVariables.themeFilter; +// duplicates --theme-filter, should be removed soon +export const THEME_FILTER = "invert(93%) hue-rotate(180deg)"; export const URL_QUERY_KEYS = { addLibrary: "addLibrary", @@ -304,8 +304,6 @@ export const MQ_MAX_HEIGHT_LANDSCAPE = 500; export const MQ_RIGHT_SIDEBAR_MIN_WIDTH = 1229; // ----------------------------------------------------------------------------- -export const LIBRARY_SIDEBAR_WIDTH = parseInt(cssVariables.rightSidebarWidth); - export const MAX_DECIMALS_FOR_SVG_EXPORT = 2; export const EXPORT_SCALES = [1, 2, 3]; @@ -461,3 +459,9 @@ export const ELEMENT_LINK_KEY = "element"; /** used in tests */ export const ORIG_ID = Symbol.for("__test__originalId__"); + +export enum UserIdleState { + ACTIVE = "active", + AWAY = "away", + IDLE = "idle", +} diff --git a/packages/excalidraw/css/theme.scss b/packages/excalidraw/css/theme.scss index a531d5bb7..fd6a8dacb 100644 --- a/packages/excalidraw/css/theme.scss +++ b/packages/excalidraw/css/theme.scss @@ -170,7 +170,7 @@ } &.theme--dark { - --theme-filter: #{$theme-filter}; + --theme-filter: invert(93%) hue-rotate(180deg); --button-destructive-bg-color: #5a0000; --button-destructive-color: #{$oc-red-3}; diff --git a/packages/excalidraw/css/variables.module.scss b/packages/excalidraw/css/variables.module.scss index 42e325a4c..c360c0dc6 100644 --- a/packages/excalidraw/css/variables.module.scss +++ b/packages/excalidraw/css/variables.module.scss @@ -188,11 +188,3 @@ box-shadow: 0 0 0 1px var(--color-brand-active); } } - -$theme-filter: "invert(93%) hue-rotate(180deg)"; -$right-sidebar-width: "302px"; - -:export { - themeFilter: unquote($theme-filter); - rightSidebarWidth: unquote($right-sidebar-width); -} diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 550b88071..837ca27de 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -57,8 +57,8 @@ import { getNormalizedGridStep, getNormalizedZoom, } from "../scene"; -import type { LocalPoint, Radians } from "../../math"; -import { isFiniteNumber, pointFrom } from "../../math"; +import type { LocalPoint, Radians } from "@excalidraw/math"; +import { isFiniteNumber, pointFrom } from "@excalidraw/math"; import { detectLineHeight } from "../element/textMeasurements"; type RestoredAppState = Omit< diff --git a/packages/excalidraw/data/transform.test.ts b/packages/excalidraw/data/transform.test.ts index 98a62daf7..a36af0c35 100644 --- a/packages/excalidraw/data/transform.test.ts +++ b/packages/excalidraw/data/transform.test.ts @@ -2,7 +2,7 @@ import { vi } from "vitest"; import type { ExcalidrawElementSkeleton } from "./transform"; import { convertToExcalidrawElements } from "./transform"; import type { ExcalidrawArrowElement } from "../element/types"; -import { pointFrom } from "../../math"; +import { pointFrom } from "@excalidraw/math"; const opts = { regenerateIds: false }; diff --git a/packages/excalidraw/data/transform.ts b/packages/excalidraw/data/transform.ts index f15de763c..023740cf1 100644 --- a/packages/excalidraw/data/transform.ts +++ b/packages/excalidraw/data/transform.ts @@ -53,7 +53,7 @@ import { randomId } from "../random"; import { syncInvalidIndices } from "../fractionalIndex"; import { getLineHeight } from "../fonts"; import { isArrowElement } from "../element/typeChecks"; -import { pointFrom, type LocalPoint } from "../../math"; +import { pointFrom, type LocalPoint } from "@excalidraw/math"; import { measureText, normalizeText } from "../element/textMeasurements"; export type ValidLinearElement = { diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 2ac8b7c69..d72b846d9 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -19,7 +19,7 @@ import type { import type { Bounds } from "./bounds"; import { getCenterForBounds } from "./bounds"; import type { AppState } from "../types"; -import { isPointOnShape } from "../../utils/collision"; +import { isPointOnShape } from "@excalidraw/utils/collision"; import { isArrowElement, isBindableElement, @@ -53,7 +53,7 @@ import { vectorToHeading, type Heading, } from "./heading"; -import type { LocalPoint, Radians } from "../../math"; +import type { LocalPoint, Radians } from "@excalidraw/math"; import { lineSegment, pointFrom, @@ -69,7 +69,7 @@ import { vectorCross, pointsEqual, lineSegmentIntersectionPoints, -} from "../../math"; +} from "@excalidraw/math"; import { intersectElementWithLineSegment } from "./collision"; import { distanceToBindableElement } from "./distance"; diff --git a/packages/excalidraw/element/bounds.test.ts b/packages/excalidraw/element/bounds.test.ts index ffa89bb3e..9d91d0925 100644 --- a/packages/excalidraw/element/bounds.test.ts +++ b/packages/excalidraw/element/bounds.test.ts @@ -1,5 +1,5 @@ -import type { LocalPoint } from "../../math"; -import { pointFrom } from "../../math"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; import { ROUNDNESS } from "../constants"; import { arrayToMap } from "../utils"; import { getElementAbsoluteCoords, getElementBounds } from "./bounds"; diff --git a/packages/excalidraw/element/bounds.ts b/packages/excalidraw/element/bounds.ts index 19cde12d5..6b5010370 100644 --- a/packages/excalidraw/element/bounds.ts +++ b/packages/excalidraw/element/bounds.ts @@ -30,7 +30,7 @@ import type { LineSegment, LocalPoint, Radians, -} from "../../math"; +} from "@excalidraw/math"; import { degreesToRadians, lineSegment, @@ -38,7 +38,7 @@ import { pointDistance, pointFromArray, pointRotateRads, -} from "../../math"; +} from "@excalidraw/math"; import type { Mutable } from "../utility-types"; export type RectangleBox = { diff --git a/packages/excalidraw/element/collision.ts b/packages/excalidraw/element/collision.ts index bbd89cfa5..b0a2ce9a5 100644 --- a/packages/excalidraw/element/collision.ts +++ b/packages/excalidraw/element/collision.ts @@ -8,9 +8,9 @@ import type { } from "./types"; import { getElementBounds } from "./bounds"; import type { FrameNameBounds } from "../types"; -import type { GeometricShape } from "../../utils/geometry/shape"; -import { getPolygonShape } from "../../utils/geometry/shape"; -import { isPointInShape, isPointOnShape } from "../../utils/collision"; +import type { GeometricShape } from "@excalidraw/utils/geometry/shape"; +import { getPolygonShape } from "@excalidraw/utils/geometry/shape"; +import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; import { isTransparent } from "../utils"; import { hasBoundTextElement, @@ -25,7 +25,7 @@ import type { LocalPoint, Polygon, Radians, -} from "../../math"; +} from "@excalidraw/math"; import { curveIntersectLineSegment, isPointWithinBounds, @@ -35,8 +35,11 @@ import { pointFrom, pointRotateRads, pointsEqual, -} from "../../math"; -import { ellipse, ellipseLineIntersectionPoints } from "../../math/ellipse"; +} from "@excalidraw/math"; +import { + ellipse, + ellipseLineIntersectionPoints, +} from "@excalidraw/math/ellipse"; import { deconstructDiamondElement, deconstructRectanguloidElement, diff --git a/packages/excalidraw/element/cropElement.ts b/packages/excalidraw/element/cropElement.ts index 20ebb8d79..b10980209 100644 --- a/packages/excalidraw/element/cropElement.ts +++ b/packages/excalidraw/element/cropElement.ts @@ -12,7 +12,7 @@ import { pointFromVector, clamp, isCloseTo, -} from "../../math"; +} from "@excalidraw/math"; import type { TransformHandleType } from "./transformHandles"; import type { ElementsMap, diff --git a/packages/excalidraw/element/distance.ts b/packages/excalidraw/element/distance.ts index d23bf7ee8..0010ab953 100644 --- a/packages/excalidraw/element/distance.ts +++ b/packages/excalidraw/element/distance.ts @@ -1,11 +1,11 @@ -import type { GlobalPoint, Radians } from "../../math"; +import type { GlobalPoint, Radians } from "@excalidraw/math"; import { curvePointDistance, distanceToLineSegment, pointFrom, pointRotateRads, -} from "../../math"; -import { ellipse, ellipseDistanceFromPoint } from "../../math/ellipse"; +} from "@excalidraw/math"; +import { ellipse, ellipseDistanceFromPoint } from "@excalidraw/math/ellipse"; import type { ExcalidrawBindableElement, ExcalidrawDiamondElement, diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index 2dd82e7c9..1839e978c 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -16,9 +16,9 @@ import type { ExcalidrawElbowArrowElement, } from "./types"; import { ARROW_TYPE } from "../constants"; -import type { LocalPoint } from "../../math"; -import { pointFrom } from "../../math"; import "../../utils/test-utils"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; const { h } = window; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index b990fb93b..703cea0d5 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -11,7 +11,7 @@ import { vectorScale, type GlobalPoint, type LocalPoint, -} from "../../math"; +} from "@excalidraw/math"; import BinaryHeap from "../binaryheap"; import { getSizeFromPoints } from "../points"; import { aabbForElement, pointInsideBounds } from "../shapes"; diff --git a/packages/excalidraw/element/embeddable.ts b/packages/excalidraw/element/embeddable.ts index b83953c2f..8265a0b13 100644 --- a/packages/excalidraw/element/embeddable.ts +++ b/packages/excalidraw/element/embeddable.ts @@ -12,7 +12,7 @@ import type { IframeData, } from "./types"; import type { MarkRequired } from "../utility-types"; -import { StoreAction } from "../store"; +import { CaptureUpdateAction } from "../store"; type IframeDataWithSandbox = MarkRequired; @@ -340,7 +340,7 @@ export const actionSetEmbeddableAsActiveTool = register({ type: "embeddable", }), }, - storeAction: StoreAction.NONE, + captureUpdate: CaptureUpdateAction.EVENTUALLY, }; }, }); diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index d2b220c45..02ee1ff29 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -31,7 +31,7 @@ import { isFlowchartNodeElement, } from "./typeChecks"; import { invariant, toBrandedType } from "../utils"; -import { pointFrom, type LocalPoint } from "../../math"; +import { pointFrom, type LocalPoint } from "@excalidraw/math"; import { aabbForElement } from "../shapes"; import { updateElbowArrowPoints } from "./elbowArrow"; diff --git a/packages/excalidraw/element/heading.ts b/packages/excalidraw/element/heading.ts index ef54ac77d..94e86339d 100644 --- a/packages/excalidraw/element/heading.ts +++ b/packages/excalidraw/element/heading.ts @@ -4,7 +4,7 @@ import type { Triangle, Vector, Radians, -} from "../../math"; +} from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -12,7 +12,7 @@ import { radiansToDegrees, triangleIncludesPoint, vectorFromPoint, -} from "../../math"; +} from "@excalidraw/math"; import { getCenterForBounds, type Bounds } from "./bounds"; import type { ExcalidrawBindableElement } from "./types"; diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index 380313067..1fcbe5fde 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -47,7 +47,7 @@ import type { Mutable } from "../utility-types"; import { ShapeCache } from "../scene/ShapeCache"; import type { Store } from "../store"; import type Scene from "../scene/Scene"; -import type { Radians } from "../../math"; +import type { Radians } from "@excalidraw/math"; import { pointCenter, pointFrom, @@ -59,7 +59,7 @@ import { pointDistance, pointTranslate, vectorFromPoint, -} from "../../math"; +} from "@excalidraw/math"; import { getBezierCurveLength, getBezierXY, diff --git a/packages/excalidraw/element/mutateElement.ts b/packages/excalidraw/element/mutateElement.ts index 2f2a5d47f..b64366be9 100644 --- a/packages/excalidraw/element/mutateElement.ts +++ b/packages/excalidraw/element/mutateElement.ts @@ -7,7 +7,7 @@ import type { Mutable } from "../utility-types"; import { ShapeCache } from "../scene/ShapeCache"; import { isElbowArrow } from "./typeChecks"; import { updateElbowArrowPoints } from "./elbowArrow"; -import type { Radians } from "../../math"; +import type { Radians } from "@excalidraw/math"; export type ElementUpdate = Omit< Partial, diff --git a/packages/excalidraw/element/newElement.test.ts b/packages/excalidraw/element/newElement.test.ts index 6a74e58f0..9c9006b6c 100644 --- a/packages/excalidraw/element/newElement.test.ts +++ b/packages/excalidraw/element/newElement.test.ts @@ -4,8 +4,8 @@ import { API } from "../tests/helpers/api"; import { FONT_FAMILY, ROUNDNESS } from "../constants"; import { isPrimitive } from "../utils"; import type { ExcalidrawLinearElement } from "./types"; -import type { LocalPoint } from "../../math"; -import { pointFrom } from "../../math"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; const assertCloneObjects = (source: any, clone: any) => { for (const key in clone) { diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 464641288..7d1f14910 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -46,7 +46,7 @@ import { } from "../constants"; import type { MarkOptional, Merge, Mutable } from "../utility-types"; import { getLineHeight } from "../fonts"; -import type { Radians } from "../../math"; +import type { Radians } from "@excalidraw/math"; import { normalizeText, measureText } from "./textMeasurements"; export type ElementConstructorOpts = MarkOptional< diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index 63923c5d8..f71a0bc7a 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -50,7 +50,7 @@ import { import { wrapText } from "./textWrapping"; import { LinearElementEditor } from "./linearElementEditor"; import { isInGroup } from "../groups"; -import type { GlobalPoint } from "../../math"; +import type { GlobalPoint } from "@excalidraw/math"; import { pointCenter, normalizeRadians, @@ -59,7 +59,7 @@ import { pointRotateRads, type Radians, type LocalPoint, -} from "../../math"; +} from "@excalidraw/math"; import { getMinTextElementWidth, measureText, diff --git a/packages/excalidraw/element/resizeTest.ts b/packages/excalidraw/element/resizeTest.ts index c00586db3..375ff980b 100644 --- a/packages/excalidraw/element/resizeTest.ts +++ b/packages/excalidraw/element/resizeTest.ts @@ -21,13 +21,13 @@ import type { Bounds } from "./bounds"; import { getElementAbsoluteCoords } from "./bounds"; import { SIDE_RESIZING_THRESHOLD } from "../constants"; import { isImageElement, isLinearElement } from "./typeChecks"; -import type { GlobalPoint, LineSegment, LocalPoint } from "../../math"; +import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; import { pointFrom, pointOnLineSegment, pointRotateRads, type Radians, -} from "../../math"; +} from "@excalidraw/math"; const isInsideTransformHandle = ( transformHandle: TransformHandle, diff --git a/packages/excalidraw/element/textWysiwyg.test.tsx b/packages/excalidraw/element/textWysiwyg.test.tsx index 80469d9e3..0842e30fd 100644 --- a/packages/excalidraw/element/textWysiwyg.test.tsx +++ b/packages/excalidraw/element/textWysiwyg.test.tsx @@ -23,7 +23,7 @@ import type { import { API } from "../tests/helpers/api"; import { getOriginalContainerHeightFromCache } from "./containerCache"; import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; -import { pointFrom } from "../../math"; +import { pointFrom } from "@excalidraw/math"; unmountComponent(); diff --git a/packages/excalidraw/element/transformHandles.ts b/packages/excalidraw/element/transformHandles.ts index 77a83e3e1..d34eb3279 100644 --- a/packages/excalidraw/element/transformHandles.ts +++ b/packages/excalidraw/element/transformHandles.ts @@ -19,8 +19,8 @@ import { isAndroid, isIOS, } from "../constants"; -import type { Radians } from "../../math"; -import { pointFrom, pointRotateRads } from "../../math"; +import type { Radians } from "@excalidraw/math"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; export type TransformHandleDirection = | "n" diff --git a/packages/excalidraw/element/types.ts b/packages/excalidraw/element/types.ts index ecd5ffecd..596586743 100644 --- a/packages/excalidraw/element/types.ts +++ b/packages/excalidraw/element/types.ts @@ -1,4 +1,4 @@ -import type { LocalPoint, Radians } from "../../math"; +import type { LocalPoint, Radians } from "@excalidraw/math"; import type { FONT_FAMILY, ROUNDNESS, diff --git a/packages/excalidraw/element/utils.ts b/packages/excalidraw/element/utils.ts index 68717ac8c..d85cd78c6 100644 --- a/packages/excalidraw/element/utils.ts +++ b/packages/excalidraw/element/utils.ts @@ -1,5 +1,5 @@ import { getDiamondPoints } from "."; -import type { Curve, LineSegment } from "../../math"; +import type { Curve, LineSegment } from "@excalidraw/math"; import { curve, lineSegment, @@ -10,7 +10,7 @@ import { vectorNormalize, vectorScale, type GlobalPoint, -} from "../../math"; +} from "@excalidraw/math"; import { getCornerRadius } from "../shapes"; import type { ExcalidrawDiamondElement, diff --git a/packages/excalidraw/fonts/ExcalidrawFontFace.ts b/packages/excalidraw/fonts/ExcalidrawFontFace.ts index d2cf7d4b4..816ed88bd 100644 --- a/packages/excalidraw/fonts/ExcalidrawFontFace.ts +++ b/packages/excalidraw/fonts/ExcalidrawFontFace.ts @@ -8,7 +8,7 @@ export class ExcalidrawFontFace { public readonly urls: URL[] | DataURL[]; public readonly fontFace: FontFace; - private static readonly UNPKG_FALLBACK_URL = `https://unpkg.com/${ + private static readonly ASSETS_FALLBACK_URL = `https://esm.sh/${ import.meta.env.VITE_PKG_NAME ? `${import.meta.env.VITE_PKG_NAME}@${import.meta.env.PKG_VERSION}` // should be provided by vite during package build : "@excalidraw/excalidraw" // fallback to latest package version (i.e. for app) @@ -164,7 +164,7 @@ export class ExcalidrawFontFace { } // fallback url for bundled fonts - urls.push(new URL(assetUrl, ExcalidrawFontFace.UNPKG_FALLBACK_URL)); + urls.push(new URL(assetUrl, ExcalidrawFontFace.ASSETS_FALLBACK_URL)); return urls; } diff --git a/packages/excalidraw/frame.ts b/packages/excalidraw/frame.ts index 952521d3e..4659a34a0 100644 --- a/packages/excalidraw/frame.ts +++ b/packages/excalidraw/frame.ts @@ -26,10 +26,13 @@ import { getElementsWithinSelection, getSelectedElements } from "./scene"; import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; import { getElementLineSegments } from "./element/bounds"; -import { doLineSegmentsIntersect, elementsOverlappingBBox } from "../utils/"; +import { + doLineSegmentsIntersect, + elementsOverlappingBBox, +} from "@excalidraw/utils"; import { isFrameElement, isFrameLikeElement } from "./element/typeChecks"; import type { ReadonlySetLike } from "./utility-types"; -import { isPointWithinBounds, pointFrom } from "../math"; +import { isPointWithinBounds, pointFrom } from "@excalidraw/math"; // --------------------------- Frame State ------------------------------------ export const bindElementsToFramesAfterDuplication = ( diff --git a/packages/excalidraw/hooks/useLibraryItemSvg.ts b/packages/excalidraw/hooks/useLibraryItemSvg.ts index b2ee746e4..72b648d11 100644 --- a/packages/excalidraw/hooks/useLibraryItemSvg.ts +++ b/packages/excalidraw/hooks/useLibraryItemSvg.ts @@ -1,7 +1,7 @@ import { useEffect, useState } from "react"; import { COLOR_PALETTE } from "../colors"; import { atom, useAtom } from "../editor-jotai"; -import { exportToSvg } from "../../utils/export"; +import { exportToSvg } from "@excalidraw/utils/export"; import type { LibraryItem } from "../types"; export type SvgCache = Map; diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index bd3d0f148..b4b8574bd 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -233,7 +233,7 @@ export { exportToBlob, exportToSvg, exportToClipboard, -} from "../utils/export"; +} from "@excalidraw/utils/export"; export { serializeAsJSON, serializeLibraryAsJSON } from "./data/json"; export { @@ -251,6 +251,7 @@ export { MIME_TYPES, ROUNDNESS, DEFAULT_LASER_COLOR, + UserIdleState, } from "./constants"; export { @@ -259,7 +260,7 @@ export { bumpVersion, } from "./element/mutateElement"; -export { StoreAction } from "./store"; +export { CaptureUpdateAction } from "./store"; export { parseLibraryTokensFromUrl, useHandleLibrary } from "./data/library"; @@ -290,7 +291,7 @@ export { elementsOverlappingBBox, isElementInsideBBox, elementPartiallyOverlapsWithOrContainsBBox, -} from "../utils/withinBounds"; +} from "@excalidraw/utils/withinBounds"; export { DiagramToCodePlugin } from "./components/DiagramToCodePlugin/DiagramToCodePlugin"; export { getDataURL } from "./data/blob"; diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json index c6e9d6575..82e5c4373 100644 --- a/packages/excalidraw/package.json +++ b/packages/excalidraw/package.json @@ -1,21 +1,25 @@ { "name": "@excalidraw/excalidraw", - "version": "0.17.1", - "main": "./dist/prod/index.js", + "version": "0.18.0", "type": "module", + "types": "./dist/types/excalidraw/index.d.ts", + "main": "./dist/prod/index.js", "module": "./dist/prod/index.js", "exports": { - ".": { - "development": "./dist/dev/index.js", - "types": "./dist/excalidraw/index.d.ts", - "default": "./dist/prod/index.js" + "./*": { + "types": "./dist/types/excalidraw/*.d.ts" }, "./index.css": { "development": "./dist/dev/index.css", - "default": "./dist/prod/index.css" + "production": "./dist/prod/index.css" + }, + ".": { + "types": "./dist/types/excalidraw/index.d.ts", + "development": "./dist/dev/index.js", + "production": "./dist/prod/index.js", + "default": "./dist/prod/index.js" } }, - "types": "./dist/excalidraw/index.d.ts", "files": [ "dist/*" ], @@ -23,7 +27,6 @@ "access": "public" }, "description": "Excalidraw as a React component", - "repository": "https://github.com/excalidraw/excalidraw", "license": "MIT", "keywords": [ "excalidraw", @@ -73,9 +76,10 @@ "jotai": "2.11.0", "jotai-scope": "0.7.2", "lodash.throttle": "4.1.1", + "lodash.debounce": "4.0.8", "nanoid": "3.3.3", "open-color": "1.9.1", - "pako": "1.0.11", + "pako": "2.0.3", "perfect-freehand": "1.2.0", "pica": "7.1.1", "png-chunk-text": "1.0.0", @@ -88,53 +92,32 @@ "tunnel-rat": "0.1.2" }, "devDependencies": { - "@babel/core": "7.24.5", - "@babel/plugin-transform-arrow-functions": "7.24.1", - "@babel/plugin-transform-async-to-generator": "7.24.1", - "@babel/plugin-transform-runtime": "7.24.3", - "@babel/plugin-transform-typescript": "7.24.5", - "@babel/preset-env": "7.24.5", - "@babel/preset-react": "7.24.1", - "@babel/preset-typescript": "7.24.1", "@size-limit/preset-big-lib": "9.0.0", "@testing-library/dom": "10.4.0", "@testing-library/jest-dom": "6.6.3", "@testing-library/react": "16.2.0", - "@types/pako": "1.0.3", + "@types/lodash.debounce": "4.0.8", + "@types/pako": "2.0.3", "@types/pica": "5.1.3", "@types/resize-observer-browser": "0.1.7", "ansicolor": "2.0.3", "autoprefixer": "10.4.7", - "babel-loader": "8.2.5", - "babel-plugin-transform-class-properties": "6.24.1", "cross-env": "7.0.3", - "css-loader": "6.7.1", "dotenv": "16.0.1", "esbuild": "0.19.10", - "esbuild-plugin-external-global": "1.0.1", "esbuild-sass-plugin": "2.16.0", "eslint-plugin-react": "7.32.2", "fake-indexeddb": "3.1.7", "fonteditor-core": "2.4.1", "harfbuzzjs": "0.3.6", - "import-meta-loader": "1.1.0", "jest-diff": "29.7.0", - "mini-css-extract-plugin": "2.6.1", - "postcss-loader": "7.0.1", - "sass-loader": "13.0.2", - "size-limit": "9.0.0", - "style-loader": "3.3.3", - "ts-loader": "9.3.1", "typescript": "4.9.4" }, + "repository": "https://github.com/excalidraw/excalidraw", "bugs": "https://github.com/excalidraw/excalidraw/issues", "homepage": "https://github.com/excalidraw/excalidraw/tree/master/packages/excalidraw", "scripts": { "gen:types": "rm -rf types && tsc", - "build:esm": "rm -rf dist && node ../../scripts/buildPackage.js && yarn gen:types", - "pack": "yarn build:umd && yarn pack", - "start": "node ../../scripts/buildExample.mjs && vite", - "build:example": "node ../../scripts/buildExample.mjs", - "size": "yarn build:umd && size-limit" + "build:esm": "rm -rf dist && node ../../scripts/buildPackage.js && yarn gen:types" } } diff --git a/packages/excalidraw/points.ts b/packages/excalidraw/points.ts index 5f9480120..9d48857db 100644 --- a/packages/excalidraw/points.ts +++ b/packages/excalidraw/points.ts @@ -1,4 +1,8 @@ -import { pointFromPair, type GlobalPoint, type LocalPoint } from "../math"; +import { + pointFromPair, + type GlobalPoint, + type LocalPoint, +} from "@excalidraw/math"; export const getSizeFromPoints = ( points: readonly (GlobalPoint | LocalPoint)[], diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 3a070e667..9aa832770 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -83,7 +83,7 @@ import { type GlobalPoint, type LocalPoint, type Radians, -} from "../../math"; +} from "@excalidraw/math"; import { getCornerRadius } from "../shapes"; const renderElbowArrowMidPointHighlight = ( diff --git a/packages/excalidraw/renderer/renderElement.ts b/packages/excalidraw/renderer/renderElement.ts index 3e87ebaf5..d93469c2d 100644 --- a/packages/excalidraw/renderer/renderElement.ts +++ b/packages/excalidraw/renderer/renderElement.ts @@ -60,7 +60,7 @@ import { LinearElementEditor } from "../element/linearElementEditor"; import { getContainingFrame } from "../frame"; import { ShapeCache } from "../scene/ShapeCache"; import { getVerticalOffset } from "../fonts"; -import { isRightAngleRads } from "../../math"; +import { isRightAngleRads } from "@excalidraw/math"; import { getCornerRadius } from "../shapes"; import { getUncroppedImageElement } from "../element/cropElement"; import { getLineHeightInPx } from "../element/textMeasurements"; diff --git a/packages/excalidraw/renderer/renderSnaps.ts b/packages/excalidraw/renderer/renderSnaps.ts index 57b57c570..878e8e523 100644 --- a/packages/excalidraw/renderer/renderSnaps.ts +++ b/packages/excalidraw/renderer/renderSnaps.ts @@ -1,4 +1,4 @@ -import { pointFrom, type GlobalPoint, type LocalPoint } from "../../math"; +import { pointFrom, type GlobalPoint, type LocalPoint } from "@excalidraw/math"; import { THEME } from "../constants"; import type { PointSnapLine, PointerSnapLine } from "../snapping"; import type { InteractiveCanvasAppState } from "../types"; diff --git a/packages/excalidraw/scene/Shape.ts b/packages/excalidraw/scene/Shape.ts index ba55b2f60..0fef0b2b2 100644 --- a/packages/excalidraw/scene/Shape.ts +++ b/packages/excalidraw/scene/Shape.ts @@ -23,7 +23,7 @@ import { } from "../element/typeChecks"; import { canChangeRoundness } from "./comparisons"; import type { EmbedsValidationStatus } from "../types"; -import { pointFrom, pointDistance, type LocalPoint } from "../../math"; +import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math"; import { getCornerRadius, isPathALoop } from "../shapes"; import { headingForPointIsHorizontal } from "../element/heading"; diff --git a/packages/excalidraw/scene/normalize.ts b/packages/excalidraw/scene/normalize.ts index a6980c91d..2a025fc27 100644 --- a/packages/excalidraw/scene/normalize.ts +++ b/packages/excalidraw/scene/normalize.ts @@ -1,4 +1,4 @@ -import { clamp, round } from "../../math"; +import { clamp, round } from "@excalidraw/math"; import { MAX_ZOOM, MIN_ZOOM } from "../constants"; import type { NormalizedZoomValue } from "../types"; diff --git a/packages/excalidraw/scene/types.ts b/packages/excalidraw/scene/types.ts index 46ee26b74..c0bfd1bba 100644 --- a/packages/excalidraw/scene/types.ts +++ b/packages/excalidraw/scene/types.ts @@ -14,11 +14,11 @@ import type { InteractiveCanvasAppState, StaticCanvasAppState, SocketId, - UserIdleState, Device, PendingExcalidrawElements, } from "../types"; import type { MakeBrand } from "../utility-types"; +import type { UserIdleState } from "../constants"; export type RenderableElementsMap = NonDeletedElementsMap & MakeBrand<"RenderableElementsMap">; diff --git a/packages/excalidraw/shapes.tsx b/packages/excalidraw/shapes.tsx index 3f1855c63..cfd639f2d 100644 --- a/packages/excalidraw/shapes.tsx +++ b/packages/excalidraw/shapes.tsx @@ -7,7 +7,7 @@ import { pointsEqual, type GlobalPoint, type LocalPoint, -} from "../math"; +} from "@excalidraw/math"; import { getClosedCurveShape, getCurvePathOps, @@ -16,7 +16,7 @@ import { getFreedrawShape, getPolygonShape, type GeometricShape, -} from "../utils/geometry/shape"; +} from "@excalidraw/utils/geometry/shape"; import { ArrowIcon, DiamondIcon, diff --git a/packages/excalidraw/snapping.ts b/packages/excalidraw/snapping.ts index 1f2451b33..1b661516e 100644 --- a/packages/excalidraw/snapping.ts +++ b/packages/excalidraw/snapping.ts @@ -1,4 +1,4 @@ -import type { InclusiveRange } from "../math"; +import type { InclusiveRange } from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -6,7 +6,7 @@ import { rangeIntersection, rangesOverlap, type GlobalPoint, -} from "../math"; +} from "@excalidraw/math"; import { TOOL_TYPE } from "./constants"; import type { Bounds } from "./element/bounds"; import { diff --git a/packages/excalidraw/store.ts b/packages/excalidraw/store.ts index b3e2713c4..1343347c4 100644 --- a/packages/excalidraw/store.ts +++ b/packages/excalidraw/store.ts @@ -37,7 +37,7 @@ const isObservedAppState = ( ): appState is ObservedAppState => !!Reflect.get(appState, hiddenObservedAppStateProp); -export const StoreAction = { +export const CaptureUpdateAction = { /** * Immediately undoable. * @@ -46,7 +46,7 @@ export const StoreAction = { * * These updates will _immediately_ make it to the local undo / redo stacks. */ - CAPTURE: "capture", + IMMEDIATELY: "IMMEDIATELY", /** * Never undoable. * @@ -55,22 +55,22 @@ export const StoreAction = { * * These updates will _never_ make it to the local undo / redo stacks. */ - UPDATE: "update", + NEVER: "NEVER", /** * Eventually undoable. * * Use for updates which should not be captured immediately - likely * exceptions which are part of some async multi-step process. Otherwise, all * such updates would end up being captured with the next - * `StoreAction.CAPTURE` - triggered either by the next `updateScene` + * `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene` * or internally by the editor. * * These updates will _eventually_ make it to the local undo / redo stacks. */ - NONE: "none", + EVENTUALLY: "EVENTUALLY", } as const; -export type StoreActionType = ValueOf; +export type CaptureUpdateActionType = ValueOf; /** * Represent an increment to the Store. @@ -133,7 +133,7 @@ export class Store implements IStore { [StoreIncrementEvent] >(); - private scheduledActions: Set = new Set(); + private scheduledActions: Set = new Set(); private _snapshot = Snapshot.empty(); public get snapshot() { @@ -146,14 +146,14 @@ export class Store implements IStore { // TODO: Suspicious that this is called so many places. Seems error-prone. public shouldCaptureIncrement = () => { - this.scheduleAction(StoreAction.CAPTURE); + this.scheduleAction(CaptureUpdateAction.IMMEDIATELY); }; public shouldUpdateSnapshot = () => { - this.scheduleAction(StoreAction.UPDATE); + this.scheduleAction(CaptureUpdateAction.NEVER); }; - private scheduleAction = (action: StoreActionType) => { + private scheduleAction = (action: CaptureUpdateActionType) => { this.scheduledActions.add(action); this.satisfiesScheduledActionsInvariant(); }; @@ -164,9 +164,9 @@ export class Store implements IStore { ): void => { try { // Capture has precedence since it also performs update - if (this.scheduledActions.has(StoreAction.CAPTURE)) { + if (this.scheduledActions.has(CaptureUpdateAction.IMMEDIATELY)) { this.captureIncrement(elements, appState); - } else if (this.scheduledActions.has(StoreAction.UPDATE)) { + } else if (this.scheduledActions.has(CaptureUpdateAction.NEVER)) { this.updateSnapshot(elements, appState); } } finally { diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx index dff4d3347..905a44e70 100644 --- a/packages/excalidraw/tests/binding.test.tsx +++ b/packages/excalidraw/tests/binding.test.tsx @@ -7,7 +7,7 @@ import { API } from "./helpers/api"; import { KEYS } from "../keys"; import { actionWrapTextInContainer } from "../actions/actionBoundText"; import { arrayToMap } from "../utils"; -import { pointFrom } from "../../math"; +import { pointFrom } from "@excalidraw/math"; const { h } = window; diff --git a/packages/excalidraw/tests/cropElement.test.tsx b/packages/excalidraw/tests/cropElement.test.tsx index 1fa33137c..a508f5d64 100644 --- a/packages/excalidraw/tests/cropElement.test.tsx +++ b/packages/excalidraw/tests/cropElement.test.tsx @@ -314,6 +314,7 @@ describe("Cropping and other features", async () => { const canvas = await exportToCanvas({ elements: [image], + // @ts-ignore appState: h.state, files: h.app.files, exportPadding: 0, @@ -324,6 +325,7 @@ describe("Cropping and other features", async () => { const svg = await exportToSvg({ elements: [image], + // @ts-ignore appState: h.state, files: h.app.files, exportPadding: 0, diff --git a/packages/excalidraw/tests/data/restore.test.ts b/packages/excalidraw/tests/data/restore.test.ts index a3d6d7350..37a27ac6a 100644 --- a/packages/excalidraw/tests/data/restore.test.ts +++ b/packages/excalidraw/tests/data/restore.test.ts @@ -13,7 +13,7 @@ import type { NormalizedZoomValue } from "../../types"; import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; import { newElementWith } from "../../element/mutateElement"; import { vi } from "vitest"; -import { pointFrom } from "../../../math"; +import { pointFrom } from "@excalidraw/math"; describe("restoreElements", () => { const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement"); diff --git a/packages/excalidraw/tests/fixtures/elementFixture.ts b/packages/excalidraw/tests/fixtures/elementFixture.ts index 3f93f0713..f0470ec86 100644 --- a/packages/excalidraw/tests/fixtures/elementFixture.ts +++ b/packages/excalidraw/tests/fixtures/elementFixture.ts @@ -1,4 +1,4 @@ -import type { Radians } from "../../../math"; +import type { Radians } from "@excalidraw/math"; import { DEFAULT_FONT_FAMILY } from "../../constants"; import type { ExcalidrawElement } from "../../element/types"; diff --git a/packages/excalidraw/tests/flip.test.tsx b/packages/excalidraw/tests/flip.test.tsx index 2cd617ebb..e3f44b333 100644 --- a/packages/excalidraw/tests/flip.test.tsx +++ b/packages/excalidraw/tests/flip.test.tsx @@ -27,8 +27,8 @@ import { KEYS } from "../keys"; import { getBoundTextElementPosition } from "../element/textElement"; import { createPasteEvent } from "../clipboard"; import { arrayToMap, cloneJSON } from "../utils"; -import type { LocalPoint } from "../../math"; -import { pointFrom, type Radians } from "../../math"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom, type Radians } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/helpers/api.ts b/packages/excalidraw/tests/helpers/api.ts index 405bce396..218f37116 100644 --- a/packages/excalidraw/tests/helpers/api.ts +++ b/packages/excalidraw/tests/helpers/api.ts @@ -39,7 +39,7 @@ import type App from "../../components/App"; import { createTestHook } from "../../components/App"; import type { Action } from "../../actions/types"; import { mutateElement } from "../../element/mutateElement"; -import { pointFrom, type LocalPoint, type Radians } from "../../../math"; +import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; import { selectGroupsForSelectedElements } from "../../groups"; const readFile = util.promisify(fs.readFile); diff --git a/packages/excalidraw/tests/helpers/ui.ts b/packages/excalidraw/tests/helpers/ui.ts index 05144011c..b9b7023c1 100644 --- a/packages/excalidraw/tests/helpers/ui.ts +++ b/packages/excalidraw/tests/helpers/ui.ts @@ -33,8 +33,8 @@ import { getCommonBounds, getElementPointsCoords } from "../../element/bounds"; import { getTextEditor } from "../queries/dom"; import { arrayToMap } from "../../utils"; import { createTestHook } from "../../components/App"; -import type { GlobalPoint, LocalPoint, Radians } from "../../../math"; -import { pointFrom, pointRotateRads } from "../../../math"; +import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; import { cropElement } from "../../element/cropElement"; import type { ToolType } from "../../types"; diff --git a/packages/excalidraw/tests/history.test.tsx b/packages/excalidraw/tests/history.test.tsx index 4942fb2b3..ffddec49f 100644 --- a/packages/excalidraw/tests/history.test.tsx +++ b/packages/excalidraw/tests/history.test.tsx @@ -46,9 +46,9 @@ import { vi } from "vitest"; import { queryByText } from "@testing-library/react"; import { HistoryEntry } from "../history"; import { AppStateChange, ElementsChange } from "../change"; -import { Snapshot, StoreAction } from "../store"; -import type { LocalPoint, Radians } from "../../math"; -import { pointFrom } from "../../math"; +import { Snapshot, CaptureUpdateAction } from "../store"; +import type { LocalPoint, Radians } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; const { h } = window; @@ -182,7 +182,7 @@ describe("history", () => { API.updateScene({ elements: [rect1, rect2], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); expect(API.getUndoStack().length).toBe(1); @@ -194,7 +194,7 @@ describe("history", () => { API.updateScene({ elements: [rect1, rect2], - storeAction: StoreAction.CAPTURE, // even though the flag is on, same elements are passed, nothing to commit + captureUpdate: CaptureUpdateAction.IMMEDIATELY, // even though the flag is on, same elements are passed, nothing to commit }); expect(API.getUndoStack().length).toBe(1); expect(API.getRedoStack().length).toBe(0); @@ -562,7 +562,7 @@ describe("history", () => { appState: { name: "New name", }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); expect(API.getUndoStack().length).toBe(1); @@ -573,7 +573,7 @@ describe("history", () => { appState: { viewBackgroundColor: "#000", }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); expect(API.getUndoStack().length).toBe(2); expect(API.getRedoStack().length).toBe(0); @@ -586,7 +586,7 @@ describe("history", () => { name: "New name", viewBackgroundColor: "#000", }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); expect(API.getUndoStack().length).toBe(2); expect(API.getRedoStack().length).toBe(0); @@ -1293,7 +1293,7 @@ describe("history", () => { API.updateScene({ elements: [rect1, text, rect2], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // bind text1 to rect1 @@ -1847,7 +1847,7 @@ describe("history", () => { strokeColor: blue, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -1885,7 +1885,7 @@ describe("history", () => { strokeColor: yellow, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -1933,7 +1933,7 @@ describe("history", () => { backgroundColor: yellow, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // At this point our entry gets updated from `red` -> `blue` into `red` -> `yellow` @@ -1949,7 +1949,7 @@ describe("history", () => { backgroundColor: violet, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // At this point our (inversed) entry gets updated from `red` -> `yellow` into `violet` -> `yellow` @@ -1994,7 +1994,7 @@ describe("history", () => { API.updateScene({ elements: [rect, diamond], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Connect the arrow @@ -2043,7 +2043,7 @@ describe("history", () => { } as FixedPointBinding, }, ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -2058,7 +2058,7 @@ describe("history", () => { } : el, ), - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2082,7 +2082,7 @@ describe("history", () => { // Initialize scene API.updateScene({ elements: [rect1, rect2], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -2091,7 +2091,7 @@ describe("history", () => { newElementWith(h.elements[0], { groupIds: ["A"] }), newElementWith(h.elements[1], { groupIds: ["A"] }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); const rect3 = API.createElement({ type: "rectangle", groupIds: ["B"] }); @@ -2105,7 +2105,7 @@ describe("history", () => { rect3, rect4, ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2151,7 +2151,7 @@ describe("history", () => { ] as LocalPoint[], }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); // undo `actionFinalize` @@ -2246,7 +2246,7 @@ describe("history", () => { isDeleted: false, // undeletion might happen due to concurrency between clients }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(API.getSelectedElements()).toEqual([]); @@ -2323,7 +2323,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(h.elements).toEqual([ @@ -2385,7 +2385,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2461,7 +2461,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2500,7 +2500,7 @@ describe("history", () => { isDeleted: false, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.redo(); @@ -2546,7 +2546,7 @@ describe("history", () => { // Simulate remote update API.updateScene({ elements: [rect1, rect2], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.withModifierKeys({ ctrl: true }, () => { @@ -2556,7 +2556,7 @@ describe("history", () => { // Simulate remote update API.updateScene({ elements: [h.elements[0], h.elements[1], rect3, rect4], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.withModifierKeys({ ctrl: true }, () => { @@ -2577,7 +2577,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2602,7 +2602,7 @@ describe("history", () => { isDeleted: false, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.redo(); @@ -2613,7 +2613,7 @@ describe("history", () => { // Simulate remote update API.updateScene({ elements: [h.elements[0], h.elements[1], rect3, rect4], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.redo(); @@ -2659,7 +2659,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2680,7 +2680,7 @@ describe("history", () => { }), h.elements[1], ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2723,7 +2723,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2766,7 +2766,7 @@ describe("history", () => { h.elements[0], h.elements[1], ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(API.getUndoStack().length).toBe(2); @@ -2805,7 +2805,7 @@ describe("history", () => { h.elements[0], h.elements[1], ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(API.getUndoStack().length).toBe(2); @@ -2856,7 +2856,7 @@ describe("history", () => { h.elements[0], // rect2 h.elements[1], // rect1 ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2886,7 +2886,7 @@ describe("history", () => { h.elements[0], // rect3 h.elements[2], // rect1 ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -2916,7 +2916,7 @@ describe("history", () => { // Simulate remote update API.updateScene({ elements: [...h.elements, rect], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); mouse.moveTo(60, 60); @@ -2968,7 +2968,7 @@ describe("history", () => { // // Simulate remote update API.updateScene({ elements: [...h.elements, rect3], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); mouse.moveTo(100, 100); @@ -3058,7 +3058,7 @@ describe("history", () => { // Simulate remote update API.updateScene({ elements: [...h.elements, rect3], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); mouse.moveTo(100, 100); @@ -3235,7 +3235,7 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [container, text], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -3248,7 +3248,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -3279,7 +3279,7 @@ describe("history", () => { x: h.elements[1].x + 10, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3322,7 +3322,7 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [container, text], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -3335,7 +3335,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -3369,7 +3369,7 @@ describe("history", () => { remoteText, h.elements[1], ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3425,7 +3425,7 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [container, text], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -3438,7 +3438,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -3475,7 +3475,7 @@ describe("history", () => { containerId: remoteContainer.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3533,7 +3533,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [container], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3544,7 +3544,7 @@ describe("history", () => { }), newElementWith(text, { containerId: container.id }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3594,7 +3594,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [text], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3605,7 +3605,7 @@ describe("history", () => { }), newElementWith(text, { containerId: container.id }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3654,7 +3654,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [container], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3667,7 +3667,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -3704,7 +3704,7 @@ describe("history", () => { // rebinding the container with a new text element! remoteText, ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3761,7 +3761,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [text], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3774,7 +3774,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.undo(); @@ -3811,7 +3811,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3867,7 +3867,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [container], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3881,7 +3881,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3924,7 +3924,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [text], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -3938,7 +3938,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -3981,7 +3981,7 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [container], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -3993,7 +3993,7 @@ describe("history", () => { angle: 90 as Radians, }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -4006,7 +4006,7 @@ describe("history", () => { }), newElementWith(text, { containerId: container.id }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(h.elements).toEqual([ @@ -4099,7 +4099,7 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [text], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update @@ -4111,7 +4111,7 @@ describe("history", () => { angle: 90 as Radians, }), ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -4126,7 +4126,7 @@ describe("history", () => { containerId: container.id, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); expect(API.getUndoStack().length).toBe(0); @@ -4217,7 +4217,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [rect1, rect2], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); mouse.reset(); @@ -4304,7 +4304,7 @@ describe("history", () => { x: h.elements[1].x + 50, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -4444,7 +4444,7 @@ describe("history", () => { }), remoteContainer, ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -4549,7 +4549,7 @@ describe("history", () => { boundElements: [{ id: arrow.id, type: "arrow" }], }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -4626,7 +4626,7 @@ describe("history", () => { // Simulate local update API.updateScene({ elements: [arrow], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate remote update @@ -4653,7 +4653,7 @@ describe("history", () => { boundElements: [{ id: arrow.id, type: "arrow" }], }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); runTwice(() => { @@ -4783,7 +4783,7 @@ describe("history", () => { newElementWith(h.elements[1], { x: 500, y: -500 }), h.elements[2], ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.redo(); @@ -4853,13 +4853,13 @@ describe("history", () => { // Initialize the scene API.updateScene({ elements: [frame], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); // Simulate local update API.updateScene({ elements: [rect, h.elements[0]], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); // Simulate local update @@ -4870,7 +4870,7 @@ describe("history", () => { }), h.elements[1], ], - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); Keyboard.undo(); @@ -4914,7 +4914,7 @@ describe("history", () => { isDeleted: true, }), ], - storeAction: StoreAction.UPDATE, + captureUpdate: CaptureUpdateAction.NEVER, }); Keyboard.redo(); diff --git a/packages/excalidraw/tests/linearElementEditor.test.tsx b/packages/excalidraw/tests/linearElementEditor.test.tsx index 986a63512..98d6058c2 100644 --- a/packages/excalidraw/tests/linearElementEditor.test.tsx +++ b/packages/excalidraw/tests/linearElementEditor.test.tsx @@ -30,8 +30,8 @@ import * as textElementUtils from "../element/textElement"; import { ROUNDNESS, VERTICAL_ALIGN } from "../constants"; import { vi } from "vitest"; import { arrayToMap } from "../utils"; -import type { GlobalPoint } from "../../math"; -import { pointCenter, pointFrom } from "../../math"; +import type { GlobalPoint } from "@excalidraw/math"; +import { pointCenter, pointFrom } from "@excalidraw/math"; import { wrapText } from "../element/textWrapping"; const renderInteractiveScene = vi.spyOn( diff --git a/packages/excalidraw/tests/packages/events.test.tsx b/packages/excalidraw/tests/packages/events.test.tsx index 34a1cc062..ad8b3c6d9 100644 --- a/packages/excalidraw/tests/packages/events.test.tsx +++ b/packages/excalidraw/tests/packages/events.test.tsx @@ -1,6 +1,6 @@ import React from "react"; import { vi } from "vitest"; -import { Excalidraw, StoreAction } from "../../index"; +import { Excalidraw, CaptureUpdateAction } from "../../index"; import type { ExcalidrawImperativeAPI } from "../../types"; import { resolvablePromise } from "../../utils"; import { render } from "../test-utils"; @@ -31,7 +31,7 @@ describe("event callbacks", () => { excalidrawAPI.onChange(onChange); API.updateScene({ appState: { viewBackgroundColor: "red" }, - storeAction: StoreAction.CAPTURE, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }); expect(onChange).toHaveBeenCalledWith( // elements diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index eca7b7e50..a12d31048 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -15,8 +15,8 @@ import { KEYS } from "../keys"; import { isLinearElement } from "../element/typeChecks"; import { LinearElementEditor } from "../element/linearElementEditor"; import { arrayToMap } from "../utils"; -import type { LocalPoint } from "../../math"; -import { pointFrom } from "../../math"; +import type { LocalPoint } from "@excalidraw/math"; +import { pointFrom } from "@excalidraw/math"; import { resizeSingleElement } from "../element/resizeElements"; import { getSizeFromPoints } from "../points"; diff --git a/packages/excalidraw/tests/scene/export.test.ts b/packages/excalidraw/tests/scene/export.test.ts index 33a554f1e..6fd8a8b85 100644 --- a/packages/excalidraw/tests/scene/export.test.ts +++ b/packages/excalidraw/tests/scene/export.test.ts @@ -11,7 +11,7 @@ import { textFixture, } from "../fixtures/elementFixture"; import { API } from "../helpers/api"; -import { exportToCanvas, exportToSvg } from "../../../utils"; +import { exportToCanvas, exportToSvg } from "@excalidraw/utils"; import { FONT_FAMILY, FRAME_STYLE } from "../../constants"; import { prepareElementsForExport } from "../../data"; @@ -114,7 +114,7 @@ describe("exportToSvg", () => { ); expect(svgElement.getAttribute("filter")).toMatchInlineSnapshot( - `"_themeFilter_1883f3"`, + `"invert(93%) hue-rotate(180deg)"`, ); }); diff --git a/packages/excalidraw/tsconfig.json b/packages/excalidraw/tsconfig.json index 4d7d4b3c1..f61b8d0af 100644 --- a/packages/excalidraw/tsconfig.json +++ b/packages/excalidraw/tsconfig.json @@ -1,15 +1,24 @@ { - "exclude": ["**/*.test.*", "tests", "types", "examples", "dist"], "compilerOptions": { + "outDir": "./dist/types", "target": "ESNext", "strict": true, - "outDir": "dist", "skipLibCheck": true, "declaration": true, "allowSyntheticDefaultImports": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, - "jsx": "react-jsx" - } + "jsx": "react-jsx", + "emitDeclarationOnly": true, + "paths": { + "@excalidraw/excalidraw": ["../excalidraw/index.tsx"], + "@excalidraw/utils": ["../utils/index.ts"], + "@excalidraw/math": ["../math/index.ts"], + "@excalidraw/excalidraw/*": ["../excalidraw/*"], + "@excalidraw/utils/*": ["../utils/*"], + "@excalidraw/math/*": ["../math/*"] + } + }, + "exclude": ["**/*.test.*", "tests", "types", "examples", "dist"] } diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 7dbb2d314..0562736cd 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -41,7 +41,8 @@ import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants"; import type { ContextMenuItems } from "./components/ContextMenu"; import type { SnapLine } from "./snapping"; import type { Merge, MaybePromise, ValueOf, MakeBrand } from "./utility-types"; -import type { StoreActionType } from "./store"; +import type { CaptureUpdateActionType } from "./store"; +import type { UserIdleState } from "./constants"; export type SocketId = string & { _brand: "SocketId" }; @@ -588,15 +589,9 @@ export type SceneData = { elements?: ImportedDataState["elements"]; appState?: ImportedDataState["appState"]; collaborators?: Map; - storeAction?: StoreActionType; + captureUpdate?: CaptureUpdateActionType; }; -export enum UserIdleState { - ACTIVE = "active", - AWAY = "away", - IDLE = "idle", -} - export type ExportOpts = { saveFileToDisk?: boolean; onExportToBackend?: ( diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index 6a682e9cf..e3e18eb93 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -1,5 +1,5 @@ import Pool from "es6-promise-pool"; -import { average } from "../math"; +import { average } from "@excalidraw/math"; import { COLOR_PALETTE } from "./colors"; import type { EVENT } from "./constants"; import { diff --git a/packages/excalidraw/visualdebug.ts b/packages/excalidraw/visualdebug.ts index 49dacc916..862f2cf20 100644 --- a/packages/excalidraw/visualdebug.ts +++ b/packages/excalidraw/visualdebug.ts @@ -1,12 +1,12 @@ -import type { Curve } from "../math"; +import type { Curve } from "@excalidraw/math"; import { isLineSegment, lineSegment, pointFrom, type GlobalPoint, type LocalPoint, -} from "../math"; -import type { LineSegment } from "../utils"; +} from "@excalidraw/math"; +import type { LineSegment } from "@excalidraw/utils"; import type { Bounds } from "./element/bounds"; import { isBounds } from "./element/typeChecks"; diff --git a/packages/math/global.d.ts b/packages/math/global.d.ts new file mode 100644 index 000000000..16ade7a7d --- /dev/null +++ b/packages/math/global.d.ts @@ -0,0 +1,3 @@ +/// +import "@excalidraw/excalidraw/global"; +import "@excalidraw/excalidraw/css"; diff --git a/packages/math/package.json b/packages/math/package.json index b6c87e8f3..a60c97119 100644 --- a/packages/math/package.json +++ b/packages/math/package.json @@ -1,16 +1,20 @@ { "name": "@excalidraw/math", "version": "0.1.0", - "main": "./dist/prod/index.js", "type": "module", + "types": "./dist/types/math/index.d.ts", + "main": "./dist/prod/index.js", "module": "./dist/prod/index.js", "exports": { ".": { "development": "./dist/dev/index.js", + "production": "./dist/prod/index.js", "default": "./dist/prod/index.js" + }, + "./*": { + "types": "./../math/dist/types/math/*" } }, - "types": "./dist/utils/index.d.ts", "files": [ "dist/*" ], @@ -48,14 +52,8 @@ }, "bugs": "https://github.com/excalidraw/excalidraw/issues", "repository": "https://github.com/excalidraw/excalidraw", - "dependencies": { - "@excalidraw/utils": "*" - }, "scripts": { "gen:types": "rm -rf types && tsc", - "build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js", - "build:esm": "rm -rf dist && node ../../scripts/buildUtils.js && yarn gen:types", - "build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js", - "pack": "yarn build:umd && yarn pack" + "build:esm": "rm -rf dist && node ../../scripts/buildMath.js && yarn gen:types" } } diff --git a/packages/math/range.ts b/packages/math/range.ts index 314d1c8ae..d90530cba 100644 --- a/packages/math/range.ts +++ b/packages/math/range.ts @@ -1,4 +1,4 @@ -import { toBrandedType } from "../excalidraw/utils"; +import { toBrandedType } from "@excalidraw/excalidraw/utils"; import type { InclusiveRange } from "./types"; /** diff --git a/packages/math/tsconfig.json b/packages/math/tsconfig.json new file mode 100644 index 000000000..f61b8d0af --- /dev/null +++ b/packages/math/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "outDir": "./dist/types", + "target": "ESNext", + "strict": true, + "skipLibCheck": true, + "declaration": true, + "allowSyntheticDefaultImports": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "jsx": "react-jsx", + "emitDeclarationOnly": true, + "paths": { + "@excalidraw/excalidraw": ["../excalidraw/index.tsx"], + "@excalidraw/utils": ["../utils/index.ts"], + "@excalidraw/math": ["../math/index.ts"], + "@excalidraw/excalidraw/*": ["../excalidraw/*"], + "@excalidraw/utils/*": ["../utils/*"], + "@excalidraw/math/*": ["../math/*"] + } + }, + "exclude": ["**/*.test.*", "tests", "types", "examples", "dist"] +} diff --git a/packages/math/webpack.prod.config.js b/packages/math/webpack.prod.config.js deleted file mode 100644 index 410d67510..000000000 --- a/packages/math/webpack.prod.config.js +++ /dev/null @@ -1,55 +0,0 @@ -const webpack = require("webpack"); -const path = require("path"); -const BundleAnalyzerPlugin = - require("webpack-bundle-analyzer").BundleAnalyzerPlugin; - -module.exports = { - mode: "production", - entry: { "excalidraw-math.min": "./index.js" }, - output: { - path: path.resolve(__dirname, "dist"), - filename: "[name].js", - library: "ExcalidrawMath", - libraryTarget: "umd", - }, - resolve: { - extensions: [".tsx", ".ts", ".js", ".css", ".scss"], - }, - optimization: { - runtimeChunk: false, - }, - module: { - rules: [ - { - test: /\.(ts|tsx|js)$/, - use: [ - { - loader: "ts-loader", - options: { - transpileOnly: true, - configFile: path.resolve(__dirname, "../tsconfig.prod.json"), - }, - }, - { - loader: "babel-loader", - - options: { - presets: [ - "@babel/preset-env", - ["@babel/preset-react", { runtime: "automatic" }], - "@babel/preset-typescript", - ], - plugins: [["@babel/plugin-transform-runtime"]], - }, - }, - ], - }, - ], - }, - plugins: [ - new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1, - }), - ...(process.env.ANALYZER === "true" ? [new BundleAnalyzerPlugin()] : []), - ], -}; diff --git a/packages/tsconfig.dev.json b/packages/tsconfig.dev.json deleted file mode 100644 index 6462aaba3..000000000 --- a/packages/tsconfig.dev.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "compilerOptions": { - "target": "es6", - "module": "esNext", - "moduleResolution": "node", - "resolveJsonModule": true, - "jsx": "react-jsx", - "sourceMap": true, - "allowJs": true - } -} diff --git a/packages/tsconfig.prod.json b/packages/tsconfig.prod.json deleted file mode 100644 index 974b46318..000000000 --- a/packages/tsconfig.prod.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "compilerOptions": { - "target": "es2017", - "module": "es2015", - "moduleResolution": "node", - "resolveJsonModule": true, - "jsx": "react" - } -} diff --git a/packages/utils/bbox.ts b/packages/utils/bbox.ts index 933c630c8..19a1a5430 100644 --- a/packages/utils/bbox.ts +++ b/packages/utils/bbox.ts @@ -3,8 +3,8 @@ import { vectorFromPoint, type GlobalPoint, type LocalPoint, -} from "../math"; -import type { Bounds } from "../excalidraw/element/bounds"; +} from "@excalidraw/math"; +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; export type LineSegment

= [P, P]; diff --git a/packages/utils/collision.test.ts b/packages/utils/collision.test.ts index 300b5acc5..744bea367 100644 --- a/packages/utils/collision.test.ts +++ b/packages/utils/collision.test.ts @@ -1,4 +1,4 @@ -import type { Curve, Degrees, GlobalPoint } from "../math"; +import type { Curve, Degrees, GlobalPoint } from "@excalidraw/math"; import { curve, degreesToRadians, @@ -6,7 +6,7 @@ import { lineSegmentRotate, pointFrom, pointRotateDegs, -} from "../math"; +} from "@excalidraw/math"; import { pointOnCurve, pointOnPolyline } from "./collision"; import type { Polyline } from "./geometry/shape"; diff --git a/packages/utils/collision.ts b/packages/utils/collision.ts index 5af742b50..fb48f4e45 100644 --- a/packages/utils/collision.ts +++ b/packages/utils/collision.ts @@ -4,7 +4,7 @@ import { pointOnEllipse, type GeometricShape, } from "./geometry/shape"; -import type { Curve } from "../math"; +import type { Curve } from "@excalidraw/math"; import { lineSegment, pointFrom, @@ -15,7 +15,7 @@ import { type GlobalPoint, type LocalPoint, type Polygon, -} from "../math"; +} from "@excalidraw/math"; // check if the given point is considered on the given shape's border export const isPointOnShape = ( diff --git a/packages/utils/export.test.ts b/packages/utils/export.test.ts index b04ec44e2..e2af763b5 100644 --- a/packages/utils/export.test.ts +++ b/packages/utils/export.test.ts @@ -1,9 +1,9 @@ import * as utils from "."; -import { diagramFactory } from "../excalidraw/tests/fixtures/diagramFixture"; +import { diagramFactory } from "@excalidraw/excalidraw/tests/fixtures/diagramFixture"; import { vi } from "vitest"; -import * as mockedSceneExportUtils from "../excalidraw/scene/export"; +import * as mockedSceneExportUtils from "@excalidraw/excalidraw/scene/export"; -import { MIME_TYPES } from "../excalidraw/constants"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; const exportToSvgSpy = vi.spyOn(mockedSceneExportUtils, "exportToSvg"); diff --git a/packages/utils/export.ts b/packages/utils/export.ts index a82ef66e6..22287ce7e 100644 --- a/packages/utils/export.ts +++ b/packages/utils/export.ts @@ -1,23 +1,23 @@ import { exportToCanvas as _exportToCanvas, exportToSvg as _exportToSvg, -} from "../excalidraw/scene/export"; -import { getDefaultAppState } from "../excalidraw/appState"; -import type { AppState, BinaryFiles } from "../excalidraw/types"; +} from "@excalidraw/excalidraw/scene/export"; +import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; +import type { AppState, BinaryFiles } from "@excalidraw/excalidraw/types"; import type { ExcalidrawElement, ExcalidrawFrameLikeElement, NonDeleted, -} from "../excalidraw/element/types"; -import { restore } from "../excalidraw/data/restore"; -import { MIME_TYPES } from "../excalidraw/constants"; -import { encodePngMetadata } from "../excalidraw/data/image"; -import { serializeAsJSON } from "../excalidraw/data/json"; +} from "@excalidraw/excalidraw/element/types"; +import { restore } from "@excalidraw/excalidraw/data/restore"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import { encodePngMetadata } from "@excalidraw/excalidraw/data/image"; +import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, copyToClipboard, -} from "../excalidraw/clipboard"; +} from "@excalidraw/excalidraw/clipboard"; export { MIME_TYPES }; diff --git a/packages/utils/geometry/geometry.test.ts b/packages/utils/geometry/geometry.test.ts index 3f425d056..e9ad067fe 100644 --- a/packages/utils/geometry/geometry.test.ts +++ b/packages/utils/geometry/geometry.test.ts @@ -1,4 +1,9 @@ -import type { GlobalPoint, LineSegment, Polygon, Radians } from "../../math"; +import type { + GlobalPoint, + LineSegment, + Polygon, + Radians, +} from "@excalidraw/math"; import { pointFrom, lineSegment, @@ -7,7 +12,7 @@ import { pointOnPolygon, polygonIncludesPoint, segmentsIntersectAt, -} from "../../math"; +} from "@excalidraw/math"; import { pointInEllipse, pointOnEllipse, type Ellipse } from "./shape"; describe("point and line", () => { diff --git a/packages/utils/geometry/shape.ts b/packages/utils/geometry/shape.ts index 4670b23ab..2ba04a2b2 100644 --- a/packages/utils/geometry/shape.ts +++ b/packages/utils/geometry/shape.ts @@ -12,7 +12,7 @@ * to pure shapes */ -import type { Curve, LineSegment, Polygon, Radians } from "../../math"; +import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; import { curve, lineSegment, @@ -31,8 +31,8 @@ import { vectorScale, type GlobalPoint, type LocalPoint, -} from "../../math"; -import { getElementAbsoluteCoords } from "../../excalidraw/element"; +} from "@excalidraw/math"; +import { getElementAbsoluteCoords } from "@excalidraw/excalidraw/element"; import type { ElementsMap, ExcalidrawBindableElement, @@ -48,10 +48,10 @@ import type { ExcalidrawRectangleElement, ExcalidrawSelectionElement, ExcalidrawTextElement, -} from "../../excalidraw/element/types"; +} from "@excalidraw/excalidraw/element/types"; import { pointsOnBezierCurves } from "points-on-curve"; import type { Drawable, Op } from "roughjs/bin/core"; -import { invariant } from "../../excalidraw/utils"; +import { invariant } from "@excalidraw/excalidraw/utils"; // a polyline (made up term here) is a line consisting of other line segments // this corresponds to a straight line element in the editor but it could also diff --git a/packages/utils/global.d.ts b/packages/utils/global.d.ts index faf1d1878..16ade7a7d 100644 --- a/packages/utils/global.d.ts +++ b/packages/utils/global.d.ts @@ -1,3 +1,3 @@ /// -import "../excalidraw/global"; -import "../excalidraw/css"; +import "@excalidraw/excalidraw/global"; +import "@excalidraw/excalidraw/css"; diff --git a/packages/utils/index.ts b/packages/utils/index.ts index 9ba56da87..2a929134e 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -1,4 +1,4 @@ export * from "./export"; export * from "./withinBounds"; export * from "./bbox"; -export { getCommonBounds } from "../excalidraw/element/bounds"; +export { getCommonBounds } from "@excalidraw/excalidraw/element/bounds"; diff --git a/packages/utils/package.json b/packages/utils/package.json index b739eddc7..ddda1e7d6 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -1,20 +1,25 @@ { "name": "@excalidraw/utils", "version": "0.1.2", - "main": "./dist/prod/index.js", "type": "module", + "types": "./dist/types/utils/index.d.ts", + "main": "./dist/prod/index.js", "module": "./dist/prod/index.js", "exports": { ".": { + "types": "./dist/types/utils/index.d.ts", "development": "./dist/dev/index.js", + "production": "./dist/prod/index.js", "default": "./dist/prod/index.js" + }, + "./*": { + "types": "./../utils/dist/types/utils/*" } }, - "types": "./dist/utils/index.d.ts", "files": [ "dist/*" ], - "description": "Excalidraw utilities functions", + "description": "Excalidraw utility functions", "publishConfig": { "access": "public" }, @@ -47,7 +52,7 @@ "@excalidraw/laser-pointer": "1.3.1", "browser-fs-access": "0.29.1", "open-color": "1.9.1", - "pako": "1.0.11", + "pako": "2.0.3", "perfect-freehand": "1.2.0", "png-chunk-text": "1.0.0", "png-chunks-encode": "1.0.0", @@ -55,35 +60,16 @@ "roughjs": "4.6.4" }, "devDependencies": { - "@babel/core": "7.24.5", - "@babel/plugin-transform-arrow-functions": "7.24.1", - "@babel/plugin-transform-async-to-generator": "7.24.1", - "@babel/plugin-transform-runtime": "7.24.3", - "@babel/plugin-transform-typescript": "7.24.5", - "@babel/preset-env": "7.24.5", - "@babel/preset-typescript": "7.24.1", - "babel-loader": "8.2.5", - "babel-plugin-transform-class-properties": "6.24.1", "cross-env": "7.0.3", - "css-loader": "6.7.1", - "file-loader": "6.2.0", "fonteditor-core": "2.4.0", - "sass-loader": "13.0.2", - "ts-loader": "9.3.1", "typescript": "4.9.4", "wawoff2": "2.0.1", - "webpack": "5.76.0", - "webpack-bundle-analyzer": "4.5.0", - "webpack-cli": "4.10.0", "which": "4.0.0" }, "bugs": "https://github.com/excalidraw/excalidraw/issues", "repository": "https://github.com/excalidraw/excalidraw", "scripts": { "gen:types": "rm -rf types && tsc", - "build:umd": "cross-env NODE_ENV=production webpack --config webpack.prod.config.js", - "build:esm": "rm -rf dist && node ../../scripts/buildUtils.js && yarn gen:types", - "build:umd:withAnalyzer": "cross-env NODE_ENV=production ANALYZER=true webpack --config webpack.prod.config.js", - "pack": "yarn build:umd && yarn pack" + "build:esm": "rm -rf dist && node ../../scripts/buildUtils.js && yarn gen:types" } } diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json index f8aa631e9..f61b8d0af 100644 --- a/packages/utils/tsconfig.json +++ b/packages/utils/tsconfig.json @@ -1,16 +1,24 @@ { "compilerOptions": { + "outDir": "./dist/types", "target": "ESNext", "strict": true, - "outDir": "dist", "skipLibCheck": true, "declaration": true, - "emitDeclarationOnly": true, "allowSyntheticDefaultImports": true, "module": "ESNext", "moduleResolution": "Node", "resolveJsonModule": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "emitDeclarationOnly": true, + "paths": { + "@excalidraw/excalidraw": ["../excalidraw/index.tsx"], + "@excalidraw/utils": ["../utils/index.ts"], + "@excalidraw/math": ["../math/index.ts"], + "@excalidraw/excalidraw/*": ["../excalidraw/*"], + "@excalidraw/utils/*": ["../utils/*"], + "@excalidraw/math/*": ["../math/*"] + } }, - "exclude": ["**/*.test.*", "**/tests/*", "types", "dist"] + "exclude": ["**/*.test.*", "tests", "types", "examples", "dist"] } diff --git a/packages/utils/utils.unmocked.test.ts b/packages/utils/utils.unmocked.test.ts index e79a981c4..341adef95 100644 --- a/packages/utils/utils.unmocked.test.ts +++ b/packages/utils/utils.unmocked.test.ts @@ -1,8 +1,8 @@ -import type { ImportedDataState } from "../excalidraw/data/types"; -import * as utils from "../utils"; -import { API } from "../excalidraw/tests/helpers/api"; -import { decodeSvgBase64Payload } from "../excalidraw/scene/export"; -import { decodePngMetadata } from "../excalidraw/data/image"; +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; +import * as utils from "./index"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; +import { decodeSvgBase64Payload } from "@excalidraw/excalidraw/scene/export"; +import { decodePngMetadata } from "@excalidraw/excalidraw/data/image"; // NOTE this test file is using the actual API, unmocked. Hence splitting it // from the other test file, because I couldn't figure out how to test diff --git a/packages/utils/webpack.prod.config.js b/packages/utils/webpack.prod.config.js deleted file mode 100644 index 7238ad029..000000000 --- a/packages/utils/webpack.prod.config.js +++ /dev/null @@ -1,60 +0,0 @@ -const webpack = require("webpack"); -const path = require("path"); -const BundleAnalyzerPlugin = - require("webpack-bundle-analyzer").BundleAnalyzerPlugin; - -module.exports = { - mode: "production", - entry: { "excalidraw-utils.min": "./index.js" }, - output: { - path: path.resolve(__dirname, "dist"), - filename: "[name].js", - library: "ExcalidrawUtils", - libraryTarget: "umd", - }, - resolve: { - extensions: [".tsx", ".ts", ".js", ".css", ".scss"], - }, - optimization: { - runtimeChunk: false, - }, - module: { - rules: [ - { - test: /\.(sa|sc|c)ss$/, - exclude: /node_modules/, - use: ["style-loader", { loader: "css-loader" }, "sass-loader"], - }, - { - test: /\.(ts|tsx|js)$/, - use: [ - { - loader: "ts-loader", - options: { - transpileOnly: true, - configFile: path.resolve(__dirname, "../tsconfig.prod.json"), - }, - }, - { - loader: "babel-loader", - - options: { - presets: [ - "@babel/preset-env", - ["@babel/preset-react", { runtime: "automatic" }], - "@babel/preset-typescript", - ], - plugins: [["@babel/plugin-transform-runtime"]], - }, - }, - ], - }, - ], - }, - plugins: [ - new webpack.optimize.LimitChunkCountPlugin({ - maxChunks: 1, - }), - ...(process.env.ANALYZER === "true" ? [new BundleAnalyzerPlugin()] : []), - ], -}; diff --git a/packages/utils/withinBounds.test.ts b/packages/utils/withinBounds.test.ts index d0cc5e339..85354d742 100644 --- a/packages/utils/withinBounds.test.ts +++ b/packages/utils/withinBounds.test.ts @@ -1,5 +1,5 @@ -import type { Bounds } from "../excalidraw/element/bounds"; -import { API } from "../excalidraw/tests/helpers/api"; +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; import { elementPartiallyOverlapsWithOrContainsBBox, elementsOverlappingBBox, diff --git a/packages/utils/withinBounds.ts b/packages/utils/withinBounds.ts index 72c53aedf..8d52eb3ad 100644 --- a/packages/utils/withinBounds.ts +++ b/packages/utils/withinBounds.ts @@ -3,24 +3,24 @@ import type { ExcalidrawFreeDrawElement, ExcalidrawLinearElement, NonDeletedExcalidrawElement, -} from "../excalidraw/element/types"; +} from "@excalidraw/excalidraw/element/types"; import { isArrowElement, isExcalidrawElement, isFreeDrawElement, isLinearElement, isTextElement, -} from "../excalidraw/element/typeChecks"; -import type { Bounds } from "../excalidraw/element/bounds"; -import { getElementBounds } from "../excalidraw/element/bounds"; -import { arrayToMap } from "../excalidraw/utils"; -import type { LocalPoint } from "../math"; +} from "@excalidraw/excalidraw/element/typeChecks"; +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; +import { getElementBounds } from "@excalidraw/excalidraw/element/bounds"; +import { arrayToMap } from "@excalidraw/excalidraw/utils"; +import type { LocalPoint } from "@excalidraw/math"; import { rangeIncludesValue, pointFrom, pointRotateRads, rangeInclusive, -} from "../math"; +} from "@excalidraw/math"; type Element = NonDeletedExcalidrawElement; type Elements = readonly NonDeletedExcalidrawElement[]; diff --git a/scripts/buildExample.mjs b/scripts/buildExample.mjs deleted file mode 100644 index 5cc50c6c6..000000000 --- a/scripts/buildExample.mjs +++ /dev/null @@ -1,36 +0,0 @@ -import * as esbuild from "esbuild"; -import { sassPlugin } from "esbuild-sass-plugin"; -import { execSync } from "child_process"; - -const createDevBuild = async () => { - return await esbuild.build({ - entryPoints: ["../../examples/excalidraw/with-script-in-browser/index.tsx"], - outfile: - "../../examples/excalidraw/with-script-in-browser/public/bundle.js", - define: { - "import.meta.env": "{}", - }, - bundle: true, - format: "esm", - plugins: [sassPlugin()], - loader: { - ".woff2": "dataurl", - ".html": "copy", - }, - }); -}; - -const startServer = async (ctx) => { - await ctx.serve({ - servedir: "example/public", - port: 5001, - }); -}; -execSync( - `rm -rf ../../examples/excalidraw/with-script-in-browser/public/dist && yarn build:esm && cp -r dist ../../examples/excalidraw/with-script-in-browser/public`, -); - -const ctx = await createDevBuild(); - -// await startServer(ctx); -// console.info("Hosted at port http://localhost:5001!!"); diff --git a/scripts/buildMath.js b/scripts/buildMath.js index 47c191af5..fd2f820ea 100644 --- a/scripts/buildMath.js +++ b/scripts/buildMath.js @@ -1,108 +1,52 @@ -const fs = require("fs"); +const path = require("path"); const { build } = require("esbuild"); +const { sassPlugin } = require("esbuild-sass-plugin"); -const browserConfig = { - entryPoints: ["index.ts"], +// contains all dependencies bundled inside +const getConfig = (outdir) => ({ + outdir, bundle: true, format: "esm", -}; + entryPoints: ["index.ts"], + entryNames: "[name]", + assetNames: "[dir]/[name]", + alias: { + "@excalidraw/excalidraw": path.resolve(__dirname, "../packages/excalidraw"), + "@excalidraw/utils": path.resolve(__dirname, "../packages/utils"), + "@excalidraw/math": path.resolve(__dirname, "../packages/math"), + }, +}); -// Will be used later for treeshaking - -// function getFiles(dir, files = []) { -// const fileList = fs.readdirSync(dir); -// for (const file of fileList) { -// const name = `${dir}/${file}`; -// if ( -// name.includes("node_modules") || -// name.includes("config") || -// name.includes("package.json") || -// name.includes("main.js") || -// name.includes("index-node.ts") || -// name.endsWith(".d.ts") || -// name.endsWith(".md") -// ) { -// continue; -// } - -// if (fs.statSync(name).isDirectory()) { -// getFiles(name, files); -// } else if ( -// name.match(/\.(sa|sc|c)ss$/) || -// name.match(/\.(woff|woff2|eot|ttf|otf)$/) || -// name.match(/locales\/[^/]+\.json$/) -// ) { -// continue; -// } else { -// files.push(name); -// } -// } -// return files; -// } -const createESMBrowserBuild = async () => { - // Development unminified build with source maps - const browserDev = await build({ - ...browserConfig, - outdir: "dist/browser/dev", +function buildDev(config) { + return build({ + ...config, + plugins: [sassPlugin()], sourcemap: true, - metafile: true, define: { "import.meta.env": JSON.stringify({ DEV: true }), }, }); - fs.writeFileSync( - "meta-browser-dev.json", - JSON.stringify(browserDev.metafile), - ); +} - // production minified build without sourcemaps - const browserProd = await build({ - ...browserConfig, - outdir: "dist/browser/prod", +function buildProd(config) { + return build({ + ...config, + plugins: [sassPlugin()], minify: true, - metafile: true, define: { "import.meta.env": JSON.stringify({ PROD: true }), }, }); - fs.writeFileSync( - "meta-browser-prod.json", - JSON.stringify(browserProd.metafile), - ); -}; - -const rawConfig = { - entryPoints: ["index.ts"], - bundle: true, - format: "esm", - packages: "external", -}; +} const createESMRawBuild = async () => { - // Development unminified build with source maps - const rawDev = await build({ - ...rawConfig, - outdir: "dist/dev", - sourcemap: true, - metafile: true, - define: { - "import.meta.env": JSON.stringify({ DEV: true }), - }, - }); - fs.writeFileSync("meta-raw-dev.json", JSON.stringify(rawDev.metafile)); + // development unminified build with source maps + buildDev(getConfig("dist/dev")); // production minified build without sourcemaps - const rawProd = await build({ - ...rawConfig, - outdir: "dist/prod", - minify: true, - metafile: true, - define: { - "import.meta.env": JSON.stringify({ PROD: true }), - }, - }); - fs.writeFileSync("meta-raw-prod.json", JSON.stringify(rawProd.metafile)); + buildProd(getConfig("dist/prod")); }; -createESMRawBuild(); -createESMBrowserBuild(); +(async () => { + await createESMRawBuild(); +})(); diff --git a/scripts/buildPackage.js b/scripts/buildPackage.js index 0dd925ed5..e00eb96cb 100644 --- a/scripts/buildPackage.js +++ b/scripts/buildPackage.js @@ -1,165 +1,67 @@ +const path = require("path"); const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); -const { externalGlobalPlugin } = require("esbuild-plugin-external-global"); -// Will be used later for treeshaking -//const fs = require("fs"); -// const path = require("path"); - -// function getFiles(dir, files = []) { -// const fileList = fs.readdirSync(dir); -// for (const file of fileList) { -// const name = `${dir}/${file}`; -// if ( -// name.includes("node_modules") || -// name.includes("config") || -// name.includes("package.json") || -// name.includes("main.js") || -// name.includes("index-node.ts") || -// name.endsWith(".d.ts") -// ) { -// continue; -// } - -// if (fs.statSync(name).isDirectory()) { -// getFiles(name, files); -// } else if ( -// !( -// name.match(/\.(sa|sc|c)ss$/) || -// name.match(/\.(woff|woff2|eot|ttf|otf)$/) || -// name.match(/locales\/[^/]+\.json$/) -// ) -// ) { -// continue; -// } else { -// files.push(name); -// } -// } -// return files; -// } - -const browserConfig = { - entryPoints: ["index.tsx"], +// excludes all external dependencies and bundles only the source code +const getConfig = (outdir) => ({ + outdir, bundle: true, - format: "esm", - plugins: [ - sassPlugin(), - externalGlobalPlugin({ - react: "React", - "react-dom": "ReactDOM", - }), - ], splitting: true, - loader: { - ".woff2": "file", - }, -}; -const createESMBrowserBuild = async () => { - // Development unminified build with source maps - await build({ - ...browserConfig, - outdir: "dist/browser/dev", - sourcemap: true, - chunkNames: "excalidraw-assets-dev/[name]-[hash]", - assetNames: "excalidraw-assets-dev/[name]-[hash]", - define: { - "import.meta.env": JSON.stringify({ DEV: true }), - }, - }); - - // production minified build without sourcemaps - await build({ - ...browserConfig, - outdir: "dist/browser/prod", - minify: true, - chunkNames: "excalidraw-assets/[name]-[hash]", - assetNames: "excalidraw-assets/[name]-[hash]", - define: { - "import.meta.env": JSON.stringify({ PROD: true }), - }, - }); -}; - -// const BASE_PATH = `${path.resolve(`${__dirname}/..`)}`; -// const filesinExcalidrawPackage = [ -// ...getFiles(`${BASE_PATH}/packages/excalidraw`), -// `${BASE_PATH}/packages/utils/export.ts`, -// `${BASE_PATH}/packages/utils/bbox.ts`, -// ...getFiles(`${BASE_PATH}/public/fonts`), -// ]; - -// const filesToTransform = filesinExcalidrawPackage.filter((file) => { -// return !( -// file.includes("/__tests__/") || -// file.includes(".test.") || -// file.includes("/tests/") || -// file.includes("example") -// ); -// }); - -const rawConfigCommon = { - bundle: true, format: "esm", + packages: "external", plugins: [sassPlugin()], - assetNames: "[dir]/[name]-[hash]", + target: "es2020", + assetNames: "[dir]/[name]", + chunkNames: "[dir]/[name]-[hash]", + alias: { + "@excalidraw/excalidraw": path.resolve(__dirname, "../packages/excalidraw"), + "@excalidraw/utils": path.resolve(__dirname, "../packages/utils"), + "@excalidraw/math": path.resolve(__dirname, "../packages/math"), + }, loader: { - ".json": "copy", ".woff2": "file", }, - packages: "external", - // chunks are always external, so they are not bundled within and get build separately - external: ["*.chunk"], -}; +}); -const rawConfigIndex = { - ...rawConfigCommon, - entryPoints: ["index.tsx"], -}; - -const rawConfigChunks = { - ...rawConfigCommon, - // create a separate chunk for each - entryPoints: ["**/*.chunk.ts"], -}; - -function buildDev(chunkConfig) { - const config = { - ...chunkConfig, +function buildDev(config) { + return build({ + ...config, sourcemap: true, define: { "import.meta.env": JSON.stringify({ DEV: true }), }, - outdir: "dist/dev", - }; - - return build(config); + }); } -function buildProd(chunkConfig) { - const config = { - ...chunkConfig, +function buildProd(config) { + return build({ + ...config, minify: true, define: { "import.meta.env": JSON.stringify({ PROD: true }), }, - outdir: "dist/prod", - }; - - return build(config); + }); } const createESMRawBuild = async () => { + const chunksConfig = { + entryPoints: ["index.tsx", "**/*.chunk.ts"], + entryNames: "[name]", + }; + // development unminified build with source maps - await buildDev(rawConfigIndex); - await buildDev(rawConfigChunks); + await buildDev({ + ...getConfig("dist/dev"), + ...chunksConfig, + }); // production minified buld without sourcemaps - await buildProd(rawConfigIndex); - await buildProd(rawConfigChunks); + await buildProd({ + ...getConfig("dist/prod"), + ...chunksConfig, + }); }; -// otherwise throws "ERROR: Could not resolve "./subset-worker.chunk" (async () => { await createESMRawBuild(); - await createESMBrowserBuild(); })(); diff --git a/scripts/buildUtils.js b/scripts/buildUtils.js index 6e4780a81..65b947385 100644 --- a/scripts/buildUtils.js +++ b/scripts/buildUtils.js @@ -1,130 +1,58 @@ -const fs = require("fs"); +const path = require("path"); const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); const { woff2ServerPlugin } = require("./woff2/woff2-esbuild-plugins"); -const browserConfig = { - entryPoints: ["index.ts"], +// contains all dependencies bundled inside +const getConfig = (outdir) => ({ + outdir, bundle: true, format: "esm", - plugins: [sassPlugin()], - assetNames: "assets/[name]", - loader: { - ".woff2": "file", + entryPoints: ["index.ts"], + entryNames: "[name]", + assetNames: "[dir]/[name]", + alias: { + "@excalidraw/excalidraw": path.resolve(__dirname, "../packages/excalidraw"), + "@excalidraw/utils": path.resolve(__dirname, "../packages/utils"), + "@excalidraw/math": path.resolve(__dirname, "../packages/math"), }, -}; +}); -// Will be used later for treeshaking - -// function getFiles(dir, files = []) { -// const fileList = fs.readdirSync(dir); -// for (const file of fileList) { -// const name = `${dir}/${file}`; -// if ( -// name.includes("node_modules") || -// name.includes("config") || -// name.includes("package.json") || -// name.includes("main.js") || -// name.includes("index-node.ts") || -// name.endsWith(".d.ts") || -// name.endsWith(".md") -// ) { -// continue; -// } - -// if (fs.statSync(name).isDirectory()) { -// getFiles(name, files); -// } else if ( -// name.match(/\.(sa|sc|c)ss$/) || -// name.match(/\.(woff|woff2|eot|ttf|otf)$/) || -// name.match(/locales\/[^/]+\.json$/) -// ) { -// continue; -// } else { -// files.push(name); -// } -// } -// return files; -// } -const createESMBrowserBuild = async () => { - // Development unminified build with source maps - const browserDev = await build({ - ...browserConfig, - outdir: "dist/browser/dev", +function buildDev(config) { + return build({ + ...config, sourcemap: true, - metafile: true, + plugins: [sassPlugin(), woff2ServerPlugin()], define: { "import.meta.env": JSON.stringify({ DEV: true }), }, }); - fs.writeFileSync( - "meta-browser-dev.json", - JSON.stringify(browserDev.metafile), - ); +} - // production minified build without sourcemaps - const browserProd = await build({ - ...browserConfig, - outdir: "dist/browser/prod", +function buildProd(config) { + return build({ + ...config, minify: true, - metafile: true, - define: { - "import.meta.env": JSON.stringify({ PROD: true }), - }, - }); - fs.writeFileSync( - "meta-browser-prod.json", - JSON.stringify(browserProd.metafile), - ); -}; - -const rawConfig = { - entryPoints: ["index.ts"], - bundle: true, - format: "esm", -}; - -// const BASE_PATH = `${path.resolve(`${__dirname}/..`)}`; -// const filesinExcalidrawPackage = getFiles(`${BASE_PATH}/packages/utils`); - -// const filesToTransform = filesinExcalidrawPackage.filter((file) => { -// return !( -// file.includes("/__tests__/") || -// file.includes(".test.") || -// file.includes("/tests/") || -// file.includes("example") -// ); -// }); -const createESMRawBuild = async () => { - // Development unminified build with source maps - const rawDev = await build({ - ...rawConfig, - outdir: "dist/dev", - sourcemap: true, - metafile: true, - plugins: [sassPlugin(), woff2ServerPlugin({ outdir: "dist/dev/assets" })], - define: { - "import.meta.env": JSON.stringify({ DEV: true }), - }, - }); - fs.writeFileSync("meta-raw-dev.json", JSON.stringify(rawDev.metafile)); - - // production minified build without sourcemaps - const rawProd = await build({ - ...rawConfig, - outdir: "dist/prod", - minify: true, - metafile: true, plugins: [ sassPlugin(), - woff2ServerPlugin({ outdir: "dist/prod/assets", generateTtf: true }), + woff2ServerPlugin({ + outdir: `${config.outdir}/assets`, + }), ], define: { "import.meta.env": JSON.stringify({ PROD: true }), }, }); - fs.writeFileSync("meta-raw-prod.json", JSON.stringify(rawProd.metafile)); +} + +const createESMRawBuild = async () => { + // development unminified build with source maps + buildDev(getConfig("dist/dev")); + + // production minified build without sourcemaps + buildProd(getConfig("dist/prod")); }; -createESMRawBuild(); -createESMBrowserBuild(); +(async () => { + await createESMRawBuild(); +})(); diff --git a/scripts/prerelease.js b/scripts/prerelease.js index 1641f99e1..3b8080d33 100644 --- a/scripts/prerelease.js +++ b/scripts/prerelease.js @@ -3,7 +3,7 @@ const util = require("util"); const exec = util.promisify(require("child_process").exec); const updateChangelog = require("./updateChangelog"); -const excalidrawDir = `${__dirname}/../packages/excalidraw/packages/excalidraw`; +const excalidrawDir = `${__dirname}/../packages/excalidraw/`; const excalidrawPackage = `${excalidrawDir}/package.json`; const updatePackageVersion = (nextVersion) => { diff --git a/scripts/woff2/woff2-esbuild-plugins.js b/scripts/woff2/woff2-esbuild-plugins.js index e53dd0299..19ebafc93 100644 --- a/scripts/woff2/woff2-esbuild-plugins.js +++ b/scripts/woff2/woff2-esbuild-plugins.js @@ -20,8 +20,6 @@ module.exports.woff2ServerPlugin = (options = {}) => { return { name: "woff2ServerPlugin", setup(build) { - const { outdir, generateTtf } = options; - const outputDir = path.resolve(outdir); const fonts = new Map(); build.onResolve({ filter: /\.woff2$/ }, (args) => { @@ -94,9 +92,12 @@ module.exports.woff2ServerPlugin = (options = {}) => { ); build.onEnd(async () => { - if (!generateTtf) { + const { outdir } = options; + + if (!outdir) { return; } + const outputDir = path.resolve(outdir); const isFontToolsInstalled = await which("fonttools", { nothrow: true, diff --git a/tsconfig.json b/tsconfig.json index 617b3531c..3eded705f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,9 @@ { "compilerOptions": { - "types": ["vitest/globals", "@testing-library/jest-dom"], + "rootDir": "./", "target": "ESNext", "lib": ["dom", "dom.iterable", "esnext"], + "types": ["vitest/globals", "@testing-library/jest-dom"], "allowJs": true, "skipLibCheck": true, "esModuleInterop": true, @@ -15,8 +16,17 @@ "resolveJsonModule": true, "isolatedModules": true, "noEmit": true, - "jsx": "react-jsx" + "jsx": "react-jsx", + "baseUrl": ".", + "paths": { + "@excalidraw/excalidraw": ["./packages/excalidraw/index.tsx"], + "@excalidraw/utils": ["./packages/utils/index.ts"], + "@excalidraw/math": ["./packages/math/index.ts"], + "@excalidraw/excalidraw/*": ["./packages/excalidraw/*"], + "@excalidraw/utils/*": ["./packages/utils/*"], + "@excalidraw/math/*": ["./packages/math/*"] + } }, "include": ["packages", "excalidraw-app"], - "exclude": ["packages/excalidraw/types", "examples"] + "exclude": ["examples", "dist", "types", "tests"] } diff --git a/vitest.config.mts b/vitest.config.mts index 99098eb91..f9d7d255e 100644 --- a/vitest.config.mts +++ b/vitest.config.mts @@ -1,6 +1,36 @@ +import path from "path"; + import { defineConfig } from "vitest/config"; export default defineConfig({ + resolve: { + alias: [ + { + find: /^@excalidraw\/excalidraw$/, + replacement: path.resolve(__dirname, "./packages/excalidraw/index.tsx"), + }, + { + find: /^@excalidraw\/excalidraw\/(.*?)/, + replacement: path.resolve(__dirname, "./packages/excalidraw/$1"), + }, + { + find: /^@excalidraw\/utils$/, + replacement: path.resolve(__dirname, "./packages/utils/index.ts"), + }, + { + find: /^@excalidraw\/utils\/(.*?)/, + replacement: path.resolve(__dirname, "./packages/utils/$1"), + }, + { + find: /^@excalidraw\/math$/, + replacement: path.resolve(__dirname, "./packages/math/index.ts"), + }, + { + find: /^@excalidraw\/math\/(.*?)/, + replacement: path.resolve(__dirname, "./packages/math/$1"), + }, + ], + }, //@ts-ignore test: { // Since hooks are running in stack in v2, which means all hooks run serially whereas diff --git a/yarn.lock b/yarn.lock index 5c1197d30..043db6da0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -31,7 +31,7 @@ dependencies: "@babel/highlight" "^7.10.4" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.24.2", "@babel/code-frame@^7.26.2": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== @@ -40,32 +40,11 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.24.4", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.26.5", "@babel/compat-data@^7.26.8": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== -"@babel/core@7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.5.tgz#15ab5b98e101972d171aeef92ac70d8d6718f06a" - integrity sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA== - dependencies: - "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.24.2" - "@babel/generator" "^7.24.5" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-module-transforms" "^7.24.5" - "@babel/helpers" "^7.24.5" - "@babel/parser" "^7.24.5" - "@babel/template" "^7.24.0" - "@babel/traverse" "^7.24.5" - "@babel/types" "^7.24.5" - convert-source-map "^2.0.0" - debug "^4.1.0" - gensync "^1.0.0-beta.2" - json5 "^2.2.3" - semver "^6.3.1" - "@babel/core@^7.16.0", "@babel/core@^7.20.12", "@babel/core@^7.21.3", "@babel/core@^7.24.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" @@ -96,7 +75,7 @@ eslint-visitor-keys "^2.1.0" semver "^6.3.1" -"@babel/generator@^7.24.5", "@babel/generator@^7.26.9": +"@babel/generator@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.9.tgz#75a9482ad3d0cc7188a537aa4910bc59db67cbca" integrity sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg== @@ -107,14 +86,14 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" -"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5", "@babel/helper-annotate-as-pure@^7.25.9": +"@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz#d8eac4d2dc0d7b6e11fa6e535332e0d3184f06b4" integrity sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g== dependencies: "@babel/types" "^7.25.9" -"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.23.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": +"@babel/helper-compilation-targets@^7.22.6", "@babel/helper-compilation-targets@^7.25.9", "@babel/helper-compilation-targets@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz#75d92bb8d8d51301c0d49e52a65c9a7fe94514d8" integrity sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA== @@ -125,7 +104,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.24.5", "@babel/helper-create-class-features-plugin@^7.25.9": +"@babel/helper-create-class-features-plugin@^7.18.6", "@babel/helper-create-class-features-plugin@^7.21.0", "@babel/helper-create-class-features-plugin@^7.25.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz#d6f83e3039547fbb39967e78043cd3c8b7820c71" integrity sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg== @@ -166,7 +145,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3", "@babel/helper-module-imports@^7.25.9": +"@babel/helper-module-imports@^7.10.4", "@babel/helper-module-imports@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== @@ -174,7 +153,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helper-module-transforms@^7.24.5", "@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": +"@babel/helper-module-transforms@^7.25.9", "@babel/helper-module-transforms@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== @@ -190,12 +169,12 @@ dependencies: "@babel/types" "^7.25.9" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.24.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.25.9", "@babel/helper-plugin-utils@^7.26.5", "@babel/helper-plugin-utils@^7.8.0": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== -"@babel/helper-remap-async-to-generator@^7.22.20", "@babel/helper-remap-async-to-generator@^7.25.9": +"@babel/helper-remap-async-to-generator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz#e53956ab3d5b9fb88be04b3e2f31b523afd34b92" integrity sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw== @@ -231,7 +210,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== -"@babel/helper-validator-option@^7.23.5", "@babel/helper-validator-option@^7.25.9": +"@babel/helper-validator-option@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== @@ -245,7 +224,7 @@ "@babel/traverse" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/helpers@^7.24.5", "@babel/helpers@^7.26.9": +"@babel/helpers@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.26.9.tgz#28f3fb45252fc88ef2dc547c8a911c255fc9fef6" integrity sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA== @@ -263,14 +242,14 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.24.5", "@babel/parser@^7.25.4", "@babel/parser@^7.26.9": +"@babel/parser@^7.25.4", "@babel/parser@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== dependencies: "@babel/types" "^7.26.9" -"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5", "@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": +"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz#cc2e53ebf0a0340777fff5ed521943e253b4d8fe" integrity sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g== @@ -285,14 +264,14 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1", "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz#e8dc26fcd616e6c5bf2bd0d5a2c151d4f92a9137" integrity sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz#807a667f9158acac6f6164b4beb85ad9ebc9e1d1" integrity sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g== @@ -301,7 +280,7 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" "@babel/plugin-transform-optional-chaining" "^7.25.9" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1", "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz#de7093f1e7deaf68eadd7cc6b07f2ab82543269e" integrity sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg== @@ -364,7 +343,7 @@ resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz#7844f9289546efa9febac2de4cfe358a050bd703" integrity sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w== -"@babel/plugin-proposal-private-property-in-object@7.21.11", "@babel/plugin-proposal-private-property-in-object@^7.16.7": +"@babel/plugin-proposal-private-property-in-object@^7.16.7": version "7.21.11" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz#69d597086b6760c4126525cfa154f34631ff272c" integrity sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw== @@ -374,27 +353,6 @@ "@babel/helper-plugin-utils" "^7.20.2" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-syntax-async-generators@^7.8.4": - version "7.8.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" - integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-class-properties@^7.12.13": - version "7.12.13" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz#b5c987274c4a3a82b89714796931a6b53544ae10" - integrity sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA== - dependencies: - "@babel/helper-plugin-utils" "^7.12.13" - -"@babel/plugin-syntax-class-static-block@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz#195df89b146b4b78b3bf897fd7a257c84659d406" - integrity sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - "@babel/plugin-syntax-decorators@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz#986b4ca8b7b5df3f67cee889cedeffc2e2bf14b3" @@ -402,20 +360,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-dynamic-import@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" - integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-export-namespace-from@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz#028964a9ba80dbc094c915c487ad7c4e7a66465a" - integrity sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.3" - "@babel/plugin-syntax-flow@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz#96507595c21b45fccfc2bc758d5c45452e6164fa" @@ -423,48 +367,27 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-assertions@^7.24.1", "@babel/plugin-syntax-import-assertions@^7.26.0": +"@babel/plugin-syntax-import-assertions@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz#620412405058efa56e4a564903b79355020f445f" integrity sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-attributes@^7.24.1", "@babel/plugin-syntax-import-attributes@^7.26.0": +"@babel/plugin-syntax-import-attributes@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz#3b1412847699eea739b4f2602c74ce36f6b0b0f7" integrity sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-import-meta@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz#ee601348c370fa334d2207be158777496521fd51" - integrity sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - -"@babel/plugin-syntax-json-strings@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" - integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-jsx@^7.24.1", "@babel/plugin-syntax-jsx@^7.25.9": +"@babel/plugin-syntax-jsx@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz#a34313a178ea56f1951599b929c1ceacee719290" integrity sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-syntax-logical-assignment-operators@^7.10.4": - version "7.10.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz#ca91ef46303530448b906652bac2e9fe9941f699" - integrity sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig== - dependencies: - "@babel/helper-plugin-utils" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" @@ -479,20 +402,6 @@ dependencies: "@babel/helper-plugin-utils" "^7.10.4" -"@babel/plugin-syntax-object-rest-spread@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" - integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - -"@babel/plugin-syntax-optional-catch-binding@^7.8.3": - version "7.8.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" - integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== - dependencies: - "@babel/helper-plugin-utils" "^7.8.0" - "@babel/plugin-syntax-optional-chaining@^7.8.3": version "7.8.3" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" @@ -507,14 +416,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-top-level-await@^7.14.5": - version "7.14.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz#c1cfdadc35a646240001f06138247b741c34d94c" - integrity sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw== - dependencies: - "@babel/helper-plugin-utils" "^7.14.5" - -"@babel/plugin-syntax-typescript@^7.24.1", "@babel/plugin-syntax-typescript@^7.25.9": +"@babel/plugin-syntax-typescript@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz#67dda2b74da43727cf21d46cf9afef23f4365399" integrity sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ== @@ -529,21 +431,14 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" - integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - -"@babel/plugin-transform-arrow-functions@^7.24.1", "@babel/plugin-transform-arrow-functions@^7.25.9": +"@babel/plugin-transform-arrow-functions@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz#7821d4410bee5daaadbb4cdd9a6649704e176845" integrity sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-async-generator-functions@^7.24.3", "@babel/plugin-transform-async-generator-functions@^7.26.8": +"@babel/plugin-transform-async-generator-functions@^7.26.8": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz#5e3991135e3b9c6eaaf5eff56d1ae5a11df45ff8" integrity sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg== @@ -552,16 +447,7 @@ "@babel/helper-remap-async-to-generator" "^7.25.9" "@babel/traverse" "^7.26.8" -"@babel/plugin-transform-async-to-generator@7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" - integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== - dependencies: - "@babel/helper-module-imports" "^7.24.1" - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-remap-async-to-generator" "^7.22.20" - -"@babel/plugin-transform-async-to-generator@^7.24.1", "@babel/plugin-transform-async-to-generator@^7.25.9": +"@babel/plugin-transform-async-to-generator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz#c80008dacae51482793e5a9c08b39a5be7e12d71" integrity sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ== @@ -570,21 +456,21 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-remap-async-to-generator" "^7.25.9" -"@babel/plugin-transform-block-scoped-functions@^7.24.1", "@babel/plugin-transform-block-scoped-functions@^7.26.5": +"@babel/plugin-transform-block-scoped-functions@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz#3dc4405d31ad1cbe45293aa57205a6e3b009d53e" integrity sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ== dependencies: "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-block-scoping@^7.24.5", "@babel/plugin-transform-block-scoping@^7.25.9": +"@babel/plugin-transform-block-scoping@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz#c33665e46b06759c93687ca0f84395b80c0473a1" integrity sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-class-properties@^7.24.1", "@babel/plugin-transform-class-properties@^7.25.9": +"@babel/plugin-transform-class-properties@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz#a8ce84fedb9ad512549984101fa84080a9f5f51f" integrity sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q== @@ -592,7 +478,7 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-class-static-block@^7.24.4", "@babel/plugin-transform-class-static-block@^7.26.0": +"@babel/plugin-transform-class-static-block@^7.26.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz#6c8da219f4eb15cae9834ec4348ff8e9e09664a0" integrity sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ== @@ -600,7 +486,7 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-classes@^7.24.5", "@babel/plugin-transform-classes@^7.25.9": +"@babel/plugin-transform-classes@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz#7152457f7880b593a63ade8a861e6e26a4469f52" integrity sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg== @@ -612,7 +498,7 @@ "@babel/traverse" "^7.25.9" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.24.1", "@babel/plugin-transform-computed-properties@^7.25.9": +"@babel/plugin-transform-computed-properties@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz#db36492c78460e534b8852b1d5befe3c923ef10b" integrity sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA== @@ -620,14 +506,14 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/template" "^7.25.9" -"@babel/plugin-transform-destructuring@^7.24.5", "@babel/plugin-transform-destructuring@^7.25.9": +"@babel/plugin-transform-destructuring@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz#966ea2595c498224340883602d3cfd7a0c79cea1" integrity sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-dotall-regex@^7.24.1", "@babel/plugin-transform-dotall-regex@^7.25.9": +"@babel/plugin-transform-dotall-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz#bad7945dd07734ca52fe3ad4e872b40ed09bb09a" integrity sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA== @@ -635,7 +521,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-duplicate-keys@^7.24.1", "@babel/plugin-transform-duplicate-keys@^7.25.9": +"@babel/plugin-transform-duplicate-keys@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz#8850ddf57dce2aebb4394bb434a7598031059e6d" integrity sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw== @@ -650,21 +536,21 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-dynamic-import@^7.24.1", "@babel/plugin-transform-dynamic-import@^7.25.9": +"@babel/plugin-transform-dynamic-import@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz#23e917de63ed23c6600c5dd06d94669dce79f7b8" integrity sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-exponentiation-operator@^7.24.1", "@babel/plugin-transform-exponentiation-operator@^7.26.3": +"@babel/plugin-transform-exponentiation-operator@^7.26.3": version "7.26.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz#e29f01b6de302c7c2c794277a48f04a9ca7f03bc" integrity sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-export-namespace-from@^7.24.1", "@babel/plugin-transform-export-namespace-from@^7.25.9": +"@babel/plugin-transform-export-namespace-from@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz#90745fe55053394f554e40584cda81f2c8a402a2" integrity sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww== @@ -679,7 +565,7 @@ "@babel/helper-plugin-utils" "^7.26.5" "@babel/plugin-syntax-flow" "^7.26.0" -"@babel/plugin-transform-for-of@^7.24.1", "@babel/plugin-transform-for-of@^7.26.9": +"@babel/plugin-transform-for-of@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz#27231f79d5170ef33b5111f07fe5cafeb2c96a56" integrity sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg== @@ -687,7 +573,7 @@ "@babel/helper-plugin-utils" "^7.26.5" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-function-name@^7.24.1", "@babel/plugin-transform-function-name@^7.25.9": +"@babel/plugin-transform-function-name@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz#939d956e68a606661005bfd550c4fc2ef95f7b97" integrity sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA== @@ -696,35 +582,35 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/plugin-transform-json-strings@^7.24.1", "@babel/plugin-transform-json-strings@^7.25.9": +"@babel/plugin-transform-json-strings@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz#c86db407cb827cded902a90c707d2781aaa89660" integrity sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-literals@^7.24.1", "@babel/plugin-transform-literals@^7.25.9": +"@babel/plugin-transform-literals@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz#1a1c6b4d4aa59bc4cad5b6b3a223a0abd685c9de" integrity sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-logical-assignment-operators@^7.24.1", "@babel/plugin-transform-logical-assignment-operators@^7.25.9": +"@babel/plugin-transform-logical-assignment-operators@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz#b19441a8c39a2fda0902900b306ea05ae1055db7" integrity sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-member-expression-literals@^7.24.1", "@babel/plugin-transform-member-expression-literals@^7.25.9": +"@babel/plugin-transform-member-expression-literals@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz#63dff19763ea64a31f5e6c20957e6a25e41ed5de" integrity sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-amd@^7.24.1", "@babel/plugin-transform-modules-amd@^7.25.9": +"@babel/plugin-transform-modules-amd@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz#49ba478f2295101544abd794486cd3088dddb6c5" integrity sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw== @@ -732,7 +618,7 @@ "@babel/helper-module-transforms" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-commonjs@^7.24.1", "@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3": +"@babel/plugin-transform-modules-commonjs@^7.25.9", "@babel/plugin-transform-modules-commonjs@^7.26.3": version "7.26.3" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz#8f011d44b20d02c3de44d8850d971d8497f981fb" integrity sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ== @@ -740,7 +626,7 @@ "@babel/helper-module-transforms" "^7.26.0" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-modules-systemjs@^7.24.1", "@babel/plugin-transform-modules-systemjs@^7.25.9": +"@babel/plugin-transform-modules-systemjs@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz#8bd1b43836269e3d33307151a114bcf3ba6793f8" integrity sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA== @@ -750,7 +636,7 @@ "@babel/helper-validator-identifier" "^7.25.9" "@babel/traverse" "^7.25.9" -"@babel/plugin-transform-modules-umd@^7.24.1", "@babel/plugin-transform-modules-umd@^7.25.9": +"@babel/plugin-transform-modules-umd@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz#6710079cdd7c694db36529a1e8411e49fcbf14c9" integrity sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw== @@ -758,7 +644,7 @@ "@babel/helper-module-transforms" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-named-capturing-groups-regex@^7.22.5", "@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": +"@babel/plugin-transform-named-capturing-groups-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz#454990ae6cc22fd2a0fa60b3a2c6f63a38064e6a" integrity sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA== @@ -766,28 +652,28 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-new-target@^7.24.1", "@babel/plugin-transform-new-target@^7.25.9": +"@babel/plugin-transform-new-target@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz#42e61711294b105c248336dcb04b77054ea8becd" integrity sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1", "@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": +"@babel/plugin-transform-nullish-coalescing-operator@^7.26.6": version "7.26.6" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz#fbf6b3c92cb509e7b319ee46e3da89c5bedd31fe" integrity sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw== dependencies: "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-numeric-separator@^7.24.1", "@babel/plugin-transform-numeric-separator@^7.25.9": +"@babel/plugin-transform-numeric-separator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz#bfed75866261a8b643468b0ccfd275f2033214a1" integrity sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-object-rest-spread@^7.24.5", "@babel/plugin-transform-object-rest-spread@^7.25.9": +"@babel/plugin-transform-object-rest-spread@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz#0203725025074164808bcf1a2cfa90c652c99f18" integrity sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg== @@ -796,7 +682,7 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/plugin-transform-parameters" "^7.25.9" -"@babel/plugin-transform-object-super@^7.24.1", "@babel/plugin-transform-object-super@^7.25.9": +"@babel/plugin-transform-object-super@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz#385d5de135162933beb4a3d227a2b7e52bb4cf03" integrity sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A== @@ -804,14 +690,14 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-replace-supers" "^7.25.9" -"@babel/plugin-transform-optional-catch-binding@^7.24.1", "@babel/plugin-transform-optional-catch-binding@^7.25.9": +"@babel/plugin-transform-optional-catch-binding@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz#10e70d96d52bb1f10c5caaac59ac545ea2ba7ff3" integrity sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-optional-chaining@^7.24.5", "@babel/plugin-transform-optional-chaining@^7.25.9": +"@babel/plugin-transform-optional-chaining@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz#e142eb899d26ef715435f201ab6e139541eee7dd" integrity sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A== @@ -819,14 +705,14 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-parameters@^7.24.5", "@babel/plugin-transform-parameters@^7.25.9": +"@babel/plugin-transform-parameters@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz#b856842205b3e77e18b7a7a1b94958069c7ba257" integrity sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-methods@^7.24.1", "@babel/plugin-transform-private-methods@^7.25.9": +"@babel/plugin-transform-private-methods@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz#847f4139263577526455d7d3223cd8bda51e3b57" integrity sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw== @@ -834,7 +720,7 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-private-property-in-object@^7.24.5", "@babel/plugin-transform-private-property-in-object@^7.25.9": +"@babel/plugin-transform-private-property-in-object@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz#9c8b73e64e6cc3cbb2743633885a7dd2c385fe33" integrity sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw== @@ -843,21 +729,21 @@ "@babel/helper-create-class-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-property-literals@^7.24.1", "@babel/plugin-transform-property-literals@^7.25.9": +"@babel/plugin-transform-property-literals@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz#d72d588bd88b0dec8b62e36f6fda91cedfe28e3f" integrity sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.24.1", "@babel/plugin-transform-react-display-name@^7.25.9": +"@babel/plugin-transform-react-display-name@^7.16.0", "@babel/plugin-transform-react-display-name@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz#4b79746b59efa1f38c8695065a92a9f5afb24f7d" integrity sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx-development@^7.22.5", "@babel/plugin-transform-react-jsx-development@^7.25.9": +"@babel/plugin-transform-react-jsx-development@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz#8fd220a77dd139c07e25225a903b8be8c829e0d7" integrity sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw== @@ -878,7 +764,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx@^7.23.4", "@babel/plugin-transform-react-jsx@^7.25.9": +"@babel/plugin-transform-react-jsx@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz#06367940d8325b36edff5e2b9cbe782947ca4166" integrity sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw== @@ -889,7 +775,7 @@ "@babel/plugin-syntax-jsx" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/plugin-transform-react-pure-annotations@^7.24.1", "@babel/plugin-transform-react-pure-annotations@^7.25.9": +"@babel/plugin-transform-react-pure-annotations@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz#ea1c11b2f9dbb8e2d97025f43a3b5bc47e18ae62" integrity sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg== @@ -897,7 +783,7 @@ "@babel/helper-annotate-as-pure" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-regenerator@^7.24.1", "@babel/plugin-transform-regenerator@^7.25.9": +"@babel/plugin-transform-regenerator@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz#03a8a4670d6cebae95305ac6defac81ece77740b" integrity sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg== @@ -913,25 +799,13 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-reserved-words@^7.24.1", "@babel/plugin-transform-reserved-words@^7.25.9": +"@babel/plugin-transform-reserved-words@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz#0398aed2f1f10ba3f78a93db219b27ef417fb9ce" integrity sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-runtime@7.24.3": - version "7.24.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz#dc58ad4a31810a890550365cc922e1ff5acb5d7f" - integrity sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ== - dependencies: - "@babel/helper-module-imports" "^7.24.3" - "@babel/helper-plugin-utils" "^7.24.0" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.1" - babel-plugin-polyfill-regenerator "^0.6.1" - semver "^6.3.1" - "@babel/plugin-transform-runtime@^7.16.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.26.9.tgz#ea8be19ef134668e98f7b54daf7c4f853859dc44" @@ -944,14 +818,14 @@ babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.24.1", "@babel/plugin-transform-shorthand-properties@^7.25.9": +"@babel/plugin-transform-shorthand-properties@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz#bb785e6091f99f826a95f9894fc16fde61c163f2" integrity sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-spread@^7.24.1", "@babel/plugin-transform-spread@^7.25.9": +"@babel/plugin-transform-spread@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz#24a35153931b4ba3d13cec4a7748c21ab5514ef9" integrity sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A== @@ -959,38 +833,28 @@ "@babel/helper-plugin-utils" "^7.25.9" "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" -"@babel/plugin-transform-sticky-regex@^7.24.1", "@babel/plugin-transform-sticky-regex@^7.25.9": +"@babel/plugin-transform-sticky-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz#c7f02b944e986a417817b20ba2c504dfc1453d32" integrity sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-template-literals@^7.24.1", "@babel/plugin-transform-template-literals@^7.26.8": +"@babel/plugin-transform-template-literals@^7.26.8": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz#966b15d153a991172a540a69ad5e1845ced990b5" integrity sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q== dependencies: "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-typeof-symbol@^7.24.5", "@babel/plugin-transform-typeof-symbol@^7.26.7": +"@babel/plugin-transform-typeof-symbol@^7.26.7": version "7.26.7" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz#d0e33acd9223744c1e857dbd6fa17bd0a3786937" integrity sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw== dependencies: "@babel/helper-plugin-utils" "^7.26.5" -"@babel/plugin-transform-typescript@7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.5.tgz#bcba979e462120dc06a75bd34c473a04781931b8" - integrity sha512-E0VWu/hk83BIFUWnsKZ4D81KXjN5L3MobvevOHErASk9IPwKHOkTgvqzvNo1yP/ePJWqqK2SpUR5z+KQbl6NVw== - dependencies: - "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.24.5" - "@babel/helper-plugin-utils" "^7.24.5" - "@babel/plugin-syntax-typescript" "^7.24.1" - -"@babel/plugin-transform-typescript@^7.24.1", "@babel/plugin-transform-typescript@^7.25.9": +"@babel/plugin-transform-typescript@^7.25.9": version "7.26.8" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz#2e9caa870aa102f50d7125240d9dbf91334b0950" integrity sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw== @@ -1001,14 +865,14 @@ "@babel/helper-skip-transparent-expression-wrappers" "^7.25.9" "@babel/plugin-syntax-typescript" "^7.25.9" -"@babel/plugin-transform-unicode-escapes@^7.24.1", "@babel/plugin-transform-unicode-escapes@^7.25.9": +"@babel/plugin-transform-unicode-escapes@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz#a75ef3947ce15363fccaa38e2dd9bc70b2788b82" integrity sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-property-regex@^7.24.1", "@babel/plugin-transform-unicode-property-regex@^7.25.9": +"@babel/plugin-transform-unicode-property-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz#a901e96f2c1d071b0d1bb5dc0d3c880ce8f53dd3" integrity sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg== @@ -1016,7 +880,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-regex@^7.24.1", "@babel/plugin-transform-unicode-regex@^7.25.9": +"@babel/plugin-transform-unicode-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz#5eae747fe39eacf13a8bd006a4fb0b5d1fa5e9b1" integrity sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA== @@ -1024,7 +888,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-unicode-sets-regex@^7.24.1", "@babel/plugin-transform-unicode-sets-regex@^7.25.9": +"@babel/plugin-transform-unicode-sets-regex@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz#65114c17b4ffc20fa5b163c63c70c0d25621fabe" integrity sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ== @@ -1032,93 +896,6 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/preset-env@7.24.5": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.5.tgz#6a9ac90bd5a5a9dae502af60dfc58c190551bbcd" - integrity sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ== - dependencies: - "@babel/compat-data" "^7.24.4" - "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.24.5" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-firefox-class-in-computed-class-key" "^7.24.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" - "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" - "@babel/plugin-syntax-async-generators" "^7.8.4" - "@babel/plugin-syntax-class-properties" "^7.12.13" - "@babel/plugin-syntax-class-static-block" "^7.14.5" - "@babel/plugin-syntax-dynamic-import" "^7.8.3" - "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.24.1" - "@babel/plugin-syntax-import-attributes" "^7.24.1" - "@babel/plugin-syntax-import-meta" "^7.10.4" - "@babel/plugin-syntax-json-strings" "^7.8.3" - "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" - "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" - "@babel/plugin-syntax-numeric-separator" "^7.10.4" - "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" - "@babel/plugin-syntax-optional-chaining" "^7.8.3" - "@babel/plugin-syntax-private-property-in-object" "^7.14.5" - "@babel/plugin-syntax-top-level-await" "^7.14.5" - "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.24.1" - "@babel/plugin-transform-async-generator-functions" "^7.24.3" - "@babel/plugin-transform-async-to-generator" "^7.24.1" - "@babel/plugin-transform-block-scoped-functions" "^7.24.1" - "@babel/plugin-transform-block-scoping" "^7.24.5" - "@babel/plugin-transform-class-properties" "^7.24.1" - "@babel/plugin-transform-class-static-block" "^7.24.4" - "@babel/plugin-transform-classes" "^7.24.5" - "@babel/plugin-transform-computed-properties" "^7.24.1" - "@babel/plugin-transform-destructuring" "^7.24.5" - "@babel/plugin-transform-dotall-regex" "^7.24.1" - "@babel/plugin-transform-duplicate-keys" "^7.24.1" - "@babel/plugin-transform-dynamic-import" "^7.24.1" - "@babel/plugin-transform-exponentiation-operator" "^7.24.1" - "@babel/plugin-transform-export-namespace-from" "^7.24.1" - "@babel/plugin-transform-for-of" "^7.24.1" - "@babel/plugin-transform-function-name" "^7.24.1" - "@babel/plugin-transform-json-strings" "^7.24.1" - "@babel/plugin-transform-literals" "^7.24.1" - "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" - "@babel/plugin-transform-member-expression-literals" "^7.24.1" - "@babel/plugin-transform-modules-amd" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-modules-systemjs" "^7.24.1" - "@babel/plugin-transform-modules-umd" "^7.24.1" - "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.24.1" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" - "@babel/plugin-transform-numeric-separator" "^7.24.1" - "@babel/plugin-transform-object-rest-spread" "^7.24.5" - "@babel/plugin-transform-object-super" "^7.24.1" - "@babel/plugin-transform-optional-catch-binding" "^7.24.1" - "@babel/plugin-transform-optional-chaining" "^7.24.5" - "@babel/plugin-transform-parameters" "^7.24.5" - "@babel/plugin-transform-private-methods" "^7.24.1" - "@babel/plugin-transform-private-property-in-object" "^7.24.5" - "@babel/plugin-transform-property-literals" "^7.24.1" - "@babel/plugin-transform-regenerator" "^7.24.1" - "@babel/plugin-transform-reserved-words" "^7.24.1" - "@babel/plugin-transform-shorthand-properties" "^7.24.1" - "@babel/plugin-transform-spread" "^7.24.1" - "@babel/plugin-transform-sticky-regex" "^7.24.1" - "@babel/plugin-transform-template-literals" "^7.24.1" - "@babel/plugin-transform-typeof-symbol" "^7.24.5" - "@babel/plugin-transform-unicode-escapes" "^7.24.1" - "@babel/plugin-transform-unicode-property-regex" "^7.24.1" - "@babel/plugin-transform-unicode-regex" "^7.24.1" - "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" - "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.10" - babel-plugin-polyfill-corejs3 "^0.10.4" - babel-plugin-polyfill-regenerator "^0.6.1" - core-js-compat "^3.31.0" - semver "^6.3.1" - "@babel/preset-env@^7.11.0", "@babel/preset-env@^7.16.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.9.tgz#2ec64e903d0efe743699f77a10bdf7955c2123c3" @@ -1203,18 +980,6 @@ "@babel/types" "^7.4.4" esutils "^2.0.2" -"@babel/preset-react@7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" - integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-transform-react-display-name" "^7.24.1" - "@babel/plugin-transform-react-jsx" "^7.23.4" - "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.24.1" - "@babel/preset-react@^7.16.0": version "7.26.3" resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.26.3.tgz#7c5e028d623b4683c1f83a0bd4713b9100560caa" @@ -1227,17 +992,6 @@ "@babel/plugin-transform-react-jsx-development" "^7.25.9" "@babel/plugin-transform-react-pure-annotations" "^7.25.9" -"@babel/preset-typescript@7.24.1": - version "7.24.1" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" - integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== - dependencies: - "@babel/helper-plugin-utils" "^7.24.0" - "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-syntax-jsx" "^7.24.1" - "@babel/plugin-transform-modules-commonjs" "^7.24.1" - "@babel/plugin-transform-typescript" "^7.24.1" - "@babel/preset-typescript@^7.16.0": version "7.26.0" resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz#4a570f1b8d104a242d923957ffa1eaff142a106d" @@ -1256,7 +1010,7 @@ dependencies: regenerator-runtime "^0.14.0" -"@babel/template@^7.24.0", "@babel/template@^7.25.9", "@babel/template@^7.26.9": +"@babel/template@^7.25.9", "@babel/template@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.26.9.tgz#4577ad3ddf43d194528cff4e1fa6b232fa609bb2" integrity sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA== @@ -1265,7 +1019,7 @@ "@babel/parser" "^7.26.9" "@babel/types" "^7.26.9" -"@babel/traverse@^7.24.5", "@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": +"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.5", "@babel/traverse@^7.26.8", "@babel/traverse@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.26.9.tgz#4398f2394ba66d05d988b2ad13c219a2c857461a" integrity sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg== @@ -1278,7 +1032,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.21.3", "@babel/types@^7.24.5", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": +"@babel/types@^7.21.3", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== @@ -1301,11 +1055,6 @@ resolved "https://registry.yarnpkg.com/@braintree/sanitize-url/-/sanitize-url-6.0.4.tgz#923ca57e173c6b232bbbb07347b1be982f03e783" integrity sha512-s3jaWicZd0pkP0jf5ysyHUI/RE7MHos6qlToFcGWXVp+ykHOy77OUMrfbgJ9it2C5bow7OIQwYYaHjk9XlBQ2A== -"@discoveryjs/json-ext@^0.5.0": - version "0.5.7" - resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" - integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== - "@esbuild/aix-ppc64@0.19.10": version "0.19.10" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz#fb3922a0183d27446de00cf60d4f7baaadf98d84" @@ -1693,6 +1442,43 @@ resolved "https://registry.yarnpkg.com/@excalidraw/eslint-config/-/eslint-config-1.0.3.tgz#2122ef7413ae77874ae9848ce0f1c6b3f0d8bbbd" integrity sha512-GemHNF5Z6ga0BWBSX7GJaNBUchLu6RwTcAB84eX1MeckRNhNasAsPCdelDlFalz27iS4RuYEQh0bPE8SRxJgbQ== +"@excalidraw/excalidraw@0.18.0-rc.5": + version "0.18.0-rc.5" + resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0-rc.5.tgz#c55598e01808693702251322e59bf9dba931b6e0" + integrity sha512-f6Z6cWlx+FWl1nxCu5F6OdKm9ooV/FPjndjIfFhGLVyERKATXhuNwZUHWwqsEW+SIGmiPG2515NG9KIOhjGd5g== + dependencies: + "@braintree/sanitize-url" "6.0.2" + "@excalidraw/laser-pointer" "1.3.1" + "@excalidraw/mermaid-to-excalidraw" "1.1.2" + "@excalidraw/random-username" "1.1.0" + "@radix-ui/react-popover" "1.0.3" + "@radix-ui/react-tabs" "1.0.2" + browser-fs-access "0.29.1" + canvas-roundrect-polyfill "0.0.1" + clsx "1.1.1" + cross-env "7.0.3" + es6-promise-pool "2.5.0" + fractional-indexing "3.2.0" + fuzzy "0.1.3" + image-blob-reduce "3.0.1" + jotai "2.11.0" + jotai-scope "0.7.2" + lodash.debounce "4.0.8" + lodash.throttle "4.1.1" + nanoid "3.3.3" + open-color "1.9.1" + pako "2.0.3" + perfect-freehand "1.2.0" + pica "7.1.1" + png-chunk-text "1.0.0" + png-chunks-encode "1.0.0" + png-chunks-extract "1.0.0" + points-on-curve "1.0.1" + pwacompat "2.0.17" + roughjs "4.6.4" + sass "1.51.0" + tunnel-rat "0.1.2" + "@excalidraw/laser-pointer@1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@excalidraw/laser-pointer/-/laser-pointer-1.3.1.tgz#7c40836598e8e6ad91f01057883ed8b88fb9266c" @@ -2406,7 +2192,7 @@ resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== -"@polka/url@^1.0.0-next.20", "@polka/url@^1.0.0-next.24": +"@polka/url@^1.0.0-next.24": version "1.0.0-next.28" resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.28.tgz#d45e01c4a56f143ee69c54dd6b12eade9e270a73" integrity sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw== @@ -3139,7 +2925,7 @@ dependencies: "@types/ms" "*" -"@types/eslint-scope@^3.7.3", "@types/eslint-scope@^3.7.7": +"@types/eslint-scope@^3.7.7": version "3.7.7" resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.7.tgz#3108bd5f18b0cdb277c867b3dd449c9ed7079ac5" integrity sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg== @@ -3165,11 +2951,6 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== - "@types/jest@27.4.0": version "27.4.0" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-27.4.0.tgz#037ab8b872067cae842a320841693080f9cb84ed" @@ -3178,7 +2959,7 @@ jest-diff "^27.0.0" pretty-format "^27.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -3188,6 +2969,13 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/lodash.debounce@4.0.8": + version "4.0.8" + resolved "https://registry.yarnpkg.com/@types/lodash.debounce/-/lodash.debounce-4.0.8.tgz#d5fe36a35aa57773e05d960b3e3c703fd9ffb8b3" + integrity sha512-REumepIJjQFSOaBUoj81U5ZzF9YIhovzE2Lm6ejUbycmwx597k2ivG1cVfPtAj4eVuSbGoZDkJR0sRIahsE6/Q== + dependencies: + "@types/lodash" "*" + "@types/lodash.throttle@4.1.7": version "4.1.7" resolved "https://registry.yarnpkg.com/@types/lodash.throttle/-/lodash.throttle-4.1.7.tgz#4ef379eb4f778068022310ef166625f420b6ba58" @@ -3226,10 +3014,10 @@ dependencies: undici-types "~6.19.2" -"@types/pako@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/pako/-/pako-1.0.3.tgz#2e61c2b02020b5f44e2e5e946dfac74f4ec33c58" - integrity sha512-EDxOsHAD5dqjbjEUM1xwa7rpKPFb8ECBE5irONTQU7/OsO3thI5YrNEWSPNMvYmvFM0l/OLQJ6Mgw7PEdXSjhg== +"@types/pako@2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/pako/-/pako-2.0.3.tgz#b6993334f3af27c158f3fe0dfeeba987c578afb1" + integrity sha512-bq0hMV9opAcrmE0Byyo0fY3Ew4tgOevJmQ9grUhpXQhYfyLJ1Kqg3P33JT5fdbT2AjeAjR51zqqVjAL/HMkx7Q== "@types/parse-json@^4.0.0": version "4.0.2" @@ -3501,14 +3289,6 @@ loupe "^3.1.3" tinyrainbow "^2.0.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== - dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ast@1.14.1", "@webassemblyjs/ast@^1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.14.1.tgz#a9f6a07f2b03c95c8d38c4536a1fdfb521ff55b6" @@ -3517,45 +3297,21 @@ "@webassemblyjs/helper-numbers" "1.13.2" "@webassemblyjs/helper-wasm-bytecode" "1.13.2" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== - "@webassemblyjs/floating-point-hex-parser@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz#fcca1eeddb1cc4e7b6eed4fc7956d6813b21b9fb" integrity sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== - "@webassemblyjs/helper-api-error@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz#e0a16152248bc38daee76dd7e21f15c5ef3ab1e7" integrity sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== - "@webassemblyjs/helper-buffer@1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz#822a9bc603166531f7d5df84e67b5bf99b72b96b" integrity sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== - dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@xtuc/long" "4.2.2" - "@webassemblyjs/helper-numbers@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz#dbd932548e7119f4b8a7877fd5a8d20e63490b2d" @@ -3565,26 +3321,11 @@ "@webassemblyjs/helper-api-error" "1.13.2" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== - "@webassemblyjs/helper-wasm-bytecode@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz#e556108758f448aae84c850e593ce18a0eb31e0b" integrity sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/helper-wasm-section@1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz#9629dda9c4430eab54b591053d6dc6f3ba050348" @@ -3595,13 +3336,6 @@ "@webassemblyjs/helper-wasm-bytecode" "1.13.2" "@webassemblyjs/wasm-gen" "1.14.1" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== - dependencies: - "@xtuc/ieee754" "^1.2.0" - "@webassemblyjs/ieee754@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz#1c5eaace1d606ada2c7fd7045ea9356c59ee0dba" @@ -3609,13 +3343,6 @@ dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== - dependencies: - "@xtuc/long" "4.2.2" - "@webassemblyjs/leb128@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.13.2.tgz#57c5c3deb0105d02ce25fa3fd74f4ebc9fd0bbb0" @@ -3623,30 +3350,11 @@ dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - "@webassemblyjs/utf8@1.13.2": version "1.13.2" resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.13.2.tgz#917a20e93f71ad5602966c2d685ae0c6c21f60f1" integrity sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ== -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - "@webassemblyjs/wasm-edit@^1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz#ac6689f502219b59198ddec42dcd496b1004d597" @@ -3661,17 +3369,6 @@ "@webassemblyjs/wasm-parser" "1.14.1" "@webassemblyjs/wast-printer" "1.14.1" -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - "@webassemblyjs/wasm-gen@1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz#991e7f0c090cb0bb62bbac882076e3d219da9570" @@ -3683,16 +3380,6 @@ "@webassemblyjs/leb128" "1.13.2" "@webassemblyjs/utf8" "1.13.2" -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wasm-opt@1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz#e6f71ed7ccae46781c206017d3c14c50efa8106b" @@ -3703,18 +3390,6 @@ "@webassemblyjs/wasm-gen" "1.14.1" "@webassemblyjs/wasm-parser" "1.14.1" -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - "@webassemblyjs/wasm-parser@1.14.1", "@webassemblyjs/wasm-parser@^1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz#b3e13f1893605ca78b52c68e54cf6a865f90b9fb" @@ -3727,14 +3402,6 @@ "@webassemblyjs/leb128" "1.13.2" "@webassemblyjs/utf8" "1.13.2" -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@xtuc/long" "4.2.2" - "@webassemblyjs/wast-printer@1.14.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz#3bb3e9638a8ae5fdaf9610e7a06b4d9f9aa6fe07" @@ -3743,23 +3410,6 @@ "@webassemblyjs/ast" "1.14.1" "@xtuc/long" "4.2.2" -"@webpack-cli/configtest@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" - integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== - -"@webpack-cli/info@^1.5.0": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" - integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== - dependencies: - envinfo "^7.7.3" - -"@webpack-cli/serve@^1.7.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" - integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== - "@xmldom/xmldom@^0.8.3": version "0.8.10" resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99" @@ -3780,29 +3430,17 @@ abab@^2.0.6: resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291" integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA== -acorn-import-assertions@^1.7.6: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - acorn-jsx@^5.3.1: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== -acorn-walk@^8.0.0: - version "8.3.4" - resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" - integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== - dependencies: - acorn "^8.11.0" - acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== -acorn@^8.0.4, acorn@^8.11.0, acorn@^8.14.0, acorn@^8.7.1, acorn@^8.8.2: +acorn@^8.14.0, acorn@^8.8.2: version "8.14.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== @@ -3829,11 +3467,6 @@ ajv-formats@^2.1.1: dependencies: ajv "^8.0.0" -ajv-keywords@^3.5.2: - version "3.5.2" - resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" - integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== - ajv-keywords@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-5.1.0.tgz#69d4d385a4733cdbeab44964a1170a88f87f0e16" @@ -3841,7 +3474,7 @@ ajv-keywords@^5.1.0: dependencies: fast-deep-equal "^3.1.3" -ajv@^6.10.0, ajv@^6.12.4, ajv@^6.12.5: +ajv@^6.10.0, ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -3873,21 +3506,11 @@ ansi-escapes@^4.3.0: dependencies: type-fest "^0.21.3" -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - integrity sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -4125,51 +3748,6 @@ axobject-query@^4.1.0: resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-4.1.0.tgz#28768c76d0e3cff21bc62a9e2d0b6ac30042a1ee" integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - integrity sha512-Oo6+e2iX+o9eVvJ9Y5eKL5iryeRdsIkwRYheCuhYdVHsdEQysbc2z2QkqCLIYnNxkT5Ss3ggrHdXiDI7Dhrn4Q== - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - integrity sha512-WfgKFX6swFB1jS2vo+DwivRN4NB8XUdM3ij0Y1gnC21y1tdBoe6xjVnd7NSI6alv+gZXCtJqvrTeMW3fR/c0ng== - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-loader@8.2.5: - version "8.2.5" - resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" - integrity sha512-OSiFfH89LrEMiWd4pLNqGz4CwJDtbs2ZVc+iGu2HrkRfPxId9F2anQj38IxWpmRfsUY0aBZYi1EFcd3mhtRMLQ== - dependencies: - find-cache-dir "^3.3.1" - loader-utils "^2.0.0" - make-dir "^3.1.0" - schema-utils "^2.6.5" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== - dependencies: - babel-runtime "^6.22.0" - babel-plugin-macros@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1" @@ -4188,7 +3766,7 @@ babel-plugin-polyfill-corejs2@^0.4.10: "@babel/helper-define-polyfill-provider" "^0.6.3" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4, babel-plugin-polyfill-corejs3@^0.10.6: +babel-plugin-polyfill-corejs3@^0.10.6: version "0.10.6" resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz#2deda57caef50f59c525aeb4964d3b2f867710c7" integrity sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA== @@ -4211,21 +3789,6 @@ babel-plugin-polyfill-regenerator@^0.6.1: dependencies: "@babel/helper-define-polyfill-provider" "^0.6.3" -babel-plugin-syntax-class-properties@^6.8.0: - version "6.13.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz#d7eb23b79a317f8543962c505b827c7d6cac27de" - integrity sha512-chI3Rt9T1AbrQD1s+vxw3KcwC9yHtF621/MacuItITfZX344uhQoANjpoSJZleAmW2tjlolqB/f+h7jIqXa7pA== - -babel-plugin-transform-class-properties@6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz#6a79763ea61d33d36f37b611aa9def81a81b46ac" - integrity sha512-n4jtBA3OYBdvG5PRMKsMXJXHfLYw/ZOmtxCLOOwz6Ro5XlrColkStLnz1AS1L2yfPA9BKJ1ZNlmVCLjAL9DSIg== - dependencies: - babel-helper-function-name "^6.24.1" - babel-plugin-syntax-class-properties "^6.8.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-plugin-transform-react-remove-prop-types@^0.4.24: version "0.4.24" resolved "https://registry.yarnpkg.com/babel-plugin-transform-react-remove-prop-types/-/babel-plugin-transform-react-remove-prop-types-0.4.24.tgz#f2edaf9b4c6a5fbe5c1d678bfb531078c1555f3a" @@ -4254,55 +3817,6 @@ babel-preset-react-app@^10.0.1: babel-plugin-macros "^3.1.0" babel-plugin-transform-react-remove-prop-types "^0.4.24" -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -4325,11 +3839,6 @@ basic-auth@^2.0.1: dependencies: safe-buffer "5.1.2" -big.js@^5.2.2: - version "5.2.2" - resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" - integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== - binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -4376,7 +3885,7 @@ browser-fs-access@0.29.1: resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.29.1.tgz#8a9794c73cf86b9aec74201829999c597128379c" integrity sha512-LSvVX5e21LRrXqVMhqtAwj5xPgDb+fXAIH80NsnCQ9xuZPs2xWsOREi24RKgZa1XOiQRbcmVrv87+ulOKsgjxw== -browserslist@^4.14.5, browserslist@^4.20.3, browserslist@^4.24.0, browserslist@^4.24.3: +browserslist@^4.20.3, browserslist@^4.24.0, browserslist@^4.24.3: version "4.24.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -4504,17 +4013,6 @@ chai@^5.2.0: loupe "^3.1.0" pathval "^2.0.0" -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -4638,15 +4136,6 @@ cliui@^8.0.1: strip-ansi "^6.0.1" wrap-ansi "^7.0.0" -clone-deep@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" - integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== - dependencies: - is-plain-object "^2.0.4" - kind-of "^6.0.2" - shallow-clone "^3.0.0" - clsx@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" @@ -4676,7 +4165,7 @@ color-name@^1.1.4, color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colorette@^2.0.14, colorette@^2.0.16: +colorette@^2.0.16: version "2.0.20" resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== @@ -4688,7 +4177,7 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -commander@7, commander@^7.0.0, commander@^7.2.0: +commander@7: version "7.2.0" resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== @@ -4713,11 +4202,6 @@ common-tags@^1.8.0: resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" integrity sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA== -commondir@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" - integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -4743,18 +4227,13 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== -core-js-compat@^3.31.0, core-js-compat@^3.38.0, core-js-compat@^3.40.0: +core-js-compat@^3.38.0, core-js-compat@^3.40.0: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== dependencies: browserslist "^4.24.3" -core-js@^2.4.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-js@^3.4: version "3.40.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" @@ -4826,20 +4305,6 @@ crypto-random-string@^2.0.0: resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5" integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA== -css-loader@6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-6.7.1.tgz#e98106f154f6e1baf3fc3bc455cb9981c1d5fd2e" - integrity sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw== - dependencies: - icss-utils "^5.1.0" - postcss "^8.4.7" - postcss-modules-extract-imports "^3.0.0" - postcss-modules-local-by-default "^4.0.0" - postcss-modules-scope "^3.0.0" - postcss-modules-values "^4.0.0" - postcss-value-parser "^4.2.0" - semver "^7.3.5" - css-select@^4.2.1: version "4.3.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" @@ -4861,11 +4326,6 @@ css.escape@^1.5.1: resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb" integrity sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg== -cssesc@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" - integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== - cssfontparser@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/cssfontparser/-/cssfontparser-1.2.1.tgz#f4022fc8f9700c68029d542084afbaf425a3f3e3" @@ -5234,13 +4694,6 @@ debug@4.3.4: dependencies: ms "2.1.2" -debug@^2.6.8: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -5466,11 +4919,6 @@ dunder-proto@^1.0.0, dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" -duplexer@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" - integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== - eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -5503,11 +4951,6 @@ emoji-regex@^9.2.2: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== -emojis-list@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" - integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== - end-of-stream@^1.1.0, end-of-stream@^1.4.1: version "1.4.4" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" @@ -5542,7 +4985,7 @@ engine.io-parser@~5.2.1: resolved "https://registry.yarnpkg.com/engine.io-parser/-/engine.io-parser-5.2.3.tgz#00dc5b97b1f233a23c9398d0209504cf5f94d92f" integrity sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q== -enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0, enhanced-resolve@^5.17.1: +enhanced-resolve@^5.17.1: version "5.18.1" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.1.tgz#728ab082f8b7b6836de51f1637aab5d3b9568faf" integrity sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg== @@ -5568,11 +5011,6 @@ entities@^4.4.0, entities@^4.5.0: resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw== -envinfo@^7.7.3: - version "7.14.0" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae" - integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg== - error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" @@ -5669,11 +5107,6 @@ es-iterator-helpers@^1.2.1: iterator.prototype "^1.1.4" safe-array-concat "^1.1.3" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== - es-module-lexer@^1.2.1, es-module-lexer@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.6.0.tgz#da49f587fd9e68ee2404fe4e256c0c7d3a81be21" @@ -5717,11 +5150,6 @@ es6-promise-pool@2.5.0: resolved "https://registry.yarnpkg.com/es6-promise-pool/-/es6-promise-pool-2.5.0.tgz#147c612b36b47f105027f9d2bf54a598a99d9ccb" integrity sha512-VHErXfzR/6r/+yyzPKeBvO0lgjfC5cbDCQWjWwMZWSb6YU39TGIl51OUmCfWCq4ylMdJSB8zkz2vIuIeIxXApA== -esbuild-plugin-external-global@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esbuild-plugin-external-global/-/esbuild-plugin-external-global-1.0.1.tgz#e3bba0e3a561f61b395bec0984a90ed0de06c4ce" - integrity sha512-NDzYHRoShpvLqNcrgV8ZQh61sMIFAry5KLTQV83BPG5iTXCCu7h72SCfJ97bW0GqtuqDD/1aqLbKinI/rNgUsg== - esbuild-sass-plugin@2.16.0: version "2.16.0" resolved "https://registry.yarnpkg.com/esbuild-sass-plugin/-/esbuild-sass-plugin-2.16.0.tgz#2908ab5e104cfc980118c46d0b409cbab8aa32dd" @@ -5824,7 +5252,7 @@ escalade@^3.1.1, escalade@^3.2.0: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== -escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: +escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== @@ -6231,11 +5659,6 @@ fast-uri@^3.0.1: resolved "https://registry.yarnpkg.com/fast-uri/-/fast-uri-3.0.6.tgz#88f130b77cfaea2378d56bf970dea21257a68748" integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== -fastest-levenshtein@^1.0.12: - version "1.0.16" - resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" - integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== - fastq@^1.6.0: version "1.19.0" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" @@ -6274,14 +5697,6 @@ file-entry-cache@^6.0.1: dependencies: flat-cache "^3.0.4" -file-loader@6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" - integrity sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw== - dependencies: - loader-utils "^2.0.0" - schema-utils "^3.0.0" - filelist@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/filelist/-/filelist-1.0.4.tgz#f78978a1e944775ff9e62e744424f215e58352b5" @@ -6296,15 +5711,6 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" -find-cache-dir@^3.3.1: - version "3.3.2" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" - integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== - dependencies: - commondir "^1.0.1" - make-dir "^3.0.2" - pkg-dir "^4.1.0" - find-chrome-bin@0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/find-chrome-bin/-/find-chrome-bin-0.1.0.tgz#9fa3e6f86c275762c6d8be9da9af71e6fef05373" @@ -6361,11 +5767,6 @@ flat-cache@^3.0.4: keyv "^4.5.3" rimraf "^3.0.2" -flat@^5.0.2: - version "5.0.2" - resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" - integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== - flatted@^3.2.9, flatted@^3.3.1: version "3.3.3" resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.3.tgz#67c8fad95454a7c7abebf74bb78ee74a44023358" @@ -6618,11 +6019,6 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" @@ -6653,7 +6049,7 @@ gopd@^1.0.1, gopd@^1.2.0: resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -6663,13 +6059,6 @@ graphemer@^1.4.0: resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== -gzip-size@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" - integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== - dependencies: - duplexer "^0.1.2" - hachure-fill@^0.5.2: version "0.5.2" resolved "https://registry.yarnpkg.com/hachure-fill/-/hachure-fill-0.5.2.tgz#d19bc4cc8750a5962b47fb1300557a85fcf934cc" @@ -6680,13 +6069,6 @@ harfbuzzjs@0.3.6: resolved "https://registry.yarnpkg.com/harfbuzzjs/-/harfbuzzjs-0.3.6.tgz#97865c861aa7734af5bd1904570712e9d753fda9" integrity sha512-dzf7y6NS8fiAIvPAL/VKwY8wx2HCzUB0vUfOo6h1J5UilFEEf7iYqFsvgwjHwvM3whbjfOMadNvQekU3KuRnWQ== -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.2: version "1.1.0" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" @@ -6839,11 +6221,6 @@ iconv-lite@0.6, iconv-lite@0.6.3: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -icss-utils@^5.0.0, icss-utils@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" - integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== - idb-keyval@6.0.3: version "6.0.3" resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.0.3.tgz#e47246a15e55d0fff9fa204fd9ca06f90ff30c52" @@ -6896,19 +6273,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1, import-fresh@^3.3.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-local@^3.0.2: - version "3.2.0" - resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260" - integrity sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA== - dependencies: - pkg-dir "^4.2.0" - resolve-cwd "^3.0.0" - -import-meta-loader@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/import-meta-loader/-/import-meta-loader-1.1.0.tgz#927060305f2d0f88b495f2754aa33387ca6579d7" - integrity sha512-f96r2o8xT+b2KVlOY4x+1KTJmJiapZlf77j1WebR8NQgMG1dpdqijjGl4i/2jMoXch2CVqcQoTMfh5BR7bR8wA== - imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -6951,18 +6315,6 @@ internmap@^1.0.0: resolved "https://registry.yarnpkg.com/internmap/-/internmap-1.0.1.tgz#0017cc8a3b99605f0302f2b198d272e015e5df95" integrity sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw== -interpret@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" - integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: version "3.0.5" resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" @@ -7106,13 +6458,6 @@ is-obj@^1.0.1: resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" integrity sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg== -is-plain-object@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" - integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== - dependencies: - isobject "^3.0.1" - is-potential-custom-element-name@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" @@ -7209,11 +6554,6 @@ isexe@^3.1.1: resolved "https://registry.yarnpkg.com/isexe/-/isexe-3.1.1.tgz#4a407e2bd78ddfb14bea0c27c6f7072dde775f0d" integrity sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ== -isobject@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" - integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== - istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" @@ -7338,11 +6678,6 @@ jotai@2.11.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -7434,7 +6769,7 @@ json5@^1.0.2: dependencies: minimist "^1.2.0" -json5@^2.1.2, json5@^2.2.0, json5@^2.2.3: +json5@^2.2.0, json5@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== @@ -7482,21 +6817,11 @@ khroma@^2.0.0: resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.1.0.tgz#45f2ce94ce231a437cf5b63c2e886e6eb42bbbb1" integrity sha512-Ls993zuzfayK269Svk9hzpeGUKob/sIgZzyHYdjQoAdQetRKpOLj+k/QQQ/6Qi0Yz65mlROrfd+Ev+1+7dz9Kw== -kind-of@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" - integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== - kleur@^4.0.3: version "4.1.5" resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.5.tgz#95106101795f7050c6c650f350c683febddb1780" integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== -klona@^2.0.4, klona@^2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.6.tgz#85bffbf819c03b2f53270412420a4555ef882e22" - integrity sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA== - language-subtag-registry@^0.3.20: version "0.3.23" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" @@ -7581,15 +6906,6 @@ loader-runner@^4.2.0: resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== -loader-utils@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.4.tgz#8b5cb38b5c34a9a018ee1fc0e6a066d1dfcc528c" - integrity sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw== - dependencies: - big.js "^5.2.2" - emojis-list "^3.0.0" - json5 "^2.1.2" - locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -7607,7 +6923,7 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== -lodash.debounce@^4.0.8: +lodash.debounce@4.0.8, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== @@ -7632,7 +6948,7 @@ lodash.truncate@^4.4.2: resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" integrity sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw== -lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0: +lodash@^4.17.14, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -7652,7 +6968,7 @@ long@^5.0.0: resolved "https://registry.yarnpkg.com/long/-/long-5.3.1.tgz#9d4222d3213f38a5ec809674834e0f0ab21abe96" integrity sha512-ka87Jz3gcx/I7Hal94xaN2tZEOPoUOEVftkQqZx2EeQRN7LGdfLlI3FvZ+7WDplm+vK2Urx9ULrvSowtdCieng== -loose-envify@^1.0.0, loose-envify@^1.4.0: +loose-envify@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== @@ -7732,13 +7048,6 @@ magicast@^0.3.5: "@babel/types" "^7.25.4" source-map-js "^1.2.0" -make-dir@^3.0.2, make-dir@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" - integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== - dependencies: - semver "^6.0.0" - make-dir@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" @@ -8006,7 +7315,7 @@ micromark@^3.0.0: micromark-util-types "^1.0.1" uvu "^0.5.0" -micromatch@^4.0.0, micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: +micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -8041,13 +7350,6 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -mini-css-extract-plugin@2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-2.6.1.tgz#9a1251d15f2035c342d99a468ab9da7a0451b71e" - integrity sha512-wd+SD57/K6DiV7jIR34P+s3uckTRuQvx0tKPcvjFlrEylk6P4mQ2KSWk1hblj1Kxaqok7LogKOieygXqBczNlg== - dependencies: - schema-utils "^4.0.0" - minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -8103,21 +7405,11 @@ mri@^1.1.0: resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b" integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== -mrmime@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-1.0.1.tgz#5f90c825fad4bdd41dc914eff5d1a8cfdaf24f27" - integrity sha512-hzzEagAgDyoU1Q6yg5uI+AorQgdvMCur3FcKf7NhMKWsaYg+RnbTyHRa/9IlLF9rf455MOCtcqqrQQ83pPP7Uw== - mrmime@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.1.tgz#bc3e87f7987853a54c9850eeb1f1078cd44adddc" integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -8356,7 +7648,7 @@ open-color@1.9.1: resolved "https://registry.yarnpkg.com/open-color/-/open-color-1.9.1.tgz#a6e6328f60eff7aa60e3e8fcfa50f53ff3eece35" integrity sha512-vCseG/EQ6/RcvxhUcGJiHViOgrtz4x0XbZepXvKik66TMGkvbmjeJrKFyBEx6daG5rNyyd14zYXhz0hZVwQFOw== -opener@^1.5.1, opener@^1.5.2: +opener@^1.5.1: version "1.5.2" resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598" integrity sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A== @@ -8413,10 +7705,10 @@ package-json-from-dist@^1.0.0: resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== -pako@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== +pako@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pako/-/pako-2.0.3.tgz#cdf475e31b678565251406de9e759196a0ea7a43" + integrity sha512-WjR1hOeg+kki3ZIOjaf4b5WVcay1jaliKSYiEaB1XzwhMQZJxRdQRv0V31EKBYlxb4T7SK3hjfc/jxyU64BoSw== param-case@^3.0.4: version "3.0.4" @@ -8572,7 +7864,7 @@ pidtree@^0.5.0: resolved "https://registry.yarnpkg.com/pidtree/-/pidtree-0.5.0.tgz#ad5fbc1de78b8a5f99d6fbdd4f6e4eee21d1aca1" integrity sha512-9nxspIM7OpZuhBxPg73Zvyq7j1QMPMPsGKTqRc2XOaFQauDvoNz9fM1Wdkjmeo7l9GXOZiRs97sPkuayl39wjA== -pkg-dir@4.2.0, pkg-dir@^4.1.0, pkg-dir@^4.2.0: +pkg-dir@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== @@ -8631,52 +7923,7 @@ possible-typed-array-names@^1.0.0: resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz#93e3582bc0e5426586d9d07b79ee40fc841de4ae" integrity sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg== -postcss-loader@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-7.0.1.tgz#4c883cc0a1b2bfe2074377b7a74c1cd805684395" - integrity sha512-VRviFEyYlLjctSM93gAZtcJJ/iSkPZ79zWbN/1fSH+NisBByEiVLqpdVDrPLVSi8DX0oJo12kL/GppTBdKVXiQ== - dependencies: - cosmiconfig "^7.0.0" - klona "^2.0.5" - semver "^7.3.7" - -postcss-modules-extract-imports@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz#b4497cb85a9c0c4b5aabeb759bb25e8d89f15002" - integrity sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q== - -postcss-modules-local-by-default@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz#d150f43837831dae25e4085596e84f6f5d6ec368" - integrity sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw== - dependencies: - icss-utils "^5.0.0" - postcss-selector-parser "^7.0.0" - postcss-value-parser "^4.1.0" - -postcss-modules-scope@^3.0.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz#1bbccddcb398f1d7a511e0a2d1d047718af4078c" - integrity sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA== - dependencies: - postcss-selector-parser "^7.0.0" - -postcss-modules-values@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz#d7c5e7e68c3bb3c9b27cbf48ca0bb3ffb4602c9c" - integrity sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ== - dependencies: - icss-utils "^5.0.0" - -postcss-selector-parser@^7.0.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" - integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== - dependencies: - cssesc "^3.0.0" - util-deprecate "^1.0.2" - -postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: +postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== @@ -8690,7 +7937,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.32, postcss@^8.4.7, postcss@^8.5.2: +postcss@^8.4.32, postcss@^8.5.2: version "8.5.3" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -8938,13 +8185,6 @@ realistic-structured-clone@^2.0.1: typeson "^6.1.0" typeson-registry "^1.0.0-alpha.20" -rechoir@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" - integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== - dependencies: - resolve "^1.9.0" - redent@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/redent/-/redent-3.0.0.tgz#e557b7998316bb53c9f1f56fa626352c6963059f" @@ -8979,11 +8219,6 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.14.0: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -9057,24 +8292,12 @@ requires-port@^1.0.0: resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ== -resolve-cwd@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" - integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== - dependencies: - resolve-from "^5.0.0" - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== -resolve-from@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" - integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== - -resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.6, resolve@^1.9.0: +resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.4, resolve@^1.22.6: version "1.22.10" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39" integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w== @@ -9253,14 +8476,6 @@ safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sass-loader@13.0.2: - version "13.0.2" - resolved "https://registry.yarnpkg.com/sass-loader/-/sass-loader-13.0.2.tgz#e81a909048e06520e9f2ff25113a801065adb3fe" - integrity sha512-BbiqbVmbfJaWVeOOAu2o7DhYWtcNmTfvroVgFXa6k2hHheMxNAeDHLNoDy/Q5aoaVlz0LH+MbMktKwm9vN/j8Q== - dependencies: - klona "^2.0.4" - neo-async "^2.6.2" - sass@1.51.0: version "1.51.0" resolved "https://registry.yarnpkg.com/sass/-/sass-1.51.0.tgz#25ea36cf819581fe1fe8329e8c3a4eaaf70d2845" @@ -9293,25 +8508,7 @@ scheduler@^0.25.0: resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== -schema-utils@^2.6.5: - version "2.7.1" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.7.1.tgz#1ca4f32d1b24c590c203b8e7a50bf0ea4cd394d7" - integrity sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg== - dependencies: - "@types/json-schema" "^7.0.5" - ajv "^6.12.4" - ajv-keywords "^3.5.2" - -schema-utils@^3.0.0, schema-utils@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" - integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== - dependencies: - "@types/json-schema" "^7.0.8" - ajv "^6.12.5" - ajv-keywords "^3.5.2" - -schema-utils@^4.0.0, schema-utils@^4.3.0: +schema-utils@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.3.0.tgz#3b669f04f71ff2dfb5aba7ce2d5a9d79b35622c0" integrity sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g== @@ -9333,12 +8530,12 @@ semver@7.5.4: dependencies: lru-cache "^6.0.0" -semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: +semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.2.1, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.3: +semver@^7.2.1, semver@^7.3.4, semver@^7.3.7, semver@^7.5.3: version "7.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== @@ -9381,13 +8578,6 @@ set-proto@^1.0.0: es-errors "^1.3.0" es-object-atoms "^1.0.0" -shallow-clone@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" - integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== - dependencies: - kind-of "^6.0.2" - shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -9455,15 +8645,6 @@ signal-exit@^4.0.1: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== -sirv@^1.0.7: - version "1.0.19" - resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.19.tgz#1d73979b38c7fe91fcba49c85280daa9c2363b49" - integrity sha512-JuLThK3TnZG1TAKDwNIqNq6QA2afLOCcm+iE8D1Kj3GA40pSPsxQjjJl0J8X3tsR7T+CP1GavpzLwYkgVLWrZQ== - dependencies: - "@polka/url" "^1.0.0-next.20" - mrmime "^1.0.0" - totalist "^1.0.0" - sirv@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/sirv/-/sirv-2.0.4.tgz#5dd9a725c578e34e449f332703eb2a74e46a29b0" @@ -9740,7 +8921,7 @@ stringify-object@^3.3.0: dependencies: ansi-regex "^5.0.1" -strip-ansi@6.0.1, strip-ansi@^3.0.0, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9774,11 +8955,6 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -style-loader@3.3.3: - version "3.3.3" - resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-3.3.3.tgz#bba8daac19930169c0c9c96706749a597ae3acff" - integrity sha512-53BiGLXAcll9maCYtZi2RCQZKa8NQQai5C4horqKyRmHj9H7QmcUyucrH+4KW/gBQbXM2AsB0axoEcFZPlfPcw== - styled-jsx@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f" @@ -9791,11 +8967,6 @@ stylis@^4.1.3: resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.6.tgz#7c7b97191cb4f195f03ecab7d52f7902ed378320" integrity sha512-yQ3rwFWRfwNUY7H5vpU0wfdkNSnvnJinhF9830Swlaxl03zsOjCfmX0ugac+3LtK0lYSgwL/KXc8oYL3mG4YFQ== -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" @@ -9889,7 +9060,7 @@ tempy@^0.6.0: type-fest "^0.16.0" unique-string "^2.0.0" -terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.3.11: +terser-webpack-plugin@^5.3.11: version "5.3.11" resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz#93c21f44ca86634257cac176f884f942b7ba3832" integrity sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ== @@ -9972,11 +9143,6 @@ tinyspy@^3.0.2: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== - to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -9984,11 +9150,6 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" -totalist@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/totalist/-/totalist-1.1.0.tgz#a4d65a3e546517701e3e5c37a47a70ac97fe56df" - integrity sha512-gduQwd1rOdDMGxFG1gEvhV88Oirdo2p+KjoYFU7k2g+i7n6AFFbDQ5kMPUsW0pNbfQsB/cwXvT1i4Bue0s9g5g== - totalist@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" @@ -10035,16 +9196,6 @@ ts-dedent@^2.2.0: resolved "https://registry.yarnpkg.com/ts-dedent/-/ts-dedent-2.2.0.tgz#39e4bd297cd036292ae2394eb3412be63f563bb5" integrity sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ== -ts-loader@9.3.1: - version "9.3.1" - resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.3.1.tgz#fe25cca56e3e71c1087fe48dc67f4df8c59b22d4" - integrity sha512-OkyShkcZTsTwyS3Kt7a4rsT/t2qvEVQuKCTg4LJmpj9fhFR7ukGdZwV6Qq3tRUkqcXtfGpPR7+hFKHCG/0d3Lw== - dependencies: - chalk "^4.1.0" - enhanced-resolve "^5.0.0" - micromatch "^4.0.0" - semver "^7.3.4" - tsconfig-paths@^3.15.0: version "3.15.0" resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" @@ -10315,7 +9466,7 @@ use-sync-external-store@^1.2.2: resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.4.0.tgz#adbc795d8eeb47029963016cefdf89dc799fcebc" integrity sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw== -util-deprecate@^1.0.1, util-deprecate@^1.0.2: +util-deprecate@^1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -10527,7 +9678,7 @@ w3c-xmlserializer@^4.0.0: dependencies: xml-name-validator "^4.0.0" -watchpack@^2.4.0, watchpack@^2.4.1: +watchpack@^2.4.1: version "2.4.2" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== @@ -10572,83 +9723,11 @@ webidl-conversions@^7.0.0: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a" integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g== -webpack-bundle-analyzer@4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.5.0.tgz#1b0eea2947e73528754a6f9af3e91b2b6e0f79d5" - integrity sha512-GUMZlM3SKwS8Z+CKeIFx7CVoHn3dXFcUAjT/dcZQQmfSZGvitPfMob2ipjai7ovFFqPvTqkEZ/leL4O0YOdAYQ== - dependencies: - acorn "^8.0.4" - acorn-walk "^8.0.0" - chalk "^4.1.0" - commander "^7.2.0" - gzip-size "^6.0.0" - lodash "^4.17.20" - opener "^1.5.2" - sirv "^1.0.7" - ws "^7.3.1" - -webpack-cli@4.10.0: - version "4.10.0" - resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" - integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== - dependencies: - "@discoveryjs/json-ext" "^0.5.0" - "@webpack-cli/configtest" "^1.2.0" - "@webpack-cli/info" "^1.5.0" - "@webpack-cli/serve" "^1.7.0" - colorette "^2.0.14" - commander "^7.0.0" - cross-spawn "^7.0.3" - fastest-levenshtein "^1.0.12" - import-local "^3.0.2" - interpret "^2.2.0" - rechoir "^0.7.0" - webpack-merge "^5.7.3" - -webpack-merge@^5.7.3: - version "5.10.0" - resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.10.0.tgz#a3ad5d773241e9c682803abf628d4cd62b8a4177" - integrity sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA== - dependencies: - clone-deep "^4.0.1" - flat "^5.0.2" - wildcard "^2.0.0" - webpack-sources@^3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.76.0: - version "5.76.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.76.0.tgz#f9fb9fb8c4a7dbdcd0d56a98e56b8a942ee2692c" - integrity sha512-l5sOdYBDunyf72HW8dF23rFtWq/7Zgvt/9ftMof71E/yUb1YLOBmTgA2K4vQthB3kotMrSj609txVE0dnr2fjA== - dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" - chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" - eslint-scope "5.1.1" - events "^3.2.0" - glob-to-regexp "^0.4.1" - graceful-fs "^4.2.9" - json-parse-even-better-errors "^2.3.1" - loader-runner "^4.2.0" - mime-types "^2.1.27" - neo-async "^2.6.2" - schema-utils "^3.1.0" - tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" - webpack-sources "^3.2.3" - webpack@^5.88.2: version "5.98.0" resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.98.0.tgz#44ae19a8f2ba97537978246072fb89d10d1fbd17" @@ -10817,11 +9896,6 @@ why-is-node-running@^2.3.0: siginfo "^2.0.0" stackback "0.0.2" -wildcard@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.1.tgz#5ab10d02487198954836b6349f74fff961e10f67" - integrity sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ== - word-wrap@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" @@ -11031,11 +10105,6 @@ ws@8.5.0: resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== -ws@^7.3.1: - version "7.5.10" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" - integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== - ws@^8.13.0: version "8.18.1" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb" From 68578556ffd7ab3a70a10f286525ccf913b165fa Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sat, 1 Mar 2025 11:03:02 +0100 Subject: [PATCH 28/51] fix: cleanup legacy `element.rawText` (obsidian) (#9203) --- packages/excalidraw/data/restore.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 837ca27de..257a2208a 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -238,6 +238,8 @@ const restoreElementWithProperties = < const restoreElement = ( element: Exclude, ): typeof element | null => { + element = { ...element }; + // NOTE (mtolmacs): This is a temporary check to detect extremely large // element position or sizing if ( @@ -255,6 +257,10 @@ const restoreElement = ( switch (element.type) { case "text": + // temp fix: cleanup legacy obsidian-excalidraw attribute else it'll + // conflict when porting between the apps + delete (element as any).rawText; + let fontSize = element.fontSize; let fontFamily = element.fontFamily; if ("font" in element) { From 2523624f157eb725809bc14e1d395e7bdc6e840b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Sun, 2 Mar 2025 14:24:50 +0100 Subject: [PATCH 29/51] fix: React 18 element.ref was accessed error (#9208) Bump @radix-ui/react-popover to fix element.ref React 19 error Signed-off-by: Mark Tolmacs --- .../components/PropertiesPopover.tsx | 4 +- packages/excalidraw/package.json | 2 +- yarn.lock | 212 +++++++++++++++++- 3 files changed, 210 insertions(+), 8 deletions(-) diff --git a/packages/excalidraw/components/PropertiesPopover.tsx b/packages/excalidraw/components/PropertiesPopover.tsx index 1086eb8af..455af1184 100644 --- a/packages/excalidraw/components/PropertiesPopover.tsx +++ b/packages/excalidraw/components/PropertiesPopover.tsx @@ -14,8 +14,8 @@ interface PropertiesPopoverProps { onClose: () => void; onKeyDown?: React.KeyboardEventHandler; onPointerLeave?: React.PointerEventHandler; - onFocusOutside?: Popover.DismissableLayerProps["onFocusOutside"]; - onPointerDownOutside?: Popover.DismissableLayerProps["onPointerDownOutside"]; + onFocusOutside?: Popover.PopoverContentProps["onFocusOutside"]; + onPointerDownOutside?: Popover.PopoverContentProps["onPointerDownOutside"]; } export const PropertiesPopover = React.forwardRef< diff --git a/packages/excalidraw/package.json b/packages/excalidraw/package.json index 82e5c4373..a545ed7f7 100644 --- a/packages/excalidraw/package.json +++ b/packages/excalidraw/package.json @@ -63,7 +63,7 @@ "@excalidraw/laser-pointer": "1.3.1", "@excalidraw/mermaid-to-excalidraw": "1.1.2", "@excalidraw/random-username": "1.1.0", - "@radix-ui/react-popover": "1.0.3", + "@radix-ui/react-popover": "1.1.6", "@radix-ui/react-tabs": "1.0.2", "browser-fs-access": "0.29.1", "canvas-roundrect-polyfill": "0.0.1", diff --git a/yarn.lock b/yarn.lock index 043db6da0..3fb9b1910 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1909,6 +1909,13 @@ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== +"@floating-ui/core@^1.6.0": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" + integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== + dependencies: + "@floating-ui/utils" "^0.2.9" + "@floating-ui/dom@^0.5.3": version "0.5.4" resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" @@ -1916,6 +1923,14 @@ dependencies: "@floating-ui/core" "^0.7.3" +"@floating-ui/dom@^1.0.0": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" + integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== + dependencies: + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.9" + "@floating-ui/react-dom@0.7.2": version "0.7.2" resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" @@ -1924,6 +1939,18 @@ "@floating-ui/dom" "^0.5.3" use-isomorphic-layout-effect "^1.1.1" +"@floating-ui/react-dom@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== + "@grpc/grpc-js@~1.9.0": version "1.9.15" resolved "https://registry.yarnpkg.com/@grpc/grpc-js/-/grpc-js-1.9.15.tgz#433d7ac19b1754af690ea650ab72190bd700739b" @@ -2257,6 +2284,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/primitive@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" + integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== + "@radix-ui/react-arrow@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" @@ -2265,6 +2297,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.1" +"@radix-ui/react-arrow@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" + integrity sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-collection@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.1.tgz#259506f97c6703b36291826768d3c1337edd1de5" @@ -2283,6 +2322,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" + integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== + "@radix-ui/react-context@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" @@ -2290,6 +2334,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" + integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== + "@radix-ui/react-direction@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" @@ -2309,6 +2358,17 @@ "@radix-ui/react-use-callback-ref" "1.0.0" "@radix-ui/react-use-escape-keydown" "1.0.2" +"@radix-ui/react-dismissable-layer@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" + integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + "@radix-ui/react-focus-guards@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" @@ -2316,6 +2376,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== + "@radix-ui/react-focus-scope@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" @@ -2326,6 +2391,15 @@ "@radix-ui/react-primitive" "1.0.1" "@radix-ui/react-use-callback-ref" "1.0.0" +"@radix-ui/react-focus-scope@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" + integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-id@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.0.0.tgz#8d43224910741870a45a8c9d092f25887bb6d11e" @@ -2334,6 +2408,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-popover@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe" @@ -2356,6 +2437,27 @@ aria-hidden "^1.1.1" react-remove-scroll "2.5.5" +"@radix-ui/react-popover@1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.6.tgz#699634dbc7899429f657bb590d71fb3ca0904087" + integrity sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + "@radix-ui/react-popper@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60" @@ -2373,6 +2475,22 @@ "@radix-ui/react-use-size" "1.0.0" "@radix-ui/rect" "1.0.0" +"@radix-ui/react-popper@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" + integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + "@radix-ui/react-portal@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" @@ -2381,6 +2499,14 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.1" +"@radix-ui/react-portal@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" + integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-presence@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.0.tgz#814fe46df11f9a468808a6010e3f3ca7e0b2e84a" @@ -2390,6 +2516,14 @@ "@radix-ui/react-compose-refs" "1.0.0" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-presence@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" + integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" @@ -2398,6 +2532,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.1" +"@radix-ui/react-primitive@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef" + integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w== + dependencies: + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-roving-focus@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de" @@ -2422,6 +2563,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.0" +"@radix-ui/react-slot@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" + integrity sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-tabs@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz#8f5ec73ca41b151a413bdd6e00553408ff34ce07" @@ -2444,6 +2592,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" @@ -2452,6 +2605,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.0" +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" @@ -2460,6 +2620,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.0" +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.0.0.tgz#2fc19e97223a81de64cd3ba1dc42ceffd82374dc" @@ -2467,6 +2634,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== + "@radix-ui/react-use-rect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" @@ -2475,6 +2647,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/rect" "1.0.0" +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== + dependencies: + "@radix-ui/rect" "1.1.0" + "@radix-ui/react-use-size@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771" @@ -2483,6 +2662,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/rect@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" @@ -2490,6 +2676,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== + "@rollup/plugin-babel@^5.2.0": version "5.3.1" resolved "https://registry.yarnpkg.com/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz#04bc0608f4aa4b2e4b1aebf284344d0f68fda283" @@ -3560,7 +3751,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1: +aria-hidden@^1.1.1, aria-hidden@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== @@ -8122,7 +8313,7 @@ react-refresh@^0.14.0: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== -react-remove-scroll-bar@^2.3.3: +react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -8141,7 +8332,18 @@ react-remove-scroll@2.5.5: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" -react-style-singleton@^2.2.1, react-style-singleton@^2.2.2: +react-remove-scroll@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" + integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" + +react-style-singleton@^2.2.1, react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== @@ -9441,7 +9643,7 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" -use-callback-ref@^1.3.0: +use-callback-ref@^1.3.0, use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== @@ -9453,7 +9655,7 @@ use-isomorphic-layout-effect@^1.1.1: resolved "https://registry.yarnpkg.com/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.0.tgz#afb292eb284c39219e8cb8d3d62d71999361a21d" integrity sha512-q6ayo8DWoPZT0VdG4u3D3uxcgONP3Mevx2i2b0434cwWBoL+aelL1DzkXI6w3PhTZzUeR2kaVlZn70iCiseP6w== -use-sidecar@^1.1.2: +use-sidecar@^1.1.2, use-sidecar@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== From d1112bbf4f39617e2e20c77e68eb6cec643b11e9 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sun, 2 Mar 2025 18:24:20 +0100 Subject: [PATCH 30/51] fix: docked sidebar width (#9213) --- packages/excalidraw/components/App.tsx | 1 + packages/excalidraw/components/LayerUI.tsx | 2 +- packages/excalidraw/components/Sidebar/Sidebar.tsx | 3 --- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 15dabb5fa..8eb2a9e2c 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -1550,6 +1550,7 @@ class App extends React.Component { ["--ui-pointerEvents" as any]: shouldBlockPointerEvents ? POINTER_EVENTS.disabled : POINTER_EVENTS.enabled, + ["--right-sidebar-width" as any]: "302px", }} ref={this.excalidrawContainerRef} onDrop={this.handleAppOnDrop} diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index ecd032bcd..11914d09a 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -526,7 +526,7 @@ const LayerUI = ({ appState.openSidebar && isSidebarDocked && device.editor.canFitSidebar - ? { width: `calc(100% - var(--right-sidebar-width)px)` } + ? { width: `calc(100% - var(--right-sidebar-width))` } : {} } > diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index ad6c9fe41..7c747d2f4 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -136,9 +136,6 @@ export const SidebarInner = forwardRef( From d21c6a1bc698ebbf31695cbe1233fe8c431c9896 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:00:13 +0100 Subject: [PATCH 31/51] chore: bump vite@6.x (#9210) --- package.json | 7 +- yarn.lock | 698 ++++++++++++++++++++++++++------------------------- 2 files changed, 357 insertions(+), 348 deletions(-) diff --git a/package.json b/package.json index 94eef472c..48d971835 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "examples/*" ], "devDependencies": { + "@babel/preset-env": "7.26.9", "@excalidraw/eslint-config": "1.0.3", "@excalidraw/prettier-config": "1.0.2", "@types/chai": "4.3.0", @@ -18,7 +19,7 @@ "@types/react": "19.0.10", "@types/react-dom": "19.0.4", "@types/socket.io-client": "3.0.0", - "@vitejs/plugin-react": "3.1.0", + "@vitejs/plugin-react": "4.3.4", "@vitest/coverage-v8": "3.0.7", "@vitest/ui": "2.0.5", "chai": "4.3.6", @@ -34,11 +35,11 @@ "prettier": "2.6.2", "rewire": "6.0.0", "typescript": "4.9.4", - "vite": "5.0.12", + "vite": "6.2.0", "vite-plugin-checker": "0.7.2", "vite-plugin-ejs": "1.7.0", "vite-plugin-pwa": "0.21.1", - "vite-plugin-svgr": "4.2.0", + "vite-plugin-svgr": "4.3.0", "vitest": "3.0.6", "vitest-canvas-mock": "0.3.3" }, diff --git a/yarn.lock b/yarn.lock index 3fb9b1910..3a8bb3e2e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45,7 +45,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== -"@babel/core@^7.16.0", "@babel/core@^7.20.12", "@babel/core@^7.21.3", "@babel/core@^7.24.4": +"@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.24.4", "@babel/core@^7.26.0": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== @@ -242,7 +242,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.25.4", "@babel/parser@^7.26.9": +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.25.4", "@babel/parser@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== @@ -750,14 +750,14 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.25.9" -"@babel/plugin-transform-react-jsx-self@^7.18.6": +"@babel/plugin-transform-react-jsx-self@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx-source@^7.19.6": +"@babel/plugin-transform-react-jsx-source@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== @@ -896,7 +896,7 @@ "@babel/helper-create-regexp-features-plugin" "^7.25.9" "@babel/helper-plugin-utils" "^7.25.9" -"@babel/preset-env@^7.11.0", "@babel/preset-env@^7.16.4": +"@babel/preset-env@7.26.9", "@babel/preset-env@^7.11.0", "@babel/preset-env@^7.16.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.26.9.tgz#2ec64e903d0efe743699f77a10bdf7955c2123c3" integrity sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ== @@ -1032,7 +1032,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.21.3", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== @@ -1065,10 +1065,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f" integrity sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA== -"@esbuild/aix-ppc64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" - integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== +"@esbuild/aix-ppc64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz#499600c5e1757a524990d5d92601f0ac3ce87f64" + integrity sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ== "@esbuild/android-arm64@0.19.10": version "0.19.10" @@ -1080,10 +1080,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz#7ad65a36cfdb7e0d429c353e00f680d737c2aed4" integrity sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA== -"@esbuild/android-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" - integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== +"@esbuild/android-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz#b9b8231561a1dfb94eb31f4ee056b92a985c324f" + integrity sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g== "@esbuild/android-arm@0.19.10": version "0.19.10" @@ -1095,10 +1095,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.12.tgz#b0c26536f37776162ca8bde25e42040c203f2824" integrity sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w== -"@esbuild/android-arm@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" - integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== +"@esbuild/android-arm@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.0.tgz#ca6e7888942505f13e88ac9f5f7d2a72f9facd2b" + integrity sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g== "@esbuild/android-x64@0.19.10": version "0.19.10" @@ -1110,10 +1110,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.12.tgz#cb13e2211282012194d89bf3bfe7721273473b3d" integrity sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew== -"@esbuild/android-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" - integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== +"@esbuild/android-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.0.tgz#e765ea753bac442dfc9cb53652ce8bd39d33e163" + integrity sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg== "@esbuild/darwin-arm64@0.19.10": version "0.19.10" @@ -1125,10 +1125,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz#cbee41e988020d4b516e9d9e44dd29200996275e" integrity sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g== -"@esbuild/darwin-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" - integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== +"@esbuild/darwin-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz#fa394164b0d89d4fdc3a8a21989af70ef579fa2c" + integrity sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw== "@esbuild/darwin-x64@0.19.10": version "0.19.10" @@ -1140,10 +1140,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz#e37d9633246d52aecf491ee916ece709f9d5f4cd" integrity sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A== -"@esbuild/darwin-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" - integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== +"@esbuild/darwin-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz#91979d98d30ba6e7d69b22c617cc82bdad60e47a" + integrity sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg== "@esbuild/freebsd-arm64@0.19.10": version "0.19.10" @@ -1155,10 +1155,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz#1ee4d8b682ed363b08af74d1ea2b2b4dbba76487" integrity sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA== -"@esbuild/freebsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" - integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== +"@esbuild/freebsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz#b97e97073310736b430a07b099d837084b85e9ce" + integrity sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w== "@esbuild/freebsd-x64@0.19.10": version "0.19.10" @@ -1170,10 +1170,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz#37a693553d42ff77cd7126764b535fb6cc28a11c" integrity sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg== -"@esbuild/freebsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" - integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== +"@esbuild/freebsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz#f3b694d0da61d9910ec7deff794d444cfbf3b6e7" + integrity sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A== "@esbuild/linux-arm64@0.19.10": version "0.19.10" @@ -1185,10 +1185,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz#be9b145985ec6c57470e0e051d887b09dddb2d4b" integrity sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA== -"@esbuild/linux-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" - integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== +"@esbuild/linux-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz#f921f699f162f332036d5657cad9036f7a993f73" + integrity sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg== "@esbuild/linux-arm@0.19.10": version "0.19.10" @@ -1200,10 +1200,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz#207ecd982a8db95f7b5279207d0ff2331acf5eef" integrity sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w== -"@esbuild/linux-arm@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" - integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== +"@esbuild/linux-arm@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz#cc49305b3c6da317c900688995a4050e6cc91ca3" + integrity sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg== "@esbuild/linux-ia32@0.19.10": version "0.19.10" @@ -1215,10 +1215,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz#d0d86b5ca1562523dc284a6723293a52d5860601" integrity sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA== -"@esbuild/linux-ia32@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" - integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== +"@esbuild/linux-ia32@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz#3e0736fcfab16cff042dec806247e2c76e109e19" + integrity sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg== "@esbuild/linux-loong64@0.19.10": version "0.19.10" @@ -1230,10 +1230,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz#9a37f87fec4b8408e682b528391fa22afd952299" integrity sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA== -"@esbuild/linux-loong64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" - integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== +"@esbuild/linux-loong64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz#ea2bf730883cddb9dfb85124232b5a875b8020c7" + integrity sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw== "@esbuild/linux-mips64el@0.19.10": version "0.19.10" @@ -1245,10 +1245,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz#4ddebd4e6eeba20b509d8e74c8e30d8ace0b89ec" integrity sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w== -"@esbuild/linux-mips64el@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" - integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== +"@esbuild/linux-mips64el@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz#4cababb14eede09248980a2d2d8b966464294ff1" + integrity sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ== "@esbuild/linux-ppc64@0.19.10": version "0.19.10" @@ -1260,10 +1260,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz#adb67dadb73656849f63cd522f5ecb351dd8dee8" integrity sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg== -"@esbuild/linux-ppc64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" - integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== +"@esbuild/linux-ppc64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz#8860a4609914c065373a77242e985179658e1951" + integrity sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw== "@esbuild/linux-riscv64@0.19.10": version "0.19.10" @@ -1275,10 +1275,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz#11bc0698bf0a2abf8727f1c7ace2112612c15adf" integrity sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg== -"@esbuild/linux-riscv64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" - integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== +"@esbuild/linux-riscv64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz#baf26e20bb2d38cfb86ee282dff840c04f4ed987" + integrity sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA== "@esbuild/linux-s390x@0.19.10": version "0.19.10" @@ -1290,10 +1290,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz#e86fb8ffba7c5c92ba91fc3b27ed5a70196c3cc8" integrity sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg== -"@esbuild/linux-s390x@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" - integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== +"@esbuild/linux-s390x@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz#8323afc0d6cb1b6dc6e9fd21efd9e1542c3640a4" + integrity sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA== "@esbuild/linux-x64@0.19.10": version "0.19.10" @@ -1305,15 +1305,15 @@ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz#5f37cfdc705aea687dfe5dfbec086a05acfe9c78" integrity sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg== -"@esbuild/linux-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" - integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== +"@esbuild/linux-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz#08fcf60cb400ed2382e9f8e0f5590bac8810469a" + integrity sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw== -"@esbuild/netbsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" - integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== +"@esbuild/netbsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz#935c6c74e20f7224918fbe2e6c6fe865b6c6ea5b" + integrity sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw== "@esbuild/netbsd-x64@0.19.10": version "0.19.10" @@ -1325,15 +1325,15 @@ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz#29da566a75324e0d0dd7e47519ba2f7ef168657b" integrity sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA== -"@esbuild/netbsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" - integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw== +"@esbuild/netbsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz#414677cef66d16c5a4d210751eb2881bb9c1b62b" + integrity sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA== -"@esbuild/openbsd-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" - integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== +"@esbuild/openbsd-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz#8fd55a4d08d25cdc572844f13c88d678c84d13f7" + integrity sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw== "@esbuild/openbsd-x64@0.19.10": version "0.19.10" @@ -1345,10 +1345,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz#306c0acbdb5a99c95be98bdd1d47c916e7dc3ff0" integrity sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw== -"@esbuild/openbsd-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" - integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== +"@esbuild/openbsd-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz#0c48ddb1494bbc2d6bcbaa1429a7f465fa1dedde" + integrity sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg== "@esbuild/sunos-x64@0.19.10": version "0.19.10" @@ -1360,10 +1360,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz#0933eaab9af8b9b2c930236f62aae3fc593faf30" integrity sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA== -"@esbuild/sunos-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" - integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== +"@esbuild/sunos-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz#86ff9075d77962b60dd26203d7352f92684c8c92" + integrity sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg== "@esbuild/win32-arm64@0.19.10": version "0.19.10" @@ -1375,10 +1375,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz#773bdbaa1971b36db2f6560088639ccd1e6773ae" integrity sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A== -"@esbuild/win32-arm64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" - integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== +"@esbuild/win32-arm64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz#849c62327c3229467f5b5cd681bf50588442e96c" + integrity sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw== "@esbuild/win32-ia32@0.19.10": version "0.19.10" @@ -1390,10 +1390,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz#000516cad06354cc84a73f0943a4aa690ef6fd67" integrity sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ== -"@esbuild/win32-ia32@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" - integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== +"@esbuild/win32-ia32@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz#f62eb480cd7cca088cb65bb46a6db25b725dc079" + integrity sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA== "@esbuild/win32-x64@0.19.10": version "0.19.10" @@ -1405,10 +1405,10 @@ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz#c57c8afbb4054a3ab8317591a0b7320360b444ae" integrity sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA== -"@esbuild/win32-x64@0.24.2": - version "0.24.2" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" - integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== +"@esbuild/win32-x64@0.25.0": + version "0.25.0" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz#c8e119a30a7c8d60b9d2e22d2073722dde3b710b" + integrity sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ== "@eslint-community/eslint-utils@^4.2.0": version "4.4.1" @@ -2034,7 +2034,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== @@ -2734,7 +2734,7 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.5": +"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.1.3": version "5.1.4" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== @@ -2743,100 +2743,100 @@ estree-walker "^2.0.2" picomatch "^4.0.2" -"@rollup/rollup-android-arm-eabi@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb" - integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw== +"@rollup/rollup-android-arm-eabi@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz#661a45a4709c70e59e596ec78daa9cb8b8d27604" + integrity sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA== -"@rollup/rollup-android-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343" - integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q== +"@rollup/rollup-android-arm64@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz#128fe8dd510d880cf98b4cb6c7add326815a0c4b" + integrity sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg== -"@rollup/rollup-darwin-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f" - integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q== +"@rollup/rollup-darwin-arm64@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz#363467bc49fd0b1e17075798ac8e9ad1e1e29535" + integrity sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ== -"@rollup/rollup-darwin-x64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82" - integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw== +"@rollup/rollup-darwin-x64@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz#c2fe3d85fffe47f0ed0f076b3563ada22c8af19c" + integrity sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q== -"@rollup/rollup-freebsd-arm64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b" - integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA== +"@rollup/rollup-freebsd-arm64@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz#d95bd8f6eaaf829781144fc8bd2d5d71d9f6a9f5" + integrity sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw== -"@rollup/rollup-freebsd-x64@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c" - integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q== +"@rollup/rollup-freebsd-x64@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz#c3576c6011656e4966ded29f051edec636b44564" + integrity sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g== -"@rollup/rollup-linux-arm-gnueabihf@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f" - integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g== +"@rollup/rollup-linux-arm-gnueabihf@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz#48c87d0dee4f8dc9591a416717f91b4a89d77e3d" + integrity sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg== -"@rollup/rollup-linux-arm-musleabihf@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78" - integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA== +"@rollup/rollup-linux-arm-musleabihf@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz#f4c4e7c03a7767f2e5aa9d0c5cfbf5c0f59f2d41" + integrity sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA== -"@rollup/rollup-linux-arm64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0" - integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A== +"@rollup/rollup-linux-arm64-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz#1015c9d07a99005025d13b8622b7600029d0b52f" + integrity sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw== -"@rollup/rollup-linux-arm64-musl@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3" - integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q== +"@rollup/rollup-linux-arm64-musl@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz#8f895eb5577748fc75af21beae32439626e0a14c" + integrity sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A== -"@rollup/rollup-linux-loongarch64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e" - integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ== +"@rollup/rollup-linux-loongarch64-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz#c9cd5dbbdc6b3ca4dbeeb0337498cf31949004a0" + integrity sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg== -"@rollup/rollup-linux-powerpc64le-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1" - integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw== +"@rollup/rollup-linux-powerpc64le-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz#7ebb5b4441faa17843a210f7d0583a20c93b40e4" + integrity sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA== -"@rollup/rollup-linux-riscv64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d" - integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw== +"@rollup/rollup-linux-riscv64-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz#10f5d7349fbd2fe78f9e36ecc90aab3154435c8d" + integrity sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg== -"@rollup/rollup-linux-s390x-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde" - integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA== +"@rollup/rollup-linux-s390x-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz#196347d2fa20593ab09d0b7e2589fb69bdf742c6" + integrity sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ== -"@rollup/rollup-linux-x64-gnu@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce" - integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA== +"@rollup/rollup-linux-x64-gnu@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz#7193cbd8d128212b8acda37e01b39d9e96259ef8" + integrity sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A== -"@rollup/rollup-linux-x64-musl@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678" - integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ== +"@rollup/rollup-linux-x64-musl@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz#29a6867278ca0420b891574cfab98ecad70c59d1" + integrity sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA== -"@rollup/rollup-win32-arm64-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd" - integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ== +"@rollup/rollup-win32-arm64-msvc@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz#89427dcac0c8e3a6d32b13a03a296a275d0de9a9" + integrity sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q== -"@rollup/rollup-win32-ia32-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62" - integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w== +"@rollup/rollup-win32-ia32-msvc@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz#ecb9711ba2b6d2bf6ee51265abe057ab90913deb" + integrity sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w== -"@rollup/rollup-win32-x64-msvc@4.34.8": - version "4.34.8" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928" - integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g== +"@rollup/rollup-win32-x64-msvc@4.34.9": + version "4.34.9" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz#1973871850856ae72bc678aeb066ab952330e923" + integrity sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw== "@rtsao/scc@^1.1.0": version "1.1.0" @@ -3087,6 +3087,39 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.6.8" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" + integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.20.6" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" + integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== + dependencies: + "@babel/types" "^7.20.7" + "@types/chai@4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" @@ -3175,9 +3208,9 @@ "@types/lodash" "*" "@types/lodash@*": - version "4.17.15" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.15.tgz#12d4af0ed17cc7600ce1f9980cec48fc17ad1e89" - integrity sha512-w/P33JFeySuhN6JLkysYUK2gEmy9kHHFN7E8ro0tkfmlDOgxBDzWEZ/J8cWA+fHqFevpswDTFZnDx+R9lbL6xw== + version "4.17.16" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.16.tgz#94ae78fab4a38d73086e962d0b65c30d816bfb0a" + integrity sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g== "@types/mdast@^3.0.0": version "3.0.15" @@ -3192,16 +3225,16 @@ integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== "@types/node@*", "@types/node@>=12.12.47", "@types/node@>=13.7.0": - version "22.13.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.5.tgz#23add1d71acddab2c6a4d31db89c0f98d330b511" - integrity sha512-+lTU0PxZXn0Dr1NBtC7Y8cR21AJr87dLLU953CWA6pMxxv/UDc7jYAY90upcrie1nRcD6XNG5HOYEDtgW5TxAg== + version "22.13.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.13.8.tgz#57e2450295b33a6518d6fd4f65f47236d3e41d8d" + integrity sha512-G3EfaZS+iOGYWLLRCEAXdWK9my08oHNZ+FHluRiggIYJPOXzhOiDgpVCUHaUvyIC5/fj7C/p637jdzC666AOKQ== dependencies: undici-types "~6.20.0" "@types/node@^20": - version "20.17.19" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.19.tgz#0f2869555719bef266ca6e1827fcdca903c1a697" - integrity sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A== + version "20.17.22" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.17.22.tgz#18e463b500af6e6d407d2a0084dfc244ef3c8d06" + integrity sha512-9RV2zST+0s3EhfrMZIhrz2bhuhBwxgkbHEwP2gtGWPjBzVQjifMzJ9exw7aDZhR1wbpj8zBrfp3bo8oJcGiUUw== dependencies: undici-types "~6.19.2" @@ -3362,16 +3395,16 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@vitejs/plugin-react@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz#d1091f535eab8b83d6e74034d01e27d73c773240" - integrity sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g== +"@vitejs/plugin-react@4.3.4": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz#c64be10b54c4640135a5b28a2432330e88ad7c20" + integrity sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug== dependencies: - "@babel/core" "^7.20.12" - "@babel/plugin-transform-react-jsx-self" "^7.18.6" - "@babel/plugin-transform-react-jsx-source" "^7.19.6" - magic-string "^0.27.0" - react-refresh "^0.14.0" + "@babel/core" "^7.26.0" + "@babel/plugin-transform-react-jsx-self" "^7.25.9" + "@babel/plugin-transform-react-jsx-source" "^7.25.9" + "@types/babel__core" "^7.20.5" + react-refresh "^0.14.2" "@vitest/coverage-v8@3.0.7": version "3.0.7" @@ -3417,13 +3450,20 @@ dependencies: tinyrainbow "^1.2.0" -"@vitest/pretty-format@3.0.6", "@vitest/pretty-format@^3.0.6": +"@vitest/pretty-format@3.0.6": version "3.0.6" resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.0.6.tgz#a828569818b666a6e955c9af8129e6b0d2968ee6" integrity sha512-Zyctv3dbNL+67qtHfRnUE/k8qxduOamRfAL1BurEIQSyOEFffoMvx2pnDSSbKAAVxY0Ej2J/GH2dQKI0W2JyVg== dependencies: tinyrainbow "^2.0.0" +"@vitest/pretty-format@^3.0.6": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-3.0.7.tgz#1780516ebb4e40dd89e60b9fc7ffcbd9cba0fc22" + integrity sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg== + dependencies: + tinyrainbow "^2.0.0" + "@vitest/runner@3.0.6": version "3.0.6" resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-3.0.6.tgz#a07b54674b1a495424f2ea959a28a6096c17c33b" @@ -4076,7 +4116,7 @@ browser-fs-access@0.29.1: resolved "https://registry.yarnpkg.com/browser-fs-access/-/browser-fs-access-0.29.1.tgz#8a9794c73cf86b9aec74201829999c597128379c" integrity sha512-LSvVX5e21LRrXqVMhqtAwj5xPgDb+fXAIH80NsnCQ9xuZPs2xWsOREi24RKgZa1XOiQRbcmVrv87+ulOKsgjxw== -browserslist@^4.20.3, browserslist@^4.24.0, browserslist@^4.24.3: +browserslist@^4.20.3, browserslist@^4.24.0, browserslist@^4.24.4: version "4.24.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== @@ -4171,9 +4211,9 @@ camelcase@^6.2.0: integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== caniuse-lite@^1.0.30001335, caniuse-lite@^1.0.30001579, caniuse-lite@^1.0.30001688: - version "1.0.30001700" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6" - integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ== + version "1.0.30001701" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001701.tgz#ad9c90301f7153cf6b3314d16cc30757285bf9e7" + integrity sha512-faRs/AW3jA9nTwmJBSO1PQ6L/EOgsB5HMQQq4iCu5zhPgVVgO/pZRHlmatwijZKetFw8/Pr4q6dEN8sJuq8qTw== canvas-roundrect-polyfill@0.0.1: version "0.0.1" @@ -4419,16 +4459,16 @@ convert-source-map@^2.0.0: integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== core-js-compat@^3.38.0, core-js-compat@^3.40.0: - version "3.40.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.40.0.tgz#7485912a5a4a4315c2fdb2cbdc623e6881c88b38" - integrity sha512-0XEDpr5y5mijvw8Lbc6E5AkjrHfp7eEoPlu36SWeAbcL8fn1G1ANe8DBlo2XoNN89oVpxWwOjYIPVzR4ZvsKCQ== + version "3.41.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.41.0.tgz#4cdfce95f39a8f27759b667cf693d96e5dda3d17" + integrity sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A== dependencies: - browserslist "^4.24.3" + browserslist "^4.24.4" core-js@^3.4: - version "3.40.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.40.0.tgz#2773f6b06877d8eda102fc42f828176437062476" - integrity sha512-7vsMc/Lty6AGnn7uFpYT56QesI5D2Y/UkgKounk87OP9Z2H9Z8kj6jzcSGAxFmUtDOS0ntK6lbQz+Nsa0Jj6mQ== + version "3.41.0" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.41.0.tgz#57714dafb8c751a6095d028a7428f1fb5834a776" + integrity sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA== corser@^2.0.1: version "2.0.1" @@ -4482,7 +4522,7 @@ cross-fetch@3.1.5: dependencies: node-fetch "2.6.7" -cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3: +cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -4542,9 +4582,9 @@ cytoscape-cose-bilkent@^4.1.0: cose-base "^1.0.0" cytoscape@^3.28.1: - version "3.31.0" - resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.0.tgz#cffbbb8ca51db01cbf360e0cf59088db6d429837" - integrity sha512-zDGn1K/tfZwEnoGOcHc0H4XazqAAXAuDpcYw9mUnUjATjqljyCNGJv8uEvbvxGaGHaVshxMecyl6oc6uKzRfbw== + version "3.31.1" + resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.31.1.tgz#29b12cac715fbb2aacc50cdf5cf1467aadde9c00" + integrity sha512-Hx5Mtb1+hnmAKaZZ/7zL1Y5HTFYOjdDswZy/jD+1WINRU8KVi1B7+vlHdsTwY+VCFucTreoyu1RDzQJ9u0d2Hw== "d3-array@1 - 2": version "2.12.1" @@ -5123,9 +5163,9 @@ ejs@^3.1.6, ejs@^3.1.9: jake "^10.8.5" electron-to-chromium@^1.5.73: - version "1.5.103" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.103.tgz#3d02025bc16e96e5edb3ed3ffa2538a11ae682dc" - integrity sha512-P6+XzIkfndgsrjROJWfSvVEgNHtPgbhVyTkwLjUM2HU/h7pZRORgaTlHqfAikqxKmdJMLW8fftrdGWbd/Ds0FA== + version "1.5.109" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.109.tgz#905a573d2b4cbb31412a2de6267fb22cf45e097e" + integrity sha512-AidaH9JETVRr9DIPGfp1kAarm/W6hRJTPuCnkF+2MqhF4KaAgRIcBc8nvjk+YMXZhwfISof/7WG29eS4iGxQLQ== elkjs@^0.9.0: version "0.9.3" @@ -5407,36 +5447,36 @@ esbuild@^0.19.3: "@esbuild/win32-ia32" "0.19.12" "@esbuild/win32-x64" "0.19.12" -esbuild@^0.24.2: - version "0.24.2" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d" - integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== +esbuild@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.0.tgz#0de1787a77206c5a79eeb634a623d39b5006ce92" + integrity sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw== optionalDependencies: - "@esbuild/aix-ppc64" "0.24.2" - "@esbuild/android-arm" "0.24.2" - "@esbuild/android-arm64" "0.24.2" - "@esbuild/android-x64" "0.24.2" - "@esbuild/darwin-arm64" "0.24.2" - "@esbuild/darwin-x64" "0.24.2" - "@esbuild/freebsd-arm64" "0.24.2" - "@esbuild/freebsd-x64" "0.24.2" - "@esbuild/linux-arm" "0.24.2" - "@esbuild/linux-arm64" "0.24.2" - "@esbuild/linux-ia32" "0.24.2" - "@esbuild/linux-loong64" "0.24.2" - "@esbuild/linux-mips64el" "0.24.2" - "@esbuild/linux-ppc64" "0.24.2" - "@esbuild/linux-riscv64" "0.24.2" - "@esbuild/linux-s390x" "0.24.2" - "@esbuild/linux-x64" "0.24.2" - "@esbuild/netbsd-arm64" "0.24.2" - "@esbuild/netbsd-x64" "0.24.2" - "@esbuild/openbsd-arm64" "0.24.2" - "@esbuild/openbsd-x64" "0.24.2" - "@esbuild/sunos-x64" "0.24.2" - "@esbuild/win32-arm64" "0.24.2" - "@esbuild/win32-ia32" "0.24.2" - "@esbuild/win32-x64" "0.24.2" + "@esbuild/aix-ppc64" "0.25.0" + "@esbuild/android-arm" "0.25.0" + "@esbuild/android-arm64" "0.25.0" + "@esbuild/android-x64" "0.25.0" + "@esbuild/darwin-arm64" "0.25.0" + "@esbuild/darwin-x64" "0.25.0" + "@esbuild/freebsd-arm64" "0.25.0" + "@esbuild/freebsd-x64" "0.25.0" + "@esbuild/linux-arm" "0.25.0" + "@esbuild/linux-arm64" "0.25.0" + "@esbuild/linux-ia32" "0.25.0" + "@esbuild/linux-loong64" "0.25.0" + "@esbuild/linux-mips64el" "0.25.0" + "@esbuild/linux-ppc64" "0.25.0" + "@esbuild/linux-riscv64" "0.25.0" + "@esbuild/linux-s390x" "0.25.0" + "@esbuild/linux-x64" "0.25.0" + "@esbuild/netbsd-arm64" "0.25.0" + "@esbuild/netbsd-x64" "0.25.0" + "@esbuild/openbsd-arm64" "0.25.0" + "@esbuild/openbsd-x64" "0.25.0" + "@esbuild/sunos-x64" "0.25.0" + "@esbuild/win32-arm64" "0.25.0" + "@esbuild/win32-ia32" "0.25.0" + "@esbuild/win32-x64" "0.25.0" escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -5792,9 +5832,9 @@ execa@^5.1.1: strip-final-newline "^2.0.0" expect-type@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.1.0.tgz#a146e414250d13dfc49eafcfd1344a4060fa4c75" - integrity sha512-bFi65yM+xZgk+u/KRIpekdSYkTB5W1pEf0Lt8Q8Msh7b+eQ7LXVtIB1Bkm4fvclDEL1b2CZkMhv2mOeF8tMdkA== + version "1.2.0" + resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.0.tgz#b52a0a1117260f5a8dcf33aef66365be18c13415" + integrity sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA== extract-zip@2.0.1: version "2.0.1" @@ -5851,9 +5891,9 @@ fast-uri@^3.0.1: integrity sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw== fastq@^1.6.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.0.tgz#a82c6b7c2bb4e44766d865f07997785fecfdcb89" - integrity sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA== + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== dependencies: reusify "^1.0.4" @@ -5990,11 +6030,11 @@ for-each@^0.3.3: is-callable "^1.2.7" foreground-child@^3.1.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" - integrity sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg== + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== dependencies: - cross-spawn "^7.0.0" + cross-spawn "^7.0.6" signal-exit "^4.0.1" form-data@^4.0.0: @@ -7216,13 +7256,6 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -magic-string@^0.27.0: - version "0.27.0" - resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" - integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== - dependencies: - "@jridgewell/sourcemap-codec" "^1.4.13" - magic-string@^0.30.17: version "0.30.17" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" @@ -8101,9 +8134,9 @@ points-on-path@^0.2.1: points-on-curve "0.2.0" portfinder@^1.0.28: - version "1.0.32" - resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.32.tgz#2fe1b9e58389712429dc2bea5beb2146146c7f81" - integrity sha512-on2ZJVVDXRADWE6jnQaX0ioEylzgBpQk8r55NE4wjXW1ZxO+BgDlY6DXwj20i0V8eB4SenDQ00WEaxfiIQPcxg== + version "1.0.33" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.33.tgz#03dbc51455aa8f83ad9fb86af8345e063bb51101" + integrity sha512-+2jndHT63cL5MdQOwDm9OT2dIe11zVpjV+0GGRXdtO1wpPxv260NfVqoEXtYAi/shanmm3W4+yLduIe55ektTw== dependencies: async "^2.6.4" debug "^3.2.7" @@ -8128,7 +8161,7 @@ postcss@8.4.31: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.32, postcss@^8.5.2: +postcss@^8.4.32, postcss@^8.5.3: version "8.5.3" resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== @@ -8308,7 +8341,7 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-refresh@^0.14.0: +react-refresh@^0.14.2: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -8526,9 +8559,9 @@ restore-cursor@^3.1.0: signal-exit "^3.0.2" reusify@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" - integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== rewire@6.0.0: version "6.0.0" @@ -8562,31 +8595,31 @@ rollup@^2.43.1: fsevents "~2.3.2" rollup@^4.2.0, rollup@^4.30.1: - version "4.34.8" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.8.tgz#e859c1a51d899aba9bcf451d4eed1d11fb8e2a6e" - integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ== + version "4.34.9" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.9.tgz#e1eb397856476778aeb6ac2ac3d09b2ce177a558" + integrity sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ== dependencies: "@types/estree" "1.0.6" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.34.8" - "@rollup/rollup-android-arm64" "4.34.8" - "@rollup/rollup-darwin-arm64" "4.34.8" - "@rollup/rollup-darwin-x64" "4.34.8" - "@rollup/rollup-freebsd-arm64" "4.34.8" - "@rollup/rollup-freebsd-x64" "4.34.8" - "@rollup/rollup-linux-arm-gnueabihf" "4.34.8" - "@rollup/rollup-linux-arm-musleabihf" "4.34.8" - "@rollup/rollup-linux-arm64-gnu" "4.34.8" - "@rollup/rollup-linux-arm64-musl" "4.34.8" - "@rollup/rollup-linux-loongarch64-gnu" "4.34.8" - "@rollup/rollup-linux-powerpc64le-gnu" "4.34.8" - "@rollup/rollup-linux-riscv64-gnu" "4.34.8" - "@rollup/rollup-linux-s390x-gnu" "4.34.8" - "@rollup/rollup-linux-x64-gnu" "4.34.8" - "@rollup/rollup-linux-x64-musl" "4.34.8" - "@rollup/rollup-win32-arm64-msvc" "4.34.8" - "@rollup/rollup-win32-ia32-msvc" "4.34.8" - "@rollup/rollup-win32-x64-msvc" "4.34.8" + "@rollup/rollup-android-arm-eabi" "4.34.9" + "@rollup/rollup-android-arm64" "4.34.9" + "@rollup/rollup-darwin-arm64" "4.34.9" + "@rollup/rollup-darwin-x64" "4.34.9" + "@rollup/rollup-freebsd-arm64" "4.34.9" + "@rollup/rollup-freebsd-x64" "4.34.9" + "@rollup/rollup-linux-arm-gnueabihf" "4.34.9" + "@rollup/rollup-linux-arm-musleabihf" "4.34.9" + "@rollup/rollup-linux-arm64-gnu" "4.34.9" + "@rollup/rollup-linux-arm64-musl" "4.34.9" + "@rollup/rollup-linux-loongarch64-gnu" "4.34.9" + "@rollup/rollup-linux-powerpc64le-gnu" "4.34.9" + "@rollup/rollup-linux-riscv64-gnu" "4.34.9" + "@rollup/rollup-linux-s390x-gnu" "4.34.9" + "@rollup/rollup-linux-x64-gnu" "4.34.9" + "@rollup/rollup-linux-x64-musl" "4.34.9" + "@rollup/rollup-win32-arm64-msvc" "4.34.9" + "@rollup/rollup-win32-ia32-msvc" "4.34.9" + "@rollup/rollup-win32-x64-msvc" "4.34.9" fsevents "~2.3.2" roughjs@4.6.4: @@ -9005,16 +9038,7 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0": - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9116,14 +9140,7 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - -strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9263,9 +9280,9 @@ tempy@^0.6.0: unique-string "^2.0.0" terser-webpack-plugin@^5.3.11: - version "5.3.11" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz#93c21f44ca86634257cac176f884f942b7ba3832" - integrity sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ== + version "5.3.12" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.12.tgz#d9518c80493081bace668aa8613b22e4a838810c" + integrity sha512-jDLYqo7oF8tJIttjXO6jBY5Hk8p3A8W4ttih7cCEq64fQFWmgJ4VqAQjKr7WwIDlmXKEc6QeoRb5ecjZ+2afcg== dependencies: "@jridgewell/trace-mapping" "^0.3.25" jest-worker "^27.4.5" @@ -9510,9 +9527,9 @@ typescript@4.9.4: integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== typescript@^5: - version "5.7.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.3.tgz#919b44a7dbb8583a9b856d162be24a54bf80073e" - integrity sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw== + version "5.8.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.2.tgz#8170b3702f74b79db2e5a96207c15e65807999e4" + integrity sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ== typeson-registry@^1.0.0-alpha.20: version "1.0.0-alpha.39" @@ -9616,9 +9633,9 @@ upath@^1.2.0: integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== update-browserslist-db@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" - integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg== + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== dependencies: escalade "^3.2.0" picocolors "^1.1.1" @@ -9765,12 +9782,12 @@ vite-plugin-sitemap@0.7.1: resolved "https://registry.yarnpkg.com/vite-plugin-sitemap/-/vite-plugin-sitemap-0.7.1.tgz#3b3cf6d2e067ec835f810e5eaaacf05485c819fe" integrity sha512-4NRTkiWytLuAmcikckrLcLl9iYA20+5v6l8XshcOrzxH1WR8H0O3S6sTQYfjMrE8su/LG6Y0cTodvOdcOIxaLw== -vite-plugin-svgr@4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz#9f3bf5206b0ec510287e56d16f1915e729bb4e6b" - integrity sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA== +vite-plugin-svgr@4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-4.3.0.tgz#742f16f11375996306c696ec323e4d23f6005075" + integrity sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w== dependencies: - "@rollup/pluginutils" "^5.0.5" + "@rollup/pluginutils" "^5.1.3" "@svgr/core" "^8.1.0" "@svgr/plugin-jsx" "^8.1.0" @@ -9785,13 +9802,13 @@ vite@5.0.12: optionalDependencies: fsevents "~2.3.3" -"vite@^5.0.0 || ^6.0.0": - version "6.1.1" - resolved "https://registry.yarnpkg.com/vite/-/vite-6.1.1.tgz#c1f221749298357b9230782a04483e60ad83c8db" - integrity sha512-4GgM54XrwRfrOp297aIYspIti66k56v16ZnqHvrIM7mG+HjDlAwS7p+Srr7J6fGvEdOJ5JcQ/D9T7HhtdXDTzA== +vite@6.2.0, "vite@^5.0.0 || ^6.0.0": + version "6.2.0" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.0.tgz#9dcb543380dab18d8384eb840a76bf30d78633f0" + integrity sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ== dependencies: - esbuild "^0.24.2" - postcss "^8.5.2" + esbuild "^0.25.0" + postcss "^8.5.3" rollup "^4.30.1" optionalDependencies: fsevents "~2.3.3" @@ -10261,7 +10278,7 @@ workbox-window@7.3.0, workbox-window@^7.3.0: "@types/trusted-types" "^2.0.2" workbox-core "7.3.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -10279,15 +10296,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From c5d3bb0b6a84a0464f6f6fd5802075373b5ffbe8 Mon Sep 17 00:00:00 2001 From: Ritobroto Kalita Date: Tue, 4 Mar 2025 21:54:39 +0530 Subject: [PATCH 32/51] fix: #8475 Arrow updated on both sides (#8593) --- packages/excalidraw/element/binding.ts | 28 ++++++++++- packages/excalidraw/element/bounds.ts | 14 ++++++ .../excalidraw/element/linearElementEditor.ts | 4 +- .../tests/__snapshots__/history.test.tsx.snap | 50 +++++++++---------- .../tests/__snapshots__/move.test.tsx.snap | 12 ++--- packages/excalidraw/tests/move.test.tsx | 7 ++- 6 files changed, 77 insertions(+), 38 deletions(-) diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index d72b846d9..b679ae9d0 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -17,7 +17,11 @@ import type { } from "./types"; import type { Bounds } from "./bounds"; -import { getCenterForBounds } from "./bounds"; +import { + getCenterForBounds, + getElementBounds, + doBoundsIntersect, +} from "./bounds"; import type { AppState } from "../types"; import { isPointOnShape } from "@excalidraw/utils/collision"; import { @@ -743,6 +747,21 @@ export const updateBoundElements = ( return; } + // Check for intersections before updating bound elements incase connected elements overlap + const startBindingElement = element.startBinding + ? elementsMap.get(element.startBinding.elementId) + : null; + const endBindingElement = element.endBinding + ? elementsMap.get(element.endBinding.elementId) + : null; + + let startBounds: Bounds | null = null; + let endBounds: Bounds | null = null; + if (startBindingElement && endBindingElement) { + startBounds = getElementBounds(startBindingElement, elementsMap); + endBounds = getElementBounds(endBindingElement, elementsMap); + } + const bindings = { startBinding: maybeCalculateNewGapWhenScaling( changedElement, @@ -770,7 +789,12 @@ export const updateBoundElements = ( bindableElement && isBindableElement(bindableElement) && (bindingProp === "startBinding" || bindingProp === "endBinding") && - changedElement.id === element[bindingProp]?.elementId + (changedElement.id === element[bindingProp]?.elementId || + (changedElement.id === + element[ + bindingProp === "startBinding" ? "endBinding" : "startBinding" + ]?.elementId && + !doBoundsIntersect(startBounds, endBounds))) ) { const point = updateBoundPoint( element, diff --git a/packages/excalidraw/element/bounds.ts b/packages/excalidraw/element/bounds.ts index 6b5010370..e4be1dfbd 100644 --- a/packages/excalidraw/element/bounds.ts +++ b/packages/excalidraw/element/bounds.ts @@ -1013,3 +1013,17 @@ export const getCenterForBounds = (bounds: Bounds): GlobalPoint => bounds[0] + (bounds[2] - bounds[0]) / 2, bounds[1] + (bounds[3] - bounds[1]) / 2, ); + +export const doBoundsIntersect = ( + bounds1: Bounds | null, + bounds2: Bounds | null, +): boolean => { + if (bounds1 == null || bounds2 == null) { + return false; + } + + const [minX1, minY1, maxX1, maxY1] = bounds1; + const [minX2, minY2, maxX2, maxY2] = bounds2; + + return minX1 < maxX2 && maxX1 > minX2 && minY1 < maxY2 && maxY1 > minY2; +}; diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index 1fcbe5fde..4bf1e988b 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -219,7 +219,9 @@ export class LinearElementEditor { }); } - /** @returns whether point was dragged */ + /** + * @returns whether point was dragged + */ static handlePointDragging( event: PointerEvent, app: AppClassProperties, diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index d8cf4ec2d..165c135fe 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -297,7 +297,7 @@ History { "focus": "0.00990", "gap": 1, }, - "height": "0.98597", + "height": "0.98586", "points": [ [ 0, @@ -305,7 +305,7 @@ History { ], [ "98.58579", - "-0.98597", + "-0.98586", ], ], "startBinding": { @@ -320,7 +320,7 @@ History { "focus": "-0.02000", "gap": 1, }, - "height": "0.00119", + "height": "0.00000", "points": [ [ 0, @@ -328,7 +328,7 @@ History { ], [ "98.58579", - "0.00119", + "0.00000", ], ], "startBinding": { @@ -409,7 +409,7 @@ History { "focus": "0.00990", "gap": 1, }, - "height": "0.98700", + "height": "0.98586", "points": [ [ 0, @@ -417,7 +417,7 @@ History { ], [ "98.58579", - "-0.98700", + "-0.98586", ], ], "startBinding": { @@ -425,7 +425,7 @@ History { "focus": "0.02970", "gap": 1, }, - "y": "0.99465", + "y": "0.99364", }, }, "id175" => Delta { @@ -1238,7 +1238,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "2.52823", + "height": "1.30038", "id": "id178", "index": "Zz", "isDeleted": false, @@ -1253,7 +1253,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl ], [ "98.58579", - "-2.52823", + "1.30038", ], ], "roughness": 1, @@ -1278,7 +1278,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "version": 11, "width": "98.58579", "x": "0.70711", - "y": "3.82861", + "y": 0, } `; @@ -1609,7 +1609,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "2.52823", + "height": "1.30038", "id": "id181", "index": "a0", "isDeleted": false, @@ -1624,7 +1624,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl ], [ "98.58579", - "-2.52823", + "1.30038", ], ], "roughness": 1, @@ -1649,7 +1649,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "version": 11, "width": "98.58579", "x": "0.70711", - "y": "3.82861", + "y": 0, } `; @@ -1767,7 +1767,7 @@ History { "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "22.07000", + "height": "11.27227", "index": "a0", "isDeleted": false, "lastCommittedPoint": null, @@ -1780,8 +1780,8 @@ History { 0, ], [ - "99.27949", - "-22.07000", + "98.58579", + "11.27227", ], ], "roughness": 1, @@ -1802,9 +1802,9 @@ History { "strokeStyle": "solid", "strokeWidth": 2, "type": "arrow", - "width": "99.27949", - "x": "0.01341", - "y": "33.34227", + "width": "98.58579", + "x": "0.70711", + "y": 0, }, "inserted": { "isDeleted": true, @@ -2320,7 +2320,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "410.63965", + "height": "374.05754", "id": "id186", "index": "a2", "isDeleted": false, @@ -2334,8 +2334,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl 0, ], [ - "501.24760", - "-410.63965", + "502.78936", + "-374.05754", ], ], "roughness": 1, @@ -2354,9 +2354,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 10, - "width": "501.24760", - "x": "0.70711", - "y": 0, + "width": "502.78936", + "x": "-0.83465", + "y": "-36.58211", } `; diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index eb5f14498..90236a4dd 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -196,7 +196,7 @@ exports[`move element > rectangles with binding arrow 7`] = ` "fillStyle": "solid", "frameId": null, "groupIds": [], - "height": "84.41974", + "height": "87.29887", "id": "id2", "index": "a2", "isDeleted": false, @@ -210,8 +210,8 @@ exports[`move element > rectangles with binding arrow 7`] = ` 0, ], [ - "83.92893", - "84.41974", + "86.85786", + "87.29887", ], ], "roughness": 1, @@ -232,8 +232,8 @@ exports[`move element > rectangles with binding arrow 7`] = ` "updated": 1, "version": 11, "versionNonce": 1051383431, - "width": "83.92893", - "x": 110, - "y": 50, + "width": "86.85786", + "x": "107.07107", + "y": "47.07107", } `; diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 17de52247..528f9554d 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -1,4 +1,5 @@ import React from "react"; +import "../../utils/test-utils"; import { render, fireEvent, act, unmountComponent } from "./test-utils"; import { Excalidraw } from "../index"; import * as StaticScene from "../renderer/staticScene"; @@ -121,10 +122,8 @@ describe("move element", () => { expect(h.state.selectedElementIds[rectB.id]).toBeTruthy(); expect([rectA.x, rectA.y]).toEqual([0, 0]); expect([rectB.x, rectB.y]).toEqual([201, 2]); - expect([Math.round(arrow.x), Math.round(arrow.y)]).toEqual([110, 50]); - expect([Math.round(arrow.width), Math.round(arrow.height)]).toEqual([ - 84, 84, - ]); + expect([[arrow.x, arrow.y]]).toCloselyEqualPoints([[107.07, 47.07]]); + expect([[arrow.width, arrow.height]]).toCloselyEqualPoints([[86.86, 87.3]]); h.elements.forEach((element) => expect(element).toMatchSnapshot()); }); From d92384b77d1fdce42a56a94395876f1b1e5c1e55 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Tue, 4 Mar 2025 18:45:52 +0100 Subject: [PATCH 33/51] revert: `vite@6` -> `vite@5` (#9220) --- package.json | 6 +-- yarn.lock | 117 +++++++++++++++++++++++++-------------------------- 2 files changed, 61 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index 48d971835..aaa8027a8 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "@types/react": "19.0.10", "@types/react-dom": "19.0.4", "@types/socket.io-client": "3.0.0", - "@vitejs/plugin-react": "4.3.4", + "@vitejs/plugin-react": "3.1.0", "@vitest/coverage-v8": "3.0.7", "@vitest/ui": "2.0.5", "chai": "4.3.6", @@ -35,11 +35,11 @@ "prettier": "2.6.2", "rewire": "6.0.0", "typescript": "4.9.4", - "vite": "6.2.0", + "vite": "5.0.12", "vite-plugin-checker": "0.7.2", "vite-plugin-ejs": "1.7.0", "vite-plugin-pwa": "0.21.1", - "vite-plugin-svgr": "4.3.0", + "vite-plugin-svgr": "4.2.0", "vitest": "3.0.6", "vitest-canvas-mock": "0.3.3" }, diff --git a/yarn.lock b/yarn.lock index 3a8bb3e2e..d1c522a91 100644 --- a/yarn.lock +++ b/yarn.lock @@ -45,7 +45,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== -"@babel/core@^7.16.0", "@babel/core@^7.21.3", "@babel/core@^7.24.4", "@babel/core@^7.26.0": +"@babel/core@^7.16.0", "@babel/core@^7.20.12", "@babel/core@^7.21.3", "@babel/core@^7.24.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.9.tgz#71838542a4b1e49dfed353d7acbc6eb89f4a76f2" integrity sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw== @@ -242,7 +242,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.25.4", "@babel/parser@^7.26.9": +"@babel/parser@^7.25.4", "@babel/parser@^7.26.9": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5" integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A== @@ -750,14 +750,14 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.25.9" -"@babel/plugin-transform-react-jsx-self@^7.25.9": +"@babel/plugin-transform-react-jsx-self@^7.18.6": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== dependencies: "@babel/helper-plugin-utils" "^7.25.9" -"@babel/plugin-transform-react-jsx-source@^7.25.9": +"@babel/plugin-transform-react-jsx-source@^7.19.6": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== @@ -1032,7 +1032,7 @@ debug "^4.3.1" globals "^11.1.0" -"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.21.3", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": +"@babel/types@^7.21.3", "@babel/types@^7.25.4", "@babel/types@^7.25.9", "@babel/types@^7.26.9", "@babel/types@^7.4.4": version "7.26.9" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce" integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw== @@ -2034,7 +2034,7 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.25" -"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.13", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": version "1.5.0" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== @@ -2734,7 +2734,7 @@ estree-walker "^2.0.1" picomatch "^2.2.2" -"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.1.3": +"@rollup/pluginutils@^5.0.1", "@rollup/pluginutils@^5.0.5": version "5.1.4" resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.4.tgz#bb94f1f9eaaac944da237767cdfee6c5b2262d4a" integrity sha512-USm05zrsFxYLPdWWq+K3STlWiT/3ELn3RcV5hJMghpeAIhxfsUIg6mt12CBJBInWMV4VneoV7SfGv8xIwo2qNQ== @@ -3087,39 +3087,6 @@ resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708" integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw== -"@types/babel__core@^7.20.5": - version "7.20.5" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" - integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== - dependencies: - "@babel/parser" "^7.20.7" - "@babel/types" "^7.20.7" - "@types/babel__generator" "*" - "@types/babel__template" "*" - "@types/babel__traverse" "*" - -"@types/babel__generator@*": - version "7.6.8" - resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.6.8.tgz#f836c61f48b1346e7d2b0d93c6dacc5b9535d3ab" - integrity sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw== - dependencies: - "@babel/types" "^7.0.0" - -"@types/babel__template@*": - version "7.4.4" - resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" - integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== - dependencies: - "@babel/parser" "^7.1.0" - "@babel/types" "^7.0.0" - -"@types/babel__traverse@*": - version "7.20.6" - resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.6.tgz#8dc9f0ae0f202c08d8d4dab648912c8d6038e3f7" - integrity sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg== - dependencies: - "@babel/types" "^7.20.7" - "@types/chai@4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.0.tgz#23509ebc1fa32f1b4d50d6a66c4032d5b8eaabdc" @@ -3395,16 +3362,16 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@vitejs/plugin-react@4.3.4": - version "4.3.4" - resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz#c64be10b54c4640135a5b28a2432330e88ad7c20" - integrity sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug== +"@vitejs/plugin-react@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz#d1091f535eab8b83d6e74034d01e27d73c773240" + integrity sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g== dependencies: - "@babel/core" "^7.26.0" - "@babel/plugin-transform-react-jsx-self" "^7.25.9" - "@babel/plugin-transform-react-jsx-source" "^7.25.9" - "@types/babel__core" "^7.20.5" - react-refresh "^0.14.2" + "@babel/core" "^7.20.12" + "@babel/plugin-transform-react-jsx-self" "^7.18.6" + "@babel/plugin-transform-react-jsx-source" "^7.19.6" + magic-string "^0.27.0" + react-refresh "^0.14.0" "@vitest/coverage-v8@3.0.7": version "3.0.7" @@ -7256,6 +7223,13 @@ magic-string@^0.25.0, magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" +magic-string@^0.27.0: + version "0.27.0" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.27.0.tgz#e4a3413b4bab6d98d2becffd48b4a257effdbbf3" + integrity sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.13" + magic-string@^0.30.17: version "0.30.17" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" @@ -8341,7 +8315,7 @@ react-is@^18.0.0: resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e" integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg== -react-refresh@^0.14.2: +react-refresh@^0.14.0: version "0.14.2" resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== @@ -9038,7 +9012,16 @@ string-natural-compare@^3.0.1: resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9140,7 +9123,14 @@ stringify-object@^3.3.0: is-obj "^1.0.1" is-regexp "^1.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@6.0.1, strip-ansi@^6.0.0, strip-ansi@^6.0.1, strip-ansi@^7.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9782,12 +9772,12 @@ vite-plugin-sitemap@0.7.1: resolved "https://registry.yarnpkg.com/vite-plugin-sitemap/-/vite-plugin-sitemap-0.7.1.tgz#3b3cf6d2e067ec835f810e5eaaacf05485c819fe" integrity sha512-4NRTkiWytLuAmcikckrLcLl9iYA20+5v6l8XshcOrzxH1WR8H0O3S6sTQYfjMrE8su/LG6Y0cTodvOdcOIxaLw== -vite-plugin-svgr@4.3.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-4.3.0.tgz#742f16f11375996306c696ec323e4d23f6005075" - integrity sha512-Jy9qLB2/PyWklpYy0xk0UU3TlU0t2UMpJXZvf+hWII1lAmRHrOUKi11Uw8N3rxoNk7atZNYO3pR3vI1f7oi+6w== +vite-plugin-svgr@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/vite-plugin-svgr/-/vite-plugin-svgr-4.2.0.tgz#9f3bf5206b0ec510287e56d16f1915e729bb4e6b" + integrity sha512-SC7+FfVtNQk7So0XMjrrtLAbEC8qjFPifyD7+fs/E6aaNdVde6umlVVh0QuwDLdOMu7vp5RiGFsB70nj5yo0XA== dependencies: - "@rollup/pluginutils" "^5.1.3" + "@rollup/pluginutils" "^5.0.5" "@svgr/core" "^8.1.0" "@svgr/plugin-jsx" "^8.1.0" @@ -9802,7 +9792,7 @@ vite@5.0.12: optionalDependencies: fsevents "~2.3.3" -vite@6.2.0, "vite@^5.0.0 || ^6.0.0": +"vite@^5.0.0 || ^6.0.0": version "6.2.0" resolved "https://registry.yarnpkg.com/vite/-/vite-6.2.0.tgz#9dcb543380dab18d8384eb840a76bf30d78633f0" integrity sha512-7dPxoo+WsT/64rDcwoOjk76XHj+TqNTIvHKcuMQ1k4/SeHDaQt5GFAeLYzrimZrMpn/O6DtdI03WUjdxuPM0oQ== @@ -10278,7 +10268,7 @@ workbox-window@7.3.0, workbox-window@^7.3.0: "@types/trusted-types" "^2.0.2" workbox-core "7.3.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -10296,6 +10286,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 70c3e921bb7f6e4576620d1fc9fa7d81dab6fcc6 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Tue, 4 Mar 2025 21:45:48 +0100 Subject: [PATCH 34/51] fix: package env vars (#9221) --- packages/excalidraw/env.cjs | 8 ++++---- packages/excalidraw/fonts/ExcalidrawFontFace.ts | 2 +- scripts/buildPackage.js | 16 ++++++++++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/packages/excalidraw/env.cjs b/packages/excalidraw/env.cjs index cb7ead2af..8d7862246 100644 --- a/packages/excalidraw/env.cjs +++ b/packages/excalidraw/env.cjs @@ -4,14 +4,14 @@ const pkg = require("./package.json"); const parseEnvVariables = (filepath) => { const envVars = Object.entries(dotenv.parse(readFileSync(filepath))).reduce( (env, [key, value]) => { - env[key] = JSON.stringify(value); + env[key] = value; return env; }, {}, ); - envVars.VITE_PKG_NAME = JSON.stringify(pkg.name); - envVars.VITE_PKG_VERSION = JSON.stringify(pkg.version); - envVars.VITE_IS_EXCALIDRAW_NPM_PACKAGE = JSON.stringify(true); + envVars.VITE_PKG_NAME = pkg.name; + envVars.VITE_PKG_VERSION = pkg.version; + envVars.VITE_IS_EXCALIDRAW_NPM_PACKAGE = true; return envVars; }; diff --git a/packages/excalidraw/fonts/ExcalidrawFontFace.ts b/packages/excalidraw/fonts/ExcalidrawFontFace.ts index 816ed88bd..a20a45577 100644 --- a/packages/excalidraw/fonts/ExcalidrawFontFace.ts +++ b/packages/excalidraw/fonts/ExcalidrawFontFace.ts @@ -10,7 +10,7 @@ export class ExcalidrawFontFace { private static readonly ASSETS_FALLBACK_URL = `https://esm.sh/${ import.meta.env.VITE_PKG_NAME - ? `${import.meta.env.VITE_PKG_NAME}@${import.meta.env.PKG_VERSION}` // should be provided by vite during package build + ? `${import.meta.env.VITE_PKG_NAME}@${import.meta.env.VITE_PKG_VERSION}` // should be provided by vite during package build : "@excalidraw/excalidraw" // fallback to latest package version (i.e. for app) }/dist/prod/`; diff --git a/scripts/buildPackage.js b/scripts/buildPackage.js index e00eb96cb..653af50f2 100644 --- a/scripts/buildPackage.js +++ b/scripts/buildPackage.js @@ -1,6 +1,18 @@ const path = require("path"); const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); +const { parseEnvVariables } = require("../packages/excalidraw/env.cjs"); + +const ENV_VARS = { + development: { + ...parseEnvVariables(`${__dirname}/../.env.development`), + DEV: true, + }, + production: { + ...parseEnvVariables(`${__dirname}/../.env.production`), + PROD: true, + }, +}; // excludes all external dependencies and bundles only the source code const getConfig = (outdir) => ({ @@ -28,7 +40,7 @@ function buildDev(config) { ...config, sourcemap: true, define: { - "import.meta.env": JSON.stringify({ DEV: true }), + "import.meta.env": JSON.stringify(ENV_VARS.development), }, }); } @@ -38,7 +50,7 @@ function buildProd(config) { ...config, minify: true, define: { - "import.meta.env": JSON.stringify({ PROD: true }), + "import.meta.env": JSON.stringify(ENV_VARS.production), }, }); } From a9e2d2348bdad814449b946eefc9515d8132cf8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Wed, 5 Mar 2025 23:06:01 +0100 Subject: [PATCH 35/51] chore: Logging and fixing extremely large scenes (#9225) --- packages/excalidraw/components/App.tsx | 61 +++++++++- packages/excalidraw/data/restore.ts | 106 ++++++++++++------ packages/excalidraw/element/binding.ts | 9 +- packages/excalidraw/element/bounds.ts | 14 +-- packages/excalidraw/element/elbowArrow.ts | 11 +- .../excalidraw/element/linearElementEditor.ts | 63 ++++------- packages/excalidraw/element/resizeElements.ts | 24 +--- packages/excalidraw/renderer/staticScene.ts | 9 +- packages/excalidraw/scene/Shape.ts | 26 ++++- packages/utils/geometry/shape.ts | 5 + 10 files changed, 207 insertions(+), 121 deletions(-) diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 8eb2a9e2c..dc6d28782 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -8437,21 +8437,78 @@ class App extends React.Component { const elements = this.scene.getElementsIncludingDeleted(); for (const element of elements) { - if ( + const isInSelection = selectedElementIds.has(element.id) || // case: the state.selectedElementIds might not have been // updated yet by the time this mousemove event is fired (element.id === hitElement?.id && - pointerDownState.hit.wasAddedToSelection) + pointerDownState.hit.wasAddedToSelection); + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(element.x) > 1e7 || + Math.abs(element.x) > 1e7 || + Math.abs(element.width) > 1e7 || + Math.abs(element.height) > 1e7 ) { + console.error( + `Alt+dragging element in scene with invalid dimensions`, + element.x, + element.y, + element.width, + element.height, + isInSelection, + ); + + return; + } + + if (isInSelection) { const duplicatedElement = duplicateElement( this.state.editingGroupId, groupIdMap, element, ); + + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(duplicatedElement.x) > 1e7 || + Math.abs(duplicatedElement.x) > 1e7 || + Math.abs(duplicatedElement.width) > 1e7 || + Math.abs(duplicatedElement.height) > 1e7 + ) { + console.error( + `Alt+dragging duplicated element with invalid dimensions`, + duplicatedElement.x, + duplicatedElement.y, + duplicatedElement.width, + duplicatedElement.height, + ); + + return; + } + const origElement = pointerDownState.originalElements.get( element.id, )!; + + // NOTE (mtolmacs): This is a temporary fix for very large scenes + if ( + Math.abs(origElement.x) > 1e7 || + Math.abs(origElement.x) > 1e7 || + Math.abs(origElement.width) > 1e7 || + Math.abs(origElement.height) > 1e7 + ) { + console.error( + `Alt+dragging duplicated element with invalid dimensions`, + origElement.x, + origElement.y, + origElement.width, + origElement.height, + ); + + return; + } + mutateElement(duplicatedElement, { x: origElement.x, y: origElement.y, diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index 257a2208a..c4e45b025 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -8,6 +8,7 @@ import type { ExcalidrawTextElement, FixedPointBinding, FontFamilyValues, + NonDeletedSceneElementsMap, OrderedExcalidrawElement, PointBinding, StrokeRoundness, @@ -60,6 +61,10 @@ import { import type { LocalPoint, Radians } from "@excalidraw/math"; import { isFiniteNumber, pointFrom } from "@excalidraw/math"; import { detectLineHeight } from "../element/textMeasurements"; +import { + updateElbowArrowPoints, + validateElbowPoints, +} from "../element/elbowArrow"; type RestoredAppState = Omit< AppState, @@ -206,24 +211,6 @@ const restoreElementWithProperties = < "customData" in extra ? extra.customData : element.customData; } - // NOTE (mtolmacs): This is a temporary check to detect extremely large - // element position or sizing - if ( - element.x < -1e6 || - element.x > 1e6 || - element.y < -1e6 || - element.y > 1e6 || - element.width < -1e6 || - element.width > 1e6 || - element.height < -1e6 || - element.height > 1e6 - ) { - console.error( - "Restore element with properties size or position is too large", - { element }, - ); - } - return { // spread the original element properties to not lose unknown ones // for forward-compatibility @@ -240,21 +227,6 @@ const restoreElement = ( ): typeof element | null => { element = { ...element }; - // NOTE (mtolmacs): This is a temporary check to detect extremely large - // element position or sizing - if ( - element.x < -1e6 || - element.x > 1e6 || - element.y < -1e6 || - element.y > 1e6 || - element.width < -1e6 || - element.width > 1e6 || - element.height < -1e6 || - element.height > 1e6 - ) { - console.error("Restore element size or position is too large", { element }); - } - switch (element.type) { case "text": // temp fix: cleanup legacy obsidian-excalidraw attribute else it'll @@ -596,7 +568,73 @@ export const restoreElements = ( } } - return restoredElements; + // NOTE (mtolmacs): Temporary fix for extremely large arrows + // Need to iterate again so we have attached text nodes in elementsMap + return restoredElements.map((element) => { + if ( + isElbowArrow(element) && + element.startBinding == null && + element.endBinding == null && + !validateElbowPoints(element.points) + ) { + return { + ...element, + ...updateElbowArrowPoints( + element, + restoredElementsMap as NonDeletedSceneElementsMap, + { + points: [ + pointFrom(0, 0), + element.points[element.points.length - 1], + ], + }, + ), + index: element.index, + }; + } + + if ( + isElbowArrow(element) && + element.startBinding && + element.endBinding && + element.startBinding.elementId === element.endBinding.elementId && + element.points.length > 1 && + element.points.some( + ([rx, ry]) => Math.abs(rx) > 1e6 || Math.abs(ry) > 1e6, + ) + ) { + console.error("Fixing self-bound elbow arrow", element.id); + const boundElement = restoredElementsMap.get( + element.startBinding.elementId, + ); + if (!boundElement) { + console.error( + "Bound element not found", + element.startBinding.elementId, + ); + return element; + } + + return { + ...element, + x: boundElement.x + boundElement.width / 2, + y: boundElement.y - 5, + width: boundElement.width, + height: boundElement.height, + points: [ + pointFrom(0, 0), + pointFrom(0, -10), + pointFrom(boundElement.width / 2 + 5, -10), + pointFrom( + boundElement.width / 2 + 5, + boundElement.height / 2 + 5, + ), + ], + }; + } + + return element; + }); }; const coalesceAppStateValue = < diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index b679ae9d0..8de9254fa 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -943,7 +943,10 @@ export const bindPointToSnapToElementOutline = ( ), )[0]; const currentDistance = pointDistance(p, center); - const fullDistance = pointDistance(intersection, center); + const fullDistance = Math.max( + pointDistance(intersection ?? p, center), + 1e-5, + ); const ratio = currentDistance / fullDistance; switch (true) { @@ -954,10 +957,10 @@ export const bindPointToSnapToElementOutline = ( return pointFromVector( vectorScale( - vectorNormalize(vectorFromPoint(p, intersection)), + vectorNormalize(vectorFromPoint(p, intersection ?? center)), ratio > 1 ? FIXED_BINDING_DISTANCE : -FIXED_BINDING_DISTANCE, ), - intersection, + intersection ?? center, ); default: diff --git a/packages/excalidraw/element/bounds.ts b/packages/excalidraw/element/bounds.ts index e4be1dfbd..06f977023 100644 --- a/packages/excalidraw/element/bounds.ts +++ b/packages/excalidraw/element/bounds.ts @@ -40,6 +40,7 @@ import { pointRotateRads, } from "@excalidraw/math"; import type { Mutable } from "../utility-types"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; export type RectangleBox = { x: number; @@ -367,15 +368,6 @@ export const getDiamondPoints = (element: ExcalidrawElement) => { return [topX, topY, rightX, rightY, bottomX, bottomY, leftX, leftY]; }; -export const getCurvePathOps = (shape: Drawable): Op[] => { - for (const set of shape.sets) { - if (set.type === "path") { - return set.ops; - } - } - return shape.sets[0].ops; -}; - // reference: https://eliot-jones.com/2019/12/cubic-bezier-curve-bounding-boxes const getBezierValueForT = ( t: number, @@ -583,6 +575,10 @@ export const getArrowheadPoints = ( position: "start" | "end", arrowhead: Arrowhead, ) => { + if (shape.length < 1) { + return null; + } + const ops = getCurvePathOps(shape[0]); if (ops.length < 1) { return null; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 703cea0d5..a965d2f93 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -1038,7 +1038,13 @@ export const updateElbowArrowPoints = ( // Short circuit on no-op to avoid huge performance hit if ( updates.startBinding === arrow.startBinding && - updates.endBinding === arrow.endBinding + updates.endBinding === arrow.endBinding && + (updates.points ?? []).every((p, i) => + pointsEqual( + p, + arrow.points[i] ?? pointFrom(Infinity, Infinity), + ), + ) ) { return {}; } @@ -2034,7 +2040,6 @@ const normalizeArrowElementUpdate = ( } => { const offsetX = global[0][0]; const offsetY = global[0][1]; - let points = global.map((p) => pointTranslate( p, @@ -2240,7 +2245,7 @@ const getHoveredElements = ( const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => a[0] === b[0] && a[1] === b[1]; -const validateElbowPoints =

( +export const validateElbowPoints =

( points: readonly P[], tolerance: number = DEDUP_TRESHOLD, ) => diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index 4bf1e988b..b616268a6 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -14,11 +14,7 @@ import type { } from "./types"; import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; import type { Bounds } from "./bounds"; -import { - getCurvePathOps, - getElementPointsCoords, - getMinMaxXYFromCurvePathOps, -} from "./bounds"; +import { getElementPointsCoords, getMinMaxXYFromCurvePathOps } from "./bounds"; import type { AppState, PointerCoords, @@ -53,11 +49,9 @@ import { pointFrom, pointRotateRads, pointsEqual, - vector, type GlobalPoint, type LocalPoint, pointDistance, - pointTranslate, vectorFromPoint, } from "@excalidraw/math"; import { @@ -69,6 +63,7 @@ import { } from "../shapes"; import { getGridPoint } from "../snapping"; import { headingIsHorizontal, vectorToHeading } from "./heading"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; const editorMidPointsCache: { version: number | null; @@ -1273,34 +1268,28 @@ export class LinearElementEditor { // all the other points in the opposite direction by delta to // offset it. We do the same with actual element.x/y position, so // this hacks are completely transparent to the user. - let offsetX = 0; - let offsetY = 0; + const [deltaX, deltaY] = + targetPoints.find(({ index }) => index === 0)?.point ?? + pointFrom(0, 0); + const [offsetX, offsetY] = pointFrom( + deltaX - points[0][0], + deltaY - points[0][1], + ); - const selectedOriginPoint = targetPoints.find(({ index }) => index === 0); + const nextPoints = isElbowArrow(element) + ? [ + targetPoints.find((t) => t.index === 0)?.point ?? points[0], + targetPoints.find((t) => t.index === points.length - 1)?.point ?? + points[points.length - 1], + ] + : points.map((p, idx) => { + const current = targetPoints.find((t) => t.index === idx)?.point ?? p; - if (selectedOriginPoint) { - offsetX = - selectedOriginPoint.point[0] + points[selectedOriginPoint.index][0]; - offsetY = - selectedOriginPoint.point[1] + points[selectedOriginPoint.index][1]; - } - - const nextPoints: LocalPoint[] = points.map((p, idx) => { - const selectedPointData = targetPoints.find((t) => t.index === idx); - if (selectedPointData) { - if (selectedPointData.index === 0) { - return p; - } - - const deltaX = - selectedPointData.point[0] - points[selectedPointData.index][0]; - const deltaY = - selectedPointData.point[1] - points[selectedPointData.index][1]; - - return pointFrom(p[0] + deltaX - offsetX, p[1] + deltaY - offsetY); - } - return offsetX || offsetY ? pointFrom(p[0] - offsetX, p[1] - offsetY) : p; - }); + return pointFrom( + current[0] - offsetX, + current[1] - offsetY, + ); + }); LinearElementEditor._updatePoints( element, @@ -1451,14 +1440,6 @@ export class LinearElementEditor { } updates.points = Array.from(nextPoints); - updates.points[0] = pointTranslate( - updates.points[0], - vector(offsetX, offsetY), - ); - updates.points[updates.points.length - 1] = pointTranslate( - updates.points[updates.points.length - 1], - vector(offsetX, offsetY), - ); mutateElement(element, updates, true, { isDragging: options?.isDragging, diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index f71a0bc7a..b86ba0279 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -769,32 +769,12 @@ const getResizedOrigin = ( y: y - (newHeight - prevHeight) / 2, }; case "east-side": - // NOTE (mtolmacs): Reverting this for a short period to test if it is - // the cause of the megasized elbow arrows showing up. - if ( - Math.abs( - y + - ((prevWidth - newWidth) / 2) * Math.sin(angle) + - (prevHeight - newHeight) / 2, - ) > 1e6 - ) { - console.error( - "getResizedOrigin() new calculation creates extremely large (> 1e6) y value where the old calculation resulted in", - { - result: - y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle), - }, - ); - } - return { x: x + ((prevWidth - newWidth) / 2) * (Math.cos(angle) + 1), y: y + - (newHeight - prevHeight) / 2 + - ((prevWidth - newWidth) / 2) * Math.sin(angle), + ((prevWidth - newWidth) / 2) * Math.sin(angle) + + (prevHeight - newHeight) / 2, }; case "west-side": return { diff --git a/packages/excalidraw/renderer/staticScene.ts b/packages/excalidraw/renderer/staticScene.ts index 21fca4590..90ed8af43 100644 --- a/packages/excalidraw/renderer/staticScene.ts +++ b/packages/excalidraw/renderer/staticScene.ts @@ -351,7 +351,14 @@ const _renderStaticScene = ({ renderLinkIcon(element, context, appState, elementsMap); } } catch (error: any) { - console.error(error); + console.error( + error, + element.id, + element.x, + element.y, + element.width, + element.height, + ); } }); diff --git a/packages/excalidraw/scene/Shape.ts b/packages/excalidraw/scene/Shape.ts index 0fef0b2b2..9c49db0c2 100644 --- a/packages/excalidraw/scene/Shape.ts +++ b/packages/excalidraw/scene/Shape.ts @@ -430,12 +430,26 @@ export const _generateElementShape = ( : [pointFrom(0, 0)]; if (isElbowArrow(element)) { - shape = [ - generator.path( - generateElbowArrowShape(points, 16), - generateRoughOptions(element, true), - ), - ]; + // NOTE (mtolmacs): Temporary fix for extremely big arrow shapes + if ( + !points.every( + (point) => Math.abs(point[0]) <= 1e6 && Math.abs(point[1]) <= 1e6, + ) + ) { + console.error( + `Elbow arrow with extreme point positions detected. Arrow not rendered.`, + element.id, + JSON.stringify(points), + ); + shape = []; + } else { + shape = [ + generator.path( + generateElbowArrowShape(points, 16), + generateRoughOptions(element, true), + ), + ]; + } } else if (!element.roundness) { // curve is always the first element // this simplifies finding the curve for an element diff --git a/packages/utils/geometry/shape.ts b/packages/utils/geometry/shape.ts index 2ba04a2b2..10fc06e31 100644 --- a/packages/utils/geometry/shape.ts +++ b/packages/utils/geometry/shape.ts @@ -192,6 +192,11 @@ export const getEllipseShape = ( }; export const getCurvePathOps = (shape: Drawable): Op[] => { + // NOTE (mtolmacs): Temporary fix for extremely large elements + if (!shape) { + return []; + } + for (const set of shape.sets) { if (set.type === "path") { return set.ops; From 4ec812bc18df090b9acc797e9a385156d13a1285 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Sat, 8 Mar 2025 12:39:54 +0100 Subject: [PATCH 36/51] fix: Bound elbow arrow on duplication does not route correctly (#9236) --- .../excalidraw/element/elbowArrow.test.tsx | 113 ++++++++++++++++++ packages/excalidraw/element/elbowArrow.ts | 56 +++++---- 2 files changed, 143 insertions(+), 26 deletions(-) diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index 1839e978c..c00eae989 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -3,6 +3,7 @@ import Scene from "../scene/Scene"; import { API } from "../tests/helpers/api"; import { Pointer, UI } from "../tests/helpers/ui"; import { + act, fireEvent, GlobalTestState, queryByTestId, @@ -19,6 +20,8 @@ import { ARROW_TYPE } from "../constants"; import "../../utils/test-utils"; import type { LocalPoint } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; +import { actionDuplicateSelection } from "../actions/actionDuplicateSelection"; +import { actionSelectAll } from "../actions"; const { h } = window; @@ -292,4 +295,114 @@ describe("elbow arrow ui", () => { [103, 165], ]); }); + + it("keeps arrow shape when the whole set of arrow and bindables are duplicated", async () => { + UI.createElement("rectangle", { + x: -150, + y: -150, + width: 100, + height: 100, + }); + UI.createElement("rectangle", { + x: 50, + y: 50, + width: 100, + height: 100, + }); + + UI.clickTool("arrow"); + UI.clickOnTestId("elbow-arrow"); + + mouse.reset(); + mouse.moveTo(-43, -99); + mouse.click(); + mouse.moveTo(43, 99); + mouse.click(); + + const arrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + const originalArrowId = arrow.id; + + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + + act(() => { + h.app.actionManager.executeAction(actionSelectAll); + }); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + expect(h.elements.length).toEqual(6); + + const duplicatedArrow = h.scene.getSelectedElements( + h.state, + )[2] as ExcalidrawArrowElement; + + expect(duplicatedArrow.id).not.toBe(originalArrowId); + expect(duplicatedArrow.type).toBe("arrow"); + expect(duplicatedArrow.elbowed).toBe(true); + expect(duplicatedArrow.points).toEqual([ + [0, 0], + [45, 0], + [45, 200], + [90, 200], + ]); + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + }); + + it("keeps arrow shape when only the bound arrow is duplicated", async () => { + UI.createElement("rectangle", { + x: -150, + y: -150, + width: 100, + height: 100, + }); + UI.createElement("rectangle", { + x: 50, + y: 50, + width: 100, + height: 100, + }); + + UI.clickTool("arrow"); + UI.clickOnTestId("elbow-arrow"); + + mouse.reset(); + mouse.moveTo(-43, -99); + mouse.click(); + mouse.moveTo(43, 99); + mouse.click(); + + const arrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + const originalArrowId = arrow.id; + + expect(arrow.startBinding).not.toBe(null); + expect(arrow.endBinding).not.toBe(null); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + expect(h.elements.length).toEqual(4); + + const duplicatedArrow = h.scene.getSelectedElements( + h.state, + )[0] as ExcalidrawArrowElement; + + expect(duplicatedArrow.id).not.toBe(originalArrowId); + expect(duplicatedArrow.type).toBe("arrow"); + expect(duplicatedArrow.elbowed).toBe(true); + expect(duplicatedArrow.points).toEqual([ + [0, 0], + [45, 0], + [45, 200], + [90, 200], + ]); + }); }); diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index a965d2f93..48ddeee2c 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -963,24 +963,6 @@ export const updateElbowArrowPoints = ( ); } - // 0. During all element replacement in the scene, we just need to renormalize - // the arrow - // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed - if ( - elementsMap.size === 0 && - updates.points && - validateElbowPoints(updates.points) - ) { - return normalizeArrowElementUpdate( - updates.points.map((p) => - pointFrom(arrow.x + p[0], arrow.y + p[1]), - ), - arrow.fixedSegments, - arrow.startIsSpecial, - arrow.endIsSpecial, - ); - } - const updatedPoints: readonly LocalPoint[] = updates.points ? updates.points && updates.points.length === 2 ? arrow.points.map((p, idx) => @@ -993,6 +975,34 @@ export const updateElbowArrowPoints = ( : updates.points.slice() : arrow.points.slice(); + // 0. During all element replacement in the scene, we just need to renormalize + // the arrow + // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed + const startBinding = + typeof updates.startBinding !== "undefined" + ? updates.startBinding + : arrow.startBinding; + const endBinding = + typeof updates.endBinding !== "undefined" + ? updates.endBinding + : arrow.endBinding; + const startElement = startBinding && elementsMap.get(startBinding.elementId); + const endElement = endBinding && elementsMap.get(endBinding.elementId); + if ( + (elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || + startElement?.id !== startBinding?.elementId || + endElement?.id !== endBinding?.elementId + ) { + return normalizeArrowElementUpdate( + updatedPoints.map((p) => + pointFrom(arrow.x + p[0], arrow.y + p[1]), + ), + arrow.fixedSegments, + arrow.startIsSpecial, + arrow.endIsSpecial, + ); + } + const { startHeading, endHeading, @@ -1005,14 +1015,8 @@ export const updateElbowArrowPoints = ( { x: arrow.x, y: arrow.y, - startBinding: - typeof updates.startBinding !== "undefined" - ? updates.startBinding - : arrow.startBinding, - endBinding: - typeof updates.endBinding !== "undefined" - ? updates.endBinding - : arrow.endBinding, + startBinding, + endBinding, startArrowhead: arrow.startArrowhead, endArrowhead: arrow.endArrowhead, }, From d587b8a3de6ce8b4ae1bd7578210977ab99fddb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Mon, 10 Mar 2025 16:25:33 +0100 Subject: [PATCH 37/51] fix: Do not rebind undragged elbow arrow endpoint (#9191) --- packages/excalidraw/element/binding.ts | 29 +++-- packages/excalidraw/element/elbowArrow.ts | 109 +++++++++++-------- packages/excalidraw/element/flowchart.ts | 3 +- packages/excalidraw/element/mutateElement.ts | 4 +- packages/excalidraw/tests/resize.test.tsx | 5 +- 5 files changed, 90 insertions(+), 60 deletions(-) diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 8de9254fa..e716b860f 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -73,6 +73,8 @@ import { vectorCross, pointsEqual, lineSegmentIntersectionPoints, + round, + PRECISION, } from "@excalidraw/math"; import { intersectElementWithLineSegment } from "./collision"; import { distanceToBindableElement } from "./distance"; @@ -272,14 +274,16 @@ const getBindingStrategyForDraggingArrowEndpoints = ( zoom, ) : null // If binding is disabled and start is dragged, break all binds - : // We have to update the focus and gap of the binding, so let's rebind + : !isElbowArrow(selectedElement) + ? // We have to update the focus and gap of the binding, so let's rebind getElligibleElementForBindingElement( selectedElement, "start", elementsMap, elements, zoom, - ); + ) + : "keep"; const end = endDragged ? isBindingEnabled ? getElligibleElementForBindingElement( @@ -290,14 +294,16 @@ const getBindingStrategyForDraggingArrowEndpoints = ( zoom, ) : null // If binding is disabled and end is dragged, break all binds - : // We have to update the focus and gap of the binding, so let's rebind + : !isElbowArrow(selectedElement) + ? // We have to update the focus and gap of the binding, so let's rebind getElligibleElementForBindingElement( selectedElement, "end", elementsMap, elements, zoom, - ); + ) + : "keep"; return [start, end]; }; @@ -309,6 +315,11 @@ const getBindingStrategyForDraggingArrowOrJoints = ( isBindingEnabled: boolean, zoom?: AppState["zoom"], ): (NonDeleted | null | "keep")[] => { + // Elbow arrows don't bind when dragged as a whole + if (isElbowArrow(selectedElement)) { + return ["keep", "keep"]; + } + const [startIsClose, endIsClose] = getOriginalBindingsIfStillCloseToArrowEnds( selectedElement, elementsMap, @@ -945,13 +956,17 @@ export const bindPointToSnapToElementOutline = ( const currentDistance = pointDistance(p, center); const fullDistance = Math.max( pointDistance(intersection ?? p, center), - 1e-5, + PRECISION, ); - const ratio = currentDistance / fullDistance; + const ratio = round(currentDistance / fullDistance, 6); switch (true) { case ratio > 0.9: - if (currentDistance - fullDistance > FIXED_BINDING_DISTANCE) { + if ( + currentDistance - fullDistance > FIXED_BINDING_DISTANCE || + // Too close to determine vector from intersection to p + pointDistanceSq(p, intersection) < PRECISION + ) { return p; } diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 48ddeee2c..ce8c3d5a6 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -15,7 +15,7 @@ import { import BinaryHeap from "../binaryheap"; import { getSizeFromPoints } from "../points"; import { aabbForElement, pointInsideBounds } from "../shapes"; -import { invariant, isAnyTrue, toBrandedType, tupleToCoors } from "../utils"; +import { invariant, isAnyTrue, tupleToCoors } from "../utils"; import type { AppState } from "../types"; import { bindPointToSnapToElementOutline, @@ -52,6 +52,7 @@ import type { ExcalidrawBindableElement, FixedPointBinding, FixedSegment, + NonDeletedExcalidrawElement, } from "./types"; import { distanceToBindableElement } from "./distance"; @@ -101,7 +102,7 @@ export const BASE_PADDING = 40; const handleSegmentRenormalization = ( arrow: ExcalidrawElbowArrowElement, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, ) => { const nextFixedSegments: FixedSegment[] | null = arrow.fixedSegments ? arrow.fixedSegments.slice() @@ -234,6 +235,16 @@ const handleSegmentRenormalization = ( nextPoints.map((p) => pointFrom(p[0] - arrow.x, p[1] - arrow.y), ), + arrow.startBinding && + getBindableElementForId( + arrow.startBinding.elementId, + elementsMap, + ), + arrow.endBinding && + getBindableElementForId( + arrow.endBinding.elementId, + elementsMap, + ), ), ) ?? [], ), @@ -271,7 +282,7 @@ const handleSegmentRenormalization = ( const handleSegmentRelease = ( arrow: ExcalidrawElbowArrowElement, fixedSegments: readonly FixedSegment[], - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, ) => { const newFixedSegmentIndices = fixedSegments.map((segment) => segment.index); const oldFixedSegmentIndices = @@ -295,6 +306,8 @@ const handleSegmentRelease = ( // We need to render a sub-arrow path to restore deleted segments const x = arrow.x + (prevSegment ? prevSegment.end[0] : 0); const y = arrow.y + (prevSegment ? prevSegment.end[1] : 0); + const startBinding = prevSegment ? null : arrow.startBinding; + const endBinding = nextSegment ? null : arrow.endBinding; const { startHeading, endHeading, @@ -307,10 +320,11 @@ const handleSegmentRelease = ( { x, y, - startBinding: prevSegment ? null : arrow.startBinding, - endBinding: nextSegment ? null : arrow.endBinding, + startBinding, + endBinding, startArrowhead: null, endArrowhead: null, + points: arrow.points, }, elementsMap, [ @@ -324,6 +338,9 @@ const handleSegmentRelease = ( y, ), ], + startBinding && + getBindableElementForId(startBinding.elementId, elementsMap), + endBinding && getBindableElementForId(endBinding.elementId, elementsMap), { isDragging: false }, ); @@ -870,7 +887,7 @@ const MAX_POS = 1e6; */ export const updateElbowArrowPoints = ( arrow: Readonly, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, updates: { points?: readonly LocalPoint[]; fixedSegments?: FixedSegment[] | null; @@ -986,8 +1003,11 @@ export const updateElbowArrowPoints = ( typeof updates.endBinding !== "undefined" ? updates.endBinding : arrow.endBinding; - const startElement = startBinding && elementsMap.get(startBinding.elementId); - const endElement = endBinding && elementsMap.get(endBinding.elementId); + const startElement = + startBinding && + getBindableElementForId(startBinding.elementId, elementsMap); + const endElement = + endBinding && getBindableElementForId(endBinding.elementId, elementsMap); if ( (elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || startElement?.id !== startBinding?.elementId || @@ -1019,9 +1039,12 @@ export const updateElbowArrowPoints = ( endBinding, startArrowhead: arrow.startArrowhead, endArrowhead: arrow.endArrowhead, + points: arrow.points, }, elementsMap, updatedPoints, + startElement, + endElement, options, ); @@ -1155,9 +1178,12 @@ const getElbowArrowData = ( endBinding: FixedPointBinding | null; startArrowhead: Arrowhead | null; endArrowhead: Arrowhead | null; + points: readonly LocalPoint[]; }, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, + elementsMap: NonDeletedSceneElementsMap, nextPoints: readonly LocalPoint[], + startElement: ExcalidrawBindableElement | null, + endElement: ExcalidrawBindableElement | null, options?: { isDragging?: boolean; zoom?: AppState["zoom"]; @@ -1171,20 +1197,27 @@ const getElbowArrowData = ( LocalPoint, GlobalPoint >(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y)); - const startElement = - arrow.startBinding && - getBindableElementForId(arrow.startBinding.elementId, elementsMap); - const endElement = - arrow.endBinding && - getBindableElementForId(arrow.endBinding.elementId, elementsMap); - const [hoveredStartElement, hoveredEndElement] = options?.isDragging - ? getHoveredElements( + + let hoveredStartElement = startElement; + let hoveredEndElement = endElement; + if (options?.isDragging) { + const elements = Array.from(elementsMap.values()); + hoveredStartElement = + getHoveredElement( origStartGlobalPoint, + elementsMap, + elements, + options?.zoom, + ) || startElement; + hoveredEndElement = + getHoveredElement( origEndGlobalPoint, elementsMap, + elements, options?.zoom, - ) - : [startElement, endElement]; + ) || endElement; + } + const startGlobalPoint = getGlobalPoint( { ...arrow, @@ -2214,36 +2247,20 @@ const getBindPointHeading = ( origPoint, ); -const getHoveredElements = ( - origStartGlobalPoint: GlobalPoint, - origEndGlobalPoint: GlobalPoint, - elementsMap: NonDeletedSceneElementsMap | SceneElementsMap, +const getHoveredElement = ( + origPoint: GlobalPoint, + elementsMap: NonDeletedSceneElementsMap, + elements: readonly NonDeletedExcalidrawElement[], zoom?: AppState["zoom"], ) => { - // TODO: Might be a performance bottleneck and the Map type - // remembers the insertion order anyway... - const nonDeletedSceneElementsMap = toBrandedType( - new Map([...elementsMap].filter((el) => !el[1].isDeleted)), + return getHoveredElementForBinding( + tupleToCoors(origPoint), + elements, + elementsMap, + zoom, + true, + true, ); - const elements = Array.from(elementsMap.values()); - return [ - getHoveredElementForBinding( - tupleToCoors(origStartGlobalPoint), - elements, - nonDeletedSceneElementsMap, - zoom, - true, - true, - ), - getHoveredElementForBinding( - tupleToCoors(origEndGlobalPoint), - elements, - nonDeletedSceneElementsMap, - zoom, - true, - true, - ), - ]; }; const gridAddressesEqual = (a: GridAddress, b: GridAddress): boolean => diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index 02ee1ff29..09f006dd0 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -10,7 +10,6 @@ import { import { bindLinearElement } from "./binding"; import { LinearElementEditor } from "./linearElementEditor"; import { newArrowElement, newElement } from "./newElement"; -import type { SceneElementsMap } from "./types"; import { type ElementsMap, type ExcalidrawBindableElement, @@ -472,7 +471,7 @@ const createBindingArrow = ( const update = updateElbowArrowPoints( bindingArrow, - toBrandedType( + toBrandedType( new Map([ ...elementsMap.entries(), [startBindingElement.id, startBindingElement], diff --git a/packages/excalidraw/element/mutateElement.ts b/packages/excalidraw/element/mutateElement.ts index b64366be9..cfff5c826 100644 --- a/packages/excalidraw/element/mutateElement.ts +++ b/packages/excalidraw/element/mutateElement.ts @@ -1,4 +1,4 @@ -import type { ExcalidrawElement, SceneElementsMap } from "./types"; +import type { ExcalidrawElement, NonDeletedSceneElementsMap } from "./types"; import Scene from "../scene/Scene"; import { getSizeFromPoints } from "../points"; import { randomInteger } from "../random"; @@ -44,7 +44,7 @@ export const mutateElement = >( typeof startBinding !== "undefined" || typeof endBinding !== "undefined") // manual binding to element ) { - const elementsMap = toBrandedType( + const elementsMap = toBrandedType( Scene.getScene(element)?.getNonDeletedElementsMap() ?? new Map(), ); diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index a12d31048..3ebd8cf81 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -533,9 +533,8 @@ describe("arrow element", () => { expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.75); UI.resize([rectangle, arrow], "nw", [300, 350]); - - expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(-0.13); - expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.11); + expect(arrow.startBinding?.fixedPoint?.[0]).toBeCloseTo(0); + expect(arrow.startBinding?.fixedPoint?.[1]).toBeCloseTo(0.25); }); }); From 69bc5bdaab1fe0064a7db085535748f7eab5f181 Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Tue, 11 Mar 2025 13:02:59 +0100 Subject: [PATCH 38/51] chore: post publish docs & examples changes (#9217) --- .../@excalidraw/excalidraw/development.mdx | 2 +- .../@excalidraw/excalidraw/installation.mdx | 2 +- .../@excalidraw/excalidraw/integration.mdx | 6 +- dev-docs/package.json | 2 +- dev-docs/src/theme/ReactLiveScope/index.js | 2 +- dev-docs/yarn.lock | 316 +++++++++++------- examples/with-script-in-browser/index.html | 3 +- examples/with-script-in-browser/package.json | 5 +- examples/with-script-in-browser/vercel.json | 3 +- packages/excalidraw/CHANGELOG.md | 12 +- packages/excalidraw/README.md | 2 +- packages/excalidraw/components/Actions.tsx | 19 -- .../excalidraw/components/SearchMenu.scss | 2 +- .../welcome-screen/WelcomeScreen.scss | 10 - packages/excalidraw/env.cjs | 7 +- .../excalidraw/fonts/ExcalidrawFontFace.ts | 6 +- packages/excalidraw/vite-env.d.ts | 5 +- yarn.lock | 240 ++----------- 18 files changed, 256 insertions(+), 388 deletions(-) diff --git a/dev-docs/docs/@excalidraw/excalidraw/development.mdx b/dev-docs/docs/@excalidraw/excalidraw/development.mdx index 52ec484aa..60700758f 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/development.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/development.mdx @@ -24,7 +24,7 @@ To start the example app using the `@excalidraw/excalidraw` package, follow the [http://localhost:3001](http://localhost:3001) will open in your default browser. - This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. + This is the same example as the [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example. ## Releasing diff --git a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx index 2ff6c2d2d..bcab22990 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/installation.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/installation.mdx @@ -52,4 +52,4 @@ Excalidraw takes _100%_ of `width` and `height` of the containing block so make ## Demo -Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example. +Go to [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example. diff --git a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx index 62bbbcca5..117877b75 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/integration.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/integration.mdx @@ -131,7 +131,7 @@ If you are using `pages router` then importing the wrapper dynamically would wor {/* Link should be updated to point to the latest! */} Here is a [source code](https://github.com/excalidraw/excalidraw/tree/master/examples/with-nextjs) for the example with app and pages router. You you can try it out [here](https://excalidraw-package-example-with-nextjs.vercel.app/). -The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/mrazator/release-v18/examples/with-script-in-browser) example for details. +The `types` are available at `@excalidraw/excalidraw/types`, check [CodeSandbox](https://codesandbox.io/p/sandbox/github/excalidraw/excalidraw/tree/master/examples/with-script-in-browser) example for details. ### Preact @@ -206,7 +206,7 @@ import TabItem from "@theme/TabItem"; ```js showLineNumbers // See https://www.npmjs.com/package/@excalidraw/excalidraw documentation. -import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.1/dist/dev/index.js?external=react,react-dom'; +import * as ExcalidrawLib from 'https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/dev/index.js?external=react,react-dom'; import React from "https://esm.sh/react@19.0.0"; import ReactDOM from "https://esm.sh/react-dom@19.0.0" @@ -235,4 +235,4 @@ root.render(React.createElement(App)); -You can try it out [here](https://jsfiddle.net/64y130L8/1/). +You can try it out [here](https://jsfiddle.net/vfn6dm14/3/). diff --git a/dev-docs/package.json b/dev-docs/package.json index 8cbd6d232..1577df9b9 100644 --- a/dev-docs/package.json +++ b/dev-docs/package.json @@ -18,7 +18,7 @@ "@docusaurus/core": "2.2.0", "@docusaurus/preset-classic": "2.2.0", "@docusaurus/theme-live-codeblock": "2.2.0", - "@excalidraw/excalidraw": "0.18.0-rc.5", + "@excalidraw/excalidraw": "0.18.0", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "docusaurus-plugin-sass": "0.2.3", diff --git a/dev-docs/src/theme/ReactLiveScope/index.js b/dev-docs/src/theme/ReactLiveScope/index.js index 4fa715f46..ca5a902e8 100644 --- a/dev-docs/src/theme/ReactLiveScope/index.js +++ b/dev-docs/src/theme/ReactLiveScope/index.js @@ -12,7 +12,7 @@ if (ExecutionEnvironment.canUseDOM) { const Excalidraw = React.forwardRef((props, ref) => { if (!window.EXCALIDRAW_ASSET_PATH) { window.EXCALIDRAW_ASSET_PATH = - "https://esm.sh/@excalidraw/excalidraw@0.18.0-rc.5/dist/prod/"; + "https://esm.sh/@excalidraw/excalidraw@0.18.0/dist/prod/"; } const { colorMode } = useColorMode(); diff --git a/dev-docs/yarn.lock b/dev-docs/yarn.lock index 6e54d978b..306c17f2a 100644 --- a/dev-docs/yarn.lock +++ b/dev-docs/yarn.lock @@ -1735,16 +1735,16 @@ url-loader "^4.1.1" webpack "^5.73.0" -"@excalidraw/excalidraw@0.18.0-rc.5": - version "0.18.0-rc.5" - resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0-rc.5.tgz#c55598e01808693702251322e59bf9dba931b6e0" - integrity sha512-f6Z6cWlx+FWl1nxCu5F6OdKm9ooV/FPjndjIfFhGLVyERKATXhuNwZUHWwqsEW+SIGmiPG2515NG9KIOhjGd5g== +"@excalidraw/excalidraw@0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@excalidraw/excalidraw/-/excalidraw-0.18.0.tgz#9f818e2df80a8735af54f8cc21da67997785532f" + integrity sha512-QkIiS+5qdy8lmDWTKsuy0sK/fen/LRDtbhm2lc2xcFcqhv2/zdg95bYnl+wnwwXGHo7kEmP65BSiMHE7PJ3Zpw== dependencies: "@braintree/sanitize-url" "6.0.2" "@excalidraw/laser-pointer" "1.3.1" "@excalidraw/mermaid-to-excalidraw" "1.1.2" "@excalidraw/random-username" "1.1.0" - "@radix-ui/react-popover" "1.0.3" + "@radix-ui/react-popover" "1.1.6" "@radix-ui/react-tabs" "1.0.2" browser-fs-access "0.29.1" canvas-roundrect-polyfill "0.0.1" @@ -1796,25 +1796,32 @@ resolved "https://registry.yarnpkg.com/@excalidraw/random-username/-/random-username-1.1.0.tgz#6f388d6a9708cf655b8c9c6aa3fa569ee71ecf0f" integrity sha512-nULYsQxkWHnbmHvcs+efMkJ4/9TtvNyFeLyHdeGxW0zHs6P+jYVqcRff9A6Vq9w9JXeDRnRh2VKvTtS19GW2qA== -"@floating-ui/core@^0.7.3": - version "0.7.3" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-0.7.3.tgz#d274116678ffae87f6b60e90f88cc4083eefab86" - integrity sha512-buc8BXHmG9l82+OQXOFU3Kr2XQx9ys01U/Q9HMIrZ300iLc8HLMgh7dcCqgYzAzf4BkoQvDcXf5Y+CuEZ5JBYg== - -"@floating-ui/dom@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-0.5.4.tgz#4eae73f78bcd4bd553ae2ade30e6f1f9c73fe3f1" - integrity sha512-419BMceRLq0RrmTSDxn8hf9R3VCJv2K9PUfugh5JyEFmdjzDo+e8U5EdR8nzKq8Yj1htzLm3b6eQEEam3/rrtg== +"@floating-ui/core@^1.6.0": + version "1.6.9" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.9.tgz#64d1da251433019dafa091de9b2886ff35ec14e6" + integrity sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw== dependencies: - "@floating-ui/core" "^0.7.3" + "@floating-ui/utils" "^0.2.9" -"@floating-ui/react-dom@0.7.2": - version "0.7.2" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-0.7.2.tgz#0bf4ceccb777a140fc535c87eb5d6241c8e89864" - integrity sha512-1T0sJcpHgX/u4I1OzIEhlcrvkUN8ln39nz7fMoE/2HDHrPiMFoOGR7++GYyfUmIQHkkrTinaeQsO3XWubjSvGg== +"@floating-ui/dom@^1.0.0": + version "1.6.13" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.13.tgz#a8a938532aea27a95121ec16e667a7cbe8c59e34" + integrity sha512-umqzocjDgNRGTuO7Q8CU32dkHkECqI8ZdMZ5Swb6QAM0t5rnlrN3lGo1hdpscRd3WS8T6DKYK4ephgIH9iRh3w== dependencies: - "@floating-ui/dom" "^0.5.3" - use-isomorphic-layout-effect "^1.1.1" + "@floating-ui/core" "^1.6.0" + "@floating-ui/utils" "^0.2.9" + +"@floating-ui/react-dom@^2.0.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31" + integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A== + dependencies: + "@floating-ui/dom" "^1.0.0" + +"@floating-ui/utils@^0.2.9": + version "0.2.9" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.9.tgz#50dea3616bc8191fb8e112283b49eaff03e78429" + integrity sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg== "@hapi/hoek@^9.0.0": version "9.3.0" @@ -1982,13 +1989,17 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-arrow@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.1.tgz#5246adf79e97f89e819af68da51ddcf349ecf1c4" - integrity sha512-1yientwXqXcErDHEv8av9ZVNEBldH8L9scVR3is20lL+jOCfcJyMFZFEY5cgIrgexsq1qggSXqiEL/d/4f+QXA== +"@radix-ui/primitive@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" + integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== + +"@radix-ui/react-arrow@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.2.tgz#30c0d574d7bb10eed55cd7007b92d38b03c6b2ab" + integrity sha512-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/react-primitive" "2.0.2" "@radix-ui/react-collection@1.0.1": version "1.0.1" @@ -2008,6 +2019,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" + integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== + "@radix-ui/react-context@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.0.0.tgz#f38e30c5859a9fb5e9aa9a9da452ee3ed9e0aee0" @@ -2015,6 +2031,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" + integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== + "@radix-ui/react-direction@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.0.tgz#a2e0b552352459ecf96342c79949dd833c1e6e45" @@ -2022,34 +2043,30 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-dismissable-layer@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.2.tgz#f04d1061bddf00b1ca304148516b9ddc62e45fb2" - integrity sha512-WjJzMrTWROozDqLB0uRWYvj4UuXsM/2L19EmQ3Au+IJWqwvwq9Bwd+P8ivo0Deg9JDPArR1I6MbWNi1CmXsskg== +"@radix-ui/react-dismissable-layer@1.1.5": + version "1.1.5" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.5.tgz#96dde2be078c694a621e55e047406c58cd5fe774" + integrity sha512-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-escape-keydown" "1.0.2" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" -"@radix-ui/react-focus-guards@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.0.tgz#339c1c69c41628c1a5e655f15f7020bf11aa01fa" - integrity sha512-UagjDk4ijOAnGu4WMUPj9ahi7/zJJqNZ9ZAiGPp7waUWJO0O1aWXi/udPphI0IUjvrhBsZJGSN66dR2dsueLWQ== - dependencies: - "@babel/runtime" "^7.13.10" +"@radix-ui/react-focus-guards@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" + integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== -"@radix-ui/react-focus-scope@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.1.tgz#faea8c25f537c5a5c38c50914b63722db0e7f951" - integrity sha512-Ej2MQTit8IWJiS2uuujGUmxXjF/y5xZptIIQnyd2JHLwtV0R2j9NRVoRj/1j/gJ7e3REdaBw4Hjf4a1ImhkZcQ== +"@radix-ui/react-focus-scope@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.2.tgz#c0a4519cd95c772606a82fc5b96226cd7fdd2602" + integrity sha512-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-id@1.0.0": version "1.0.0" @@ -2059,52 +2076,57 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.0" -"@radix-ui/react-popover@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.0.3.tgz#65ae2ee1fca2d7fd750308549eb8e0857c6160fe" - integrity sha512-YwedSukfWsyJs3/yP3yXUq44k4/JBe3jqU63Z8v2i19qZZ3dsx32oma17ztgclWPNuqp3A+Xa9UiDlZHyVX8Vg== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.0" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-dismissable-layer" "1.0.2" - "@radix-ui/react-focus-guards" "1.0.0" - "@radix-ui/react-focus-scope" "1.0.1" - "@radix-ui/react-id" "1.0.0" - "@radix-ui/react-popper" "1.1.0" - "@radix-ui/react-portal" "1.0.1" - "@radix-ui/react-presence" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-slot" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.0" - aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" - -"@radix-ui/react-popper@1.1.0": +"@radix-ui/react-id@1.1.0": version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.0.tgz#2be7e4c0cd4581f54277ca33a981c9037d2a8e60" - integrity sha512-07U7jpI0dZcLRAxT7L9qs6HecSoPhDSJybF7mEGHJDBDv+ZoGCvIlva0s+WxMXwJEav+ckX3hAlXBtnHmuvlCQ== + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== dependencies: - "@babel/runtime" "^7.13.10" - "@floating-ui/react-dom" "0.7.2" - "@radix-ui/react-arrow" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.0" - "@radix-ui/react-context" "1.0.0" - "@radix-ui/react-primitive" "1.0.1" - "@radix-ui/react-use-callback-ref" "1.0.0" - "@radix-ui/react-use-layout-effect" "1.0.0" - "@radix-ui/react-use-rect" "1.0.0" - "@radix-ui/react-use-size" "1.0.0" - "@radix-ui/rect" "1.0.0" + "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-portal@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.1.tgz#169c5a50719c2bb0079cf4c91a27aa6d37e5dd33" - integrity sha512-NY2vUWI5WENgAT1nfC6JS7RU5xRYBfjZVLq0HmgEN1Ezy3rk/UruMV4+Rd0F40PEaFC5SrLS1ixYvcYIQrb4Ig== +"@radix-ui/react-popover@1.1.6": + version "1.1.6" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.6.tgz#699634dbc7899429f657bb590d71fb3ca0904087" + integrity sha512-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.1" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.5" + "@radix-ui/react-focus-guards" "1.1.1" + "@radix-ui/react-focus-scope" "1.1.2" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.2" + "@radix-ui/react-portal" "1.1.4" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-use-controllable-state" "1.1.0" + aria-hidden "^1.2.4" + react-remove-scroll "^2.6.3" + +"@radix-ui/react-popper@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.2.tgz#d2e1ee5a9b24419c5936a1b7f6f472b7b412b029" + integrity sha512-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@radix-ui/react-arrow" "1.1.2" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" + +"@radix-ui/react-portal@1.1.4": + version "1.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.4.tgz#ff5401ff63c8a825c46eea96d3aef66074b8c0c8" + integrity sha512-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA== + dependencies: + "@radix-ui/react-primitive" "2.0.2" + "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-presence@1.0.0": version "1.0.0" @@ -2115,6 +2137,14 @@ "@radix-ui/react-compose-refs" "1.0.0" "@radix-ui/react-use-layout-effect" "1.0.0" +"@radix-ui/react-presence@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" + integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-primitive@1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-1.0.1.tgz#c1ebcce283dd2f02e4fbefdaa49d1cb13dbc990a" @@ -2123,6 +2153,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.1" +"@radix-ui/react-primitive@2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.2.tgz#ac8b7854d87b0d7af388d058268d9a7eb64ca8ef" + integrity sha512-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w== + dependencies: + "@radix-ui/react-slot" "1.1.2" + "@radix-ui/react-roving-focus@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.2.tgz#d8ac2e3b8006697bdfc2b0eb06bef7e15b6245de" @@ -2147,6 +2184,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.0" +"@radix-ui/react-slot@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.2.tgz#daffff7b2bfe99ade63b5168407680b93c00e1c6" + integrity sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ== + dependencies: + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-tabs@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.0.2.tgz#8f5ec73ca41b151a413bdd6e00553408ff34ce07" @@ -2169,6 +2213,11 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== + "@radix-ui/react-use-controllable-state@1.0.0": version "1.0.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.0.tgz#a64deaafbbc52d5d407afaa22d493d687c538b7f" @@ -2177,13 +2226,19 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-callback-ref" "1.0.0" -"@radix-ui/react-use-escape-keydown@1.0.2": - version "1.0.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.2.tgz#09ab6455ab240b4f0a61faf06d4e5132c4d639f6" - integrity sha512-DXGim3x74WgUv+iMNCF+cAo8xUHHeqvjx8zs7trKf+FkQKPQXLk2sX7Gx1ysH7Q76xCpZuxIJE7HLPxRE+Q+GA== +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== + dependencies: + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect@1.0.0": version "1.0.0" @@ -2192,28 +2247,29 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-use-rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.0.tgz#b040cc88a4906b78696cd3a32b075ed5b1423b3e" - integrity sha512-TB7pID8NRMEHxb/qQJpvSt3hQU4sqNPM1VCTjTRjEOa7cEop/QMuq8S6fb/5Tsz64kqSvB9WnwsDHtjnrM9qew== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect" "1.0.0" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== -"@radix-ui/react-use-size@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.0.tgz#a0b455ac826749419f6354dc733e2ca465054771" - integrity sha512-imZ3aYcoYCKhhgNpkNDh/aTiU05qw9hX+HHI1QDBTyIlcFjgeFlKKySNGMwTp7nYFLQg/j0VA2FmCY4WPDDHMg== +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.0" + "@radix-ui/rect" "1.1.0" -"@radix-ui/rect@1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.0.tgz#0dc8e6a829ea2828d53cbc94b81793ba6383bf3c" - integrity sha512-d0O68AYy/9oeEy1DdC07bz1/ZXX+DqCskRd3i4JzLSTXwefzaepQrKjXC7aNM8lTHjFLDO0pDgaEiQ7jEk+HVg== +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== dependencies: - "@babel/runtime" "^7.13.10" + "@radix-ui/react-use-layout-effect" "1.1.0" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== "@sideway/address@^4.1.3": version "4.1.4" @@ -2952,7 +3008,7 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -aria-hidden@^1.1.1: +aria-hidden@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.4.tgz#b78e383fdbc04d05762c78b4a25a501e736c4522" integrity sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A== @@ -7483,7 +7539,7 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1: "@types/react" "*" prop-types "^15.6.2" -react-remove-scroll-bar@^2.3.3: +react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -7491,16 +7547,16 @@ react-remove-scroll-bar@^2.3.3: react-style-singleton "^2.2.2" tslib "^2.0.0" -react-remove-scroll@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" - integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== +react-remove-scroll@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.3.tgz#df02cde56d5f2731e058531f8ffd7f9adec91ac2" + integrity sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ== dependencies: - react-remove-scroll-bar "^2.3.3" - react-style-singleton "^2.2.1" + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.3" tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.3" react-router-config@^5.1.1: version "5.1.1" @@ -7543,7 +7599,7 @@ react-simple-code-editor@^0.10.0: resolved "https://registry.yarnpkg.com/react-simple-code-editor/-/react-simple-code-editor-0.10.0.tgz#73e7ac550a928069715482aeb33ccba36efe2373" integrity sha512-bL5W5mAxSW6+cLwqqVWY47Silqgy2DKDTR4hDBrLrUqC5BXc29YVx17l2IZk5v36VcDEq1Bszu2oHm1qBwKqBA== -react-style-singleton@^2.2.1, react-style-singleton@^2.2.2: +react-style-singleton@^2.2.2, react-style-singleton@^2.2.3: version "2.2.3" resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388" integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ== @@ -8805,7 +8861,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -use-callback-ref@^1.3.0: +use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== @@ -8829,7 +8885,7 @@ use-latest@^1.2.1: dependencies: use-isomorphic-layout-effect "^1.1.1" -use-sidecar@^1.1.2: +use-sidecar@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb" integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ== diff --git a/examples/with-script-in-browser/index.html b/examples/with-script-in-browser/index.html index 07c36bde0..dbbc4ca21 100644 --- a/examples/with-script-in-browser/index.html +++ b/examples/with-script-in-browser/index.html @@ -12,9 +12,8 @@ - diff --git a/examples/with-script-in-browser/package.json b/examples/with-script-in-browser/package.json index 41d31630c..3d61f1a1b 100644 --- a/examples/with-script-in-browser/package.json +++ b/examples/with-script-in-browser/package.json @@ -5,7 +5,7 @@ "dependencies": { "react": "19.0.0", "react-dom": "19.0.0", - "@excalidraw/excalidraw": "0.18.0-rc.5", + "@excalidraw/excalidraw": "*", "browser-fs-access": "0.29.1" }, "devDependencies": { @@ -15,6 +15,7 @@ "scripts": { "start": "vite", "build": "vite build", - "build:preview": "yarn build && vite preview --port 5002" + "build:preview": "yarn build && vite preview --port 5002", + "build:package": "yarn workspace @excalidraw/excalidraw run build:esm" } } diff --git a/examples/with-script-in-browser/vercel.json b/examples/with-script-in-browser/vercel.json index 139f31ef0..99a5811c3 100644 --- a/examples/with-script-in-browser/vercel.json +++ b/examples/with-script-in-browser/vercel.json @@ -1,4 +1,5 @@ { "outputDirectory": "dist", - "installCommand": "yarn install" + "installCommand": "yarn install", + "buildCommand": "yarn build:package && yarn build" } diff --git a/packages/excalidraw/CHANGELOG.md b/packages/excalidraw/CHANGELOG.md index cdcb39660..a31e88781 100644 --- a/packages/excalidraw/CHANGELOG.md +++ b/packages/excalidraw/CHANGELOG.md @@ -64,14 +64,20 @@ We've transitioned from `UMD` to `ESM` bundle format. Our new `dist` bundles ins │ └── types/ ``` -##### JavaScript: required `"type": "module"` in package.json - -Make sure that your JavaScript environment supports ES modules, as it might be required to define `"type": "module"` in your `package.json` file or as part of the ` @@ -159,7 +159,7 @@ or, if you serve your assets from the root of your CDN, you would do: ``` -or, if you prefer the path to be dynamicly set based on the `location.origin`, you could do the following: +or, if you prefer the path to be dynamically set based on the `location.origin`, you could do the following: ```jsx // Next.js @@ -189,7 +189,7 @@ updateScene({ }); // B ``` -The `updateScene` API has changed due to the added `Store` component, as part of multiplayer undo / redo initiative. Specifically, optional `sceneData` parameter `commitToHistory: boolean` was replaced with optional `captureUpdate: CaptureUpdateActionType` parameter. Therefore, make sure to update all instances of `updateScene`, which use `commitToHistory` parameter according to the _before / after_ table below. +The `updateScene` API has changed due to the added `Store` component, as part of the multiplayer undo / redo initiative. Specifically, optional `sceneData` parameter `commitToHistory: boolean` was replaced with optional `captureUpdate: CaptureUpdateActionType` parameter. Therefore, make sure to update all instances of `updateScene`, which use `commitToHistory` parameter according to the _before / after_ table below. > **Note**: Some updates are not observed by the store / history - i.e. updates to `collaborators` object or parts of `AppState` which are not observed (not `ObservedAppState`). Such updates will never make it to the undo / redo stacks, regardless of the passed `captureUpdate` value. @@ -203,7 +203,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - `ExcalidrawTextElement.baseline` was removed and replaced with a vertical offset computation based on font metrics, performed on each text element re-render. In case of custom font usage, extend the `FONT_METRICS` object with the related properties. [#7693](https://github.com/excalidraw/excalidraw/pull/7693) -- `ExcalidrawEmbeddableElement.validated` was removed and moved to private editor state. This should largely not affect your apps unless you were reading from this attribute. We keep validating embeddable urls internally, and the public [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateembeddable) still applies. [#7539](https://github.com/excalidraw/excalidraw/pull/7539) +- `ExcalidrawEmbeddableElement.validated` was removed and moved to the private editor state. This should largely not affect your apps unless you were reading from this attribute. We keep validating embeddable urls internally, and the public [`props.validateEmbeddable`](https://docs.excalidraw.com/docs/@excalidraw/excalidraw/api/props#validateembeddable) still applies. [#7539](https://github.com/excalidraw/excalidraw/pull/7539) - Stats container CSS has changed, so if you're using `renderCustomStats`, you may need to adjust your styles to retain the same layout. [#8361](https://github.com/excalidraw/excalidraw/pull/8361) @@ -487,7 +487,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Linear element complete button disabled [#8492](https://github.com/excalidraw/excalidraw/pull/8492) -- Aspect ratio of distorted images are not preserved in SVG exports [#8061](https://github.com/excalidraw/excalidraw/pull/8061) +- Aspect ratios of distorted images are not preserved in SVG exports [#8061](https://github.com/excalidraw/excalidraw/pull/8061) - WYSIWYG editor padding is not normalized with zoom.value [#8481](https://github.com/excalidraw/excalidraw/pull/8481) @@ -517,7 +517,7 @@ The `updateScene` API has changed due to the added `Store` component, as part of - Round coordinates and sizes for rectangle intersection [#8366](https://github.com/excalidraw/excalidraw/pull/8366) -- Text content with tab characters act different in view/edit [#8336](https://github.com/excalidraw/excalidraw/pull/8336) +- Text content with tab characters act differently in view/edit [#8336](https://github.com/excalidraw/excalidraw/pull/8336) - Drawing from 0-dimension canvas [#8356](https://github.com/excalidraw/excalidraw/pull/8356) From 21ffaf4d76bf8554c3ba5561ab8ff41ce89b55fa Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Wed, 12 Mar 2025 15:23:31 +0100 Subject: [PATCH 41/51] refactor: auto ordered imports (#9163) --- .eslintrc.json | 15 ++ dev-docs/src/components/Homepage/index.js | 3 +- dev-docs/src/components/Homepage/index.tsx | 3 +- dev-docs/src/pages/index.tsx | 9 +- dev-docs/src/theme/MDXComponents.js | 2 +- examples/with-nextjs/src/app/page.tsx | 1 + .../with-nextjs/src/excalidrawWrapper.tsx | 3 +- .../src/pages/excalidraw-in-pages.tsx | 1 + .../components/CustomFooter.tsx | 1 + .../components/ExampleApp.tsx | 39 ++- .../components/MobileFooter.tsx | 6 +- .../components/sidebar/ExampleSidebar.tsx | 1 + examples/with-script-in-browser/index.tsx | 5 +- examples/with-script-in-browser/utils.ts | 4 +- excalidraw-app/App.tsx | 202 +++++++-------- excalidraw-app/CustomStats.tsx | 16 +- excalidraw-app/ExcalidrawPlusIframeExport.tsx | 10 +- excalidraw-app/app-language/LanguageList.tsx | 4 +- .../app-language/language-detector.ts | 2 +- excalidraw-app/app-language/language-state.ts | 2 + excalidraw-app/collab/Collab.tsx | 102 ++++---- excalidraw-app/collab/CollabError.tsx | 1 + excalidraw-app/collab/Portal.tsx | 31 +-- excalidraw-app/components/AI.tsx | 3 +- excalidraw-app/components/AppFooter.tsx | 8 +- excalidraw-app/components/AppMainMenu.tsx | 9 +- .../components/AppWelcomeScreen.tsx | 5 +- excalidraw-app/components/DebugCanvas.tsx | 23 +- excalidraw-app/components/EncryptedIcon.tsx | 2 +- .../components/ExportToExcalidrawPlus.tsx | 30 +-- excalidraw-app/components/GitHubCorner.tsx | 3 +- .../components/TopErrorBoundary.tsx | 6 +- excalidraw-app/data/FileManager.ts | 3 +- excalidraw-app/data/LocalData.ts | 17 +- excalidraw-app/data/firebase.ts | 42 ++-- excalidraw-app/data/index.ts | 16 +- excalidraw-app/data/localStorage.ts | 6 +- excalidraw-app/index.tsx | 4 +- excalidraw-app/share/ShareDialog.tsx | 20 +- excalidraw-app/tests/MobileMenu.test.tsx | 4 +- excalidraw-app/tests/collab.test.tsx | 13 +- excalidraw-app/useHandleAppTheme.ts | 6 +- package.json | 1 + .../excalidraw/actions/actionAddToLibrary.ts | 9 +- packages/excalidraw/actions/actionAlign.tsx | 10 +- .../excalidraw/actions/actionBoundText.tsx | 22 +- packages/excalidraw/actions/actionCanvas.tsx | 35 +-- .../excalidraw/actions/actionClipboard.tsx | 11 +- .../excalidraw/actions/actionCropEditor.tsx | 10 +- .../actions/actionDeleteSelected.test.tsx | 4 +- .../actions/actionDeleteSelected.tsx | 28 ++- .../excalidraw/actions/actionDistribute.tsx | 10 +- .../actions/actionDuplicateSelection.test.tsx | 8 +- .../actions/actionDuplicateSelection.tsx | 48 ++-- .../excalidraw/actions/actionElementLink.ts | 1 + .../actions/actionElementLock.test.tsx | 9 +- .../excalidraw/actions/actionElementLock.ts | 4 +- packages/excalidraw/actions/actionExport.tsx | 30 +-- .../excalidraw/actions/actionFinalize.tsx | 25 +- .../excalidraw/actions/actionFlip.test.tsx | 10 +- packages/excalidraw/actions/actionFlip.ts | 42 ++-- packages/excalidraw/actions/actionFrame.ts | 26 +- packages/excalidraw/actions/actionGroup.tsx | 52 ++-- packages/excalidraw/actions/actionHistory.tsx | 23 +- .../excalidraw/actions/actionLinearEditor.tsx | 12 +- packages/excalidraw/actions/actionLink.tsx | 3 +- packages/excalidraw/actions/actionMenu.tsx | 7 +- .../excalidraw/actions/actionNavigate.tsx | 9 +- .../actions/actionProperties.test.tsx | 11 +- .../excalidraw/actions/actionProperties.tsx | 60 ++--- .../excalidraw/actions/actionSelectAll.ts | 16 +- packages/excalidraw/actions/actionStyles.ts | 28 ++- .../actions/actionTextAutoResize.ts | 4 +- .../actions/actionToggleGridMode.tsx | 8 +- .../actions/actionToggleObjectsSnapMode.tsx | 1 + .../actions/actionToggleSearchMenu.ts | 10 +- .../excalidraw/actions/actionToggleStats.tsx | 5 +- .../actions/actionToggleViewMode.tsx | 1 + .../actions/actionToggleZenMode.tsx | 1 + packages/excalidraw/actions/actionZindex.tsx | 21 +- packages/excalidraw/actions/manager.tsx | 16 +- packages/excalidraw/actions/shortcuts.ts | 3 +- packages/excalidraw/actions/types.ts | 4 +- packages/excalidraw/align.ts | 11 +- packages/excalidraw/animated-trail.ts | 13 +- packages/excalidraw/appState.ts | 1 + packages/excalidraw/change.ts | 25 +- packages/excalidraw/charts.test.ts | 3 +- packages/excalidraw/charts.ts | 7 +- packages/excalidraw/clients.ts | 1 + packages/excalidraw/clipboard.ts | 21 +- packages/excalidraw/colors.ts | 1 + packages/excalidraw/components/Actions.tsx | 68 ++--- .../components/ActiveConfirmDialog.tsx | 3 +- packages/excalidraw/components/App.tsx | 233 +++++++++--------- packages/excalidraw/components/Avatar.tsx | 9 +- packages/excalidraw/components/Button.tsx | 2 + packages/excalidraw/components/ButtonIcon.tsx | 5 +- .../excalidraw/components/ButtonIconCycle.tsx | 3 +- .../components/ButtonIconSelect.tsx | 4 +- .../excalidraw/components/CheckboxItem.tsx | 3 +- .../components/ColorPicker/ColorInput.tsx | 21 +- .../components/ColorPicker/ColorPicker.tsx | 31 +-- .../ColorPicker/CustomColorList.tsx | 6 +- .../components/ColorPicker/HotkeyLabel.tsx | 1 + .../components/ColorPicker/Picker.tsx | 27 +- .../ColorPicker/PickerColorList.tsx | 9 +- .../components/ColorPicker/ShadeList.tsx | 9 +- .../components/ColorPicker/TopPicks.tsx | 4 +- .../ColorPicker/colorPickerUtils.ts | 5 +- .../ColorPicker/keyboardNavHandlers.ts | 14 +- .../CommandPalette/CommandPalette.tsx | 59 +++-- .../defaultCommandPaletteItems.ts | 1 + .../excalidraw/components/ConfirmDialog.tsx | 13 +- .../excalidraw/components/ContextMenu.tsx | 21 +- .../excalidraw/components/DarkModeToggle.tsx | 8 +- .../components/DefaultSidebar.test.tsx | 2 + .../excalidraw/components/DefaultSidebar.tsx | 16 +- .../DiagramToCodePlugin.tsx | 2 + packages/excalidraw/components/Dialog.tsx | 15 +- .../components/DialogActionButton.tsx | 7 +- .../components/ElementLinkDialog.tsx | 19 +- .../excalidraw/components/ErrorDialog.tsx | 3 +- packages/excalidraw/components/EyeDropper.tsx | 10 +- .../excalidraw/components/FilledButton.tsx | 12 +- .../components/FixedSideContainer.tsx | 4 +- .../components/FollowMode/FollowMode.tsx | 4 +- .../components/FontPicker/FontPicker.tsx | 16 +- .../components/FontPicker/FontPickerList.tsx | 17 +- .../FontPicker/FontPickerTrigger.tsx | 7 +- .../FontPicker/keyboardNavHandlers.ts | 4 +- packages/excalidraw/components/HandButton.tsx | 8 +- packages/excalidraw/components/HelpButton.tsx | 1 + packages/excalidraw/components/HelpDialog.tsx | 20 +- packages/excalidraw/components/HintViewer.tsx | 13 +- packages/excalidraw/components/IconPicker.tsx | 13 +- .../components/ImageExportDialog.tsx | 20 +- .../excalidraw/components/InitializeApp.tsx | 6 +- packages/excalidraw/components/Island.tsx | 4 +- .../components/JSONExportDialog.tsx | 21 +- .../components/LaserPointerButton.tsx | 6 +- packages/excalidraw/components/LayerUI.tsx | 95 +++---- .../excalidraw/components/LibraryMenu.tsx | 47 ++-- .../components/LibraryMenuBrowseButton.tsx | 1 + .../components/LibraryMenuControlButtons.tsx | 6 +- .../components/LibraryMenuHeaderContent.tsx | 37 +-- .../components/LibraryMenuItems.tsx | 29 ++- .../components/LibraryMenuSection.tsx | 9 +- .../excalidraw/components/LibraryUnit.tsx | 10 +- .../excalidraw/components/LoadingMessage.tsx | 9 +- packages/excalidraw/components/LockButton.tsx | 6 +- .../excalidraw/components/MagicButton.tsx | 5 +- packages/excalidraw/components/MobileMenu.tsx | 39 +-- packages/excalidraw/components/Modal.tsx | 12 +- .../OverwriteConfirm/OverwriteConfirm.tsx | 7 +- .../OverwriteConfirmActions.tsx | 7 +- .../OverwriteConfirm/OverwriteConfirmState.ts | 1 + .../components/PasteChartDialog.tsx | 9 +- .../excalidraw/components/PenModeButton.tsx | 6 +- packages/excalidraw/components/Popover.tsx | 6 +- .../excalidraw/components/ProjectName.tsx | 11 +- .../components/PropertiesPopover.tsx | 7 +- .../excalidraw/components/PublishLibrary.tsx | 31 +-- .../excalidraw/components/QuickSearch.tsx | 1 + packages/excalidraw/components/RadioGroup.tsx | 1 + packages/excalidraw/components/Range.tsx | 2 + packages/excalidraw/components/SVGLayer.tsx | 3 +- packages/excalidraw/components/SearchMenu.tsx | 38 +-- packages/excalidraw/components/Section.tsx | 2 + .../components/ShareableLinkDialog.tsx | 4 +- .../components/Sidebar/Sidebar.test.tsx | 4 +- .../excalidraw/components/Sidebar/Sidebar.tsx | 29 ++- .../components/Sidebar/SidebarHeader.tsx | 8 +- .../components/Sidebar/SidebarTab.tsx | 1 + .../components/Sidebar/SidebarTabTrigger.tsx | 1 + .../components/Sidebar/SidebarTabs.tsx | 1 + .../components/Sidebar/SidebarTrigger.tsx | 8 +- .../excalidraw/components/Sidebar/common.ts | 3 +- .../Sidebar/siderbar.test.helpers.tsx | 1 + packages/excalidraw/components/Stack.tsx | 4 +- .../excalidraw/components/Stats/Angle.tsx | 12 +- .../components/Stats/CanvasGrid.tsx | 6 +- .../excalidraw/components/Stats/Dimension.tsx | 21 +- .../excalidraw/components/Stats/DragInput.tsx | 21 +- .../excalidraw/components/Stats/FontSize.tsx | 18 +- .../components/Stats/MultiAngle.tsx | 14 +- .../components/Stats/MultiDimension.tsx | 17 +- .../components/Stats/MultiFontSize.tsx | 14 +- .../components/Stats/MultiPosition.tsx | 19 +- .../excalidraw/components/Stats/Position.tsx | 17 +- .../excalidraw/components/Stats/index.tsx | 55 +++-- .../components/Stats/stats.test.tsx | 32 +-- packages/excalidraw/components/Stats/utils.ts | 15 +- .../TTDDialog/MermaidToExcalidraw.tsx | 28 ++- .../components/TTDDialog/TTDDialog.tsx | 34 +-- .../components/TTDDialog/TTDDialogInput.tsx | 4 +- .../components/TTDDialog/TTDDialogPanel.tsx | 6 +- .../components/TTDDialog/TTDDialogTabs.tsx | 6 +- .../components/TTDDialog/TTDDialogTrigger.tsx | 15 +- .../excalidraw/components/TTDDialog/common.ts | 8 +- packages/excalidraw/components/TextField.tsx | 8 +- packages/excalidraw/components/Toast.tsx | 7 +- packages/excalidraw/components/ToolButton.tsx | 15 +- packages/excalidraw/components/Tooltip.tsx | 4 +- packages/excalidraw/components/Trans.test.tsx | 3 +- packages/excalidraw/components/Trans.tsx | 3 +- packages/excalidraw/components/UserList.tsx | 28 ++- .../components/canvases/InteractiveCanvas.tsx | 20 +- .../components/canvases/NewElementCanvas.tsx | 8 +- .../components/canvases/StaticCanvas.tsx | 16 +- .../dropdownMenu/DropdownMenu.test.tsx | 1 + .../components/dropdownMenu/DropdownMenu.tsx | 11 +- .../dropdownMenu/DropdownMenuContent.tsx | 14 +- .../dropdownMenu/DropdownMenuItem.tsx | 11 +- .../dropdownMenu/DropdownMenuItemContent.tsx | 3 +- .../dropdownMenu/DropdownMenuItemLink.tsx | 6 +- .../dropdownMenu/DropdownMenuTrigger.tsx | 1 + .../components/dropdownMenu/common.ts | 1 + .../excalidraw/components/footer/Footer.tsx | 6 +- .../components/footer/FooterCenter.tsx | 4 +- .../hoc/withInternalFallback.test.tsx | 3 +- .../components/hoc/withInternalFallback.tsx | 1 + .../components/hyperlink/Hyperlink.tsx | 60 ++--- .../components/hyperlink/helpers.ts | 9 +- packages/excalidraw/components/icons.tsx | 7 +- .../LiveCollaborationTrigger.tsx | 10 +- .../components/main-menu/DefaultItems.tsx | 45 ++-- .../components/main-menu/MainMenu.tsx | 18 +- .../welcome-screen/WelcomeScreen.Center.tsx | 9 +- .../welcome-screen/WelcomeScreen.Hints.tsx | 2 +- packages/excalidraw/constants.ts | 5 +- packages/excalidraw/context/tunnels.ts | 2 +- packages/excalidraw/context/ui-appState.ts | 1 + packages/excalidraw/cursor.ts | 6 +- packages/excalidraw/data/blob.ts | 11 +- packages/excalidraw/data/encode.ts | 1 + packages/excalidraw/data/encryption.ts | 1 + packages/excalidraw/data/filesystem.ts | 4 +- packages/excalidraw/data/image.ts | 6 +- packages/excalidraw/data/index.ts | 20 +- packages/excalidraw/data/json.ts | 7 +- packages/excalidraw/data/library.ts | 41 +-- packages/excalidraw/data/reconcile.ts | 6 +- packages/excalidraw/data/resave.ts | 6 +- packages/excalidraw/data/restore.ts | 104 ++++---- packages/excalidraw/data/transform.test.ts | 10 +- packages/excalidraw/data/transform.ts | 34 +-- packages/excalidraw/data/types.ts | 4 +- packages/excalidraw/data/url.ts | 1 + packages/excalidraw/distribute.ts | 3 +- .../element/ElementCanvasButtons.tsx | 11 +- packages/excalidraw/element/binding.ts | 123 ++++----- packages/excalidraw/element/bounds.test.ts | 6 +- packages/excalidraw/element/bounds.ts | 70 +++--- packages/excalidraw/element/collision.ts | 60 ++--- packages/excalidraw/element/cropElement.ts | 12 +- packages/excalidraw/element/distance.ts | 13 +- packages/excalidraw/element/dragElements.ts | 28 ++- .../excalidraw/element/elbowArrow.test.tsx | 18 +- packages/excalidraw/element/elbowArrow.ts | 11 +- packages/excalidraw/element/elementLink.ts | 1 + packages/excalidraw/element/embeddable.ts | 10 +- .../excalidraw/element/flowchart.test.tsx | 8 +- packages/excalidraw/element/flowchart.ts | 31 +-- packages/excalidraw/element/heading.ts | 17 +- packages/excalidraw/element/image.ts | 4 +- packages/excalidraw/element/index.ts | 5 +- .../excalidraw/element/linearElementEditor.ts | 90 +++---- packages/excalidraw/element/mutateElement.ts | 15 +- .../excalidraw/element/newElement.test.ts | 18 +- packages/excalidraw/element/newElement.ts | 54 ++-- packages/excalidraw/element/resizeElements.ts | 110 +++++---- packages/excalidraw/element/resizeTest.ts | 51 ++-- .../element/showSelectedShapeActions.ts | 3 +- .../excalidraw/element/sizeHelpers.test.ts | 4 +- packages/excalidraw/element/sizeHelpers.ts | 10 +- .../excalidraw/element/sortElements.test.ts | 2 + packages/excalidraw/element/sortElements.ts | 1 + .../excalidraw/element/textElement.test.ts | 2 + packages/excalidraw/element/textElement.ts | 41 +-- .../excalidraw/element/textMeasurements.ts | 1 + .../excalidraw/element/textWrapping.test.ts | 1 + packages/excalidraw/element/textWrapping.ts | 2 + .../excalidraw/element/textWysiwyg.test.tsx | 18 +- packages/excalidraw/element/textWysiwyg.tsx | 62 ++--- .../excalidraw/element/transformHandles.ts | 33 +-- .../excalidraw/element/typeChecks.test.ts | 1 + packages/excalidraw/element/typeChecks.ts | 3 +- packages/excalidraw/element/types.ts | 1 + packages/excalidraw/element/utils.ts | 8 +- packages/excalidraw/fonts/Cascadia/index.ts | 4 +- .../excalidraw/fonts/ComicShanns/index.ts | 10 +- packages/excalidraw/fonts/Emoji/index.ts | 1 - .../excalidraw/fonts/ExcalidrawFontFace.ts | 5 +- packages/excalidraw/fonts/Excalifont/index.ts | 16 +- packages/excalidraw/fonts/FontMetadata.ts | 3 +- packages/excalidraw/fonts/Fonts.ts | 6 +- packages/excalidraw/fonts/Helvetica/index.ts | 1 - packages/excalidraw/fonts/Liberation/index.ts | 4 +- packages/excalidraw/fonts/Lilita/index.ts | 7 +- packages/excalidraw/fonts/Nunito/index.ts | 13 +- packages/excalidraw/fonts/Virgil/index.ts | 4 +- packages/excalidraw/fonts/Xiaolai/index.ts | 40 +-- packages/excalidraw/fractionalIndex.ts | 10 +- packages/excalidraw/frame.test.tsx | 6 +- packages/excalidraw/frame.ts | 34 +-- packages/excalidraw/groups.ts | 7 +- packages/excalidraw/history.ts | 3 +- .../hooks/useCreatePortalContainer.ts | 1 + packages/excalidraw/hooks/useEmitter.ts | 1 + .../excalidraw/hooks/useLibraryItemSvg.ts | 4 +- packages/excalidraw/hooks/useOutsideClick.ts | 1 + .../excalidraw/hooks/useScrollPosition.ts | 5 +- packages/excalidraw/i18n.ts | 3 +- packages/excalidraw/index-node.ts | 5 +- packages/excalidraw/index.tsx | 19 +- packages/excalidraw/keys.ts | 1 + packages/excalidraw/laser-trails.ts | 10 +- packages/excalidraw/queue.ts | 3 +- packages/excalidraw/random.ts | 3 +- packages/excalidraw/reactUtils.ts | 3 +- packages/excalidraw/renderer/helpers.ts | 5 +- .../excalidraw/renderer/interactiveScene.ts | 100 ++++---- packages/excalidraw/renderer/renderElement.ts | 82 +++--- .../renderer/renderNewElementScene.ts | 4 +- packages/excalidraw/renderer/renderSnaps.ts | 2 + packages/excalidraw/renderer/staticScene.ts | 35 +-- .../excalidraw/renderer/staticSvgScene.ts | 22 +- packages/excalidraw/scene/Renderer.ts | 12 +- packages/excalidraw/scene/Scene.ts | 31 +-- packages/excalidraw/scene/Shape.ts | 39 +-- packages/excalidraw/scene/ShapeCache.ts | 13 +- packages/excalidraw/scene/export.ts | 44 ++-- packages/excalidraw/scene/normalize.ts | 2 + packages/excalidraw/scene/scroll.ts | 6 +- packages/excalidraw/scene/scrollbars.ts | 7 +- packages/excalidraw/scene/selection.ts | 17 +- packages/excalidraw/scene/types.ts | 6 +- packages/excalidraw/shapes.tsx | 10 +- packages/excalidraw/snapping.ts | 19 +- packages/excalidraw/store.ts | 5 +- .../subset/harfbuzz/harfbuzz-loader.ts | 2 +- packages/excalidraw/subset/subset-main.ts | 4 +- .../excalidraw/subset/subset-shared.chunk.ts | 2 +- .../excalidraw/subset/woff2/woff2-loader.ts | 2 +- packages/excalidraw/tests/App.test.tsx | 8 +- .../tests/MermaidToExcalidraw.test.tsx | 8 +- .../excalidraw/tests/actionStyles.test.tsx | 3 +- packages/excalidraw/tests/align.test.tsx | 14 +- packages/excalidraw/tests/appState.test.tsx | 9 +- packages/excalidraw/tests/binding.test.tsx | 20 +- packages/excalidraw/tests/clipboard.test.tsx | 23 +- .../excalidraw/tests/contextmenu.test.tsx | 21 +- .../excalidraw/tests/cropElement.test.tsx | 19 +- .../excalidraw/tests/data/reconcile.test.ts | 9 +- .../excalidraw/tests/data/restore.test.ts | 18 +- packages/excalidraw/tests/dragCreate.test.tsx | 11 +- .../excalidraw/tests/elementLocking.test.tsx | 11 +- packages/excalidraw/tests/excalidraw.test.tsx | 10 +- packages/excalidraw/tests/export.test.tsx | 15 +- .../excalidraw/tests/fitToContent.test.tsx | 7 +- .../tests/fixtures/diagramFixture.ts | 1 + .../tests/fixtures/elementFixture.ts | 2 + packages/excalidraw/tests/flip.test.tsx | 32 +-- .../excalidraw/tests/fractionalIndex.test.ts | 11 +- packages/excalidraw/tests/helpers/api.ts | 55 +++-- packages/excalidraw/tests/helpers/mocks.ts | 5 +- packages/excalidraw/tests/helpers/ui.ts | 56 +++-- packages/excalidraw/tests/history.test.tsx | 69 +++--- packages/excalidraw/tests/library.test.tsx | 18 +- .../tests/linearElementEditor.test.tsx | 47 ++-- packages/excalidraw/tests/move.test.tsx | 19 +- .../tests/multiPointCreate.test.tsx | 15 +- .../excalidraw/tests/packages/events.test.tsx | 8 +- .../excalidraw/tests/queries/toolQueries.ts | 4 +- .../excalidraw/tests/regressionTests.test.tsx | 11 +- packages/excalidraw/tests/resize.test.tsx | 30 ++- packages/excalidraw/tests/rotate.test.tsx | 10 +- .../excalidraw/tests/scene/export.test.ts | 18 +- packages/excalidraw/tests/scroll.test.tsx | 10 +- packages/excalidraw/tests/search.test.tsx | 11 +- packages/excalidraw/tests/selection.test.tsx | 20 +- packages/excalidraw/tests/shortcuts.test.tsx | 4 +- packages/excalidraw/tests/test-utils.ts | 20 +- packages/excalidraw/tests/tool.test.tsx | 7 +- packages/excalidraw/tests/viewMode.test.tsx | 8 +- packages/excalidraw/tests/zindex.test.tsx | 13 +- packages/excalidraw/types.ts | 38 +-- packages/excalidraw/utils.ts | 6 +- packages/excalidraw/visualdebug.ts | 7 +- packages/excalidraw/zindex.ts | 11 +- packages/math/angle.ts | 3 +- packages/math/curve.test.ts | 1 + packages/math/curve.ts | 3 +- packages/math/ellipse.test.ts | 1 + packages/math/ellipse.ts | 15 +- packages/math/line.ts | 1 + packages/math/point.test.ts | 1 + packages/math/point.ts | 5 +- packages/math/polygon.ts | 3 +- packages/math/range.ts | 1 + packages/math/rectangle.ts | 1 + packages/math/segment.ts | 3 +- packages/utils/bbox.ts | 1 + packages/utils/collision.test.ts | 5 +- packages/utils/collision.ts | 17 +- packages/utils/export.test.ts | 6 +- packages/utils/export.ts | 29 +-- packages/utils/geometry/geometry.test.ts | 14 +- packages/utils/geometry/shape.ts | 10 +- packages/utils/utils.unmocked.test.ts | 10 +- packages/utils/withinBounds.test.ts | 4 +- packages/utils/withinBounds.ts | 19 +- scripts/autorelease.js | 3 +- scripts/buildMath.js | 1 + scripts/buildPackage.js | 2 + scripts/buildUtils.js | 2 + scripts/prerelease.js | 1 + scripts/woff2/woff2-esbuild-plugins.js | 7 +- setupTests.ts | 6 +- yarn.lock | 2 +- 421 files changed, 3532 insertions(+), 2763 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 095543a85..8263b08a9 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,6 +1,21 @@ { "extends": ["@excalidraw/eslint-config", "react-app"], "rules": { + "import/order": [ + "warn", + { + "groups": ["builtin", "external", "internal", "parent", "sibling", "index", "object", "type"], + "pathGroups": [ + { + "pattern": "@excalidraw/**", + "group": "external", + "position": "after" + } + ], + "newlines-between": "always-and-inside-groups", + "warnOnUnassignedImports": true + } + ], "import/no-anonymous-default-export": "off", "no-restricted-globals": "off", "@typescript-eslint/consistent-type-imports": [ diff --git a/dev-docs/src/components/Homepage/index.js b/dev-docs/src/components/Homepage/index.js index e350e03a2..3c1c25f4f 100644 --- a/dev-docs/src/components/Homepage/index.js +++ b/dev-docs/src/components/Homepage/index.js @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import styles from "./styles.module.css"; const FeatureList = [ diff --git a/dev-docs/src/components/Homepage/index.tsx b/dev-docs/src/components/Homepage/index.tsx index ee86e9195..613eaa556 100644 --- a/dev-docs/src/components/Homepage/index.tsx +++ b/dev-docs/src/components/Homepage/index.tsx @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import styles from "./styles.module.css"; type FeatureItem = { diff --git a/dev-docs/src/pages/index.tsx b/dev-docs/src/pages/index.tsx index f35c2e4a7..39b66bb79 100644 --- a/dev-docs/src/pages/index.tsx +++ b/dev-docs/src/pages/index.tsx @@ -1,10 +1,11 @@ -import React from "react"; -import clsx from "clsx"; -import Layout from "@theme/Layout"; import Link from "@docusaurus/Link"; import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import styles from "./index.module.css"; import HomepageFeatures from "@site/src/components/Homepage"; +import Layout from "@theme/Layout"; +import clsx from "clsx"; +import React from "react"; + +import styles from "./index.module.css"; function HomepageHeader() { const { siteConfig } = useDocusaurusContext(); diff --git a/dev-docs/src/theme/MDXComponents.js b/dev-docs/src/theme/MDXComponents.js index 35234301f..97ff4d054 100644 --- a/dev-docs/src/theme/MDXComponents.js +++ b/dev-docs/src/theme/MDXComponents.js @@ -1,6 +1,6 @@ // Import the original mapper -import MDXComponents from "@theme-original/MDXComponents"; import Highlight from "@site/src/components/Highlight"; +import MDXComponents from "@theme-original/MDXComponents"; export default { // Re-use the default mapping diff --git a/examples/with-nextjs/src/app/page.tsx b/examples/with-nextjs/src/app/page.tsx index 191aca120..e23255237 100644 --- a/examples/with-nextjs/src/app/page.tsx +++ b/examples/with-nextjs/src/app/page.tsx @@ -1,5 +1,6 @@ import dynamic from "next/dynamic"; import Script from "next/script"; + import "../common.scss"; // Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically diff --git a/examples/with-nextjs/src/excalidrawWrapper.tsx b/examples/with-nextjs/src/excalidrawWrapper.tsx index b4c45fa7d..fab4df651 100644 --- a/examples/with-nextjs/src/excalidrawWrapper.tsx +++ b/examples/with-nextjs/src/excalidrawWrapper.tsx @@ -1,10 +1,11 @@ "use client"; import * as excalidrawLib from "@excalidraw/excalidraw"; import { Excalidraw } from "@excalidraw/excalidraw"; -import App from "../../with-script-in-browser/components/ExampleApp"; import "@excalidraw/excalidraw/index.css"; +import App from "../../with-script-in-browser/components/ExampleApp"; + const ExcalidrawWrapper: React.FC = () => { return ( <> diff --git a/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx b/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx index 527a346b9..116bb96ce 100644 --- a/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx +++ b/examples/with-nextjs/src/pages/excalidraw-in-pages.tsx @@ -1,4 +1,5 @@ import dynamic from "next/dynamic"; + import "../common.scss"; // Since client components get prerenderd on server as well hence importing the excalidraw stuff dynamically diff --git a/examples/with-script-in-browser/components/CustomFooter.tsx b/examples/with-script-in-browser/components/CustomFooter.tsx index 72fd199f6..a9c902ade 100644 --- a/examples/with-script-in-browser/components/CustomFooter.tsx +++ b/examples/with-script-in-browser/components/CustomFooter.tsx @@ -1,4 +1,5 @@ import React from "react"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; diff --git a/examples/with-script-in-browser/components/ExampleApp.tsx b/examples/with-script-in-browser/components/ExampleApp.tsx index 08c8032d5..976004f04 100644 --- a/examples/with-script-in-browser/components/ExampleApp.tsx +++ b/examples/with-script-in-browser/components/ExampleApp.tsx @@ -1,3 +1,4 @@ +import { nanoid } from "nanoid"; import React, { useEffect, useState, @@ -6,13 +7,24 @@ import React, { Children, cloneElement, } from "react"; -import ExampleSidebar from "./sidebar/ExampleSidebar"; import type * as TExcalidraw from "@excalidraw/excalidraw"; +import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types"; +import type { + NonDeletedExcalidrawElement, + Theme, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + BinaryFileData, + ExcalidrawImperativeAPI, + ExcalidrawInitialDataState, + Gesture, + LibraryItems, + PointerDownState as ExcalidrawPointerDownState, +} from "@excalidraw/excalidraw/types"; -import { nanoid } from "nanoid"; - -import type { ResolvablePromise } from "../utils"; +import initialData from "../initialData"; import { resolvablePromise, distance2d, @@ -23,25 +35,12 @@ import { import CustomFooter from "./CustomFooter"; import MobileFooter from "./MobileFooter"; -import initialData from "../initialData"; - -import type { - AppState, - BinaryFileData, - ExcalidrawImperativeAPI, - ExcalidrawInitialDataState, - Gesture, - LibraryItems, - PointerDownState as ExcalidrawPointerDownState, -} from "@excalidraw/excalidraw/types"; -import type { - NonDeletedExcalidrawElement, - Theme, -} from "@excalidraw/excalidraw/element/types"; -import type { ImportedLibraryData } from "@excalidraw/excalidraw/data/types"; +import ExampleSidebar from "./sidebar/ExampleSidebar"; import "./ExampleApp.scss"; +import type { ResolvablePromise } from "../utils"; + type Comment = { x: number; y: number; diff --git a/examples/with-script-in-browser/components/MobileFooter.tsx b/examples/with-script-in-browser/components/MobileFooter.tsx index c8fc0f113..a6e1fa1b2 100644 --- a/examples/with-script-in-browser/components/MobileFooter.tsx +++ b/examples/with-script-in-browser/components/MobileFooter.tsx @@ -1,7 +1,9 @@ import React from "react"; -import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; -import CustomFooter from "./CustomFooter"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; +import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; + +import CustomFooter from "./CustomFooter"; const MobileFooter = ({ excalidrawAPI, diff --git a/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx b/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx index 193913410..88950b34b 100644 --- a/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx +++ b/examples/with-script-in-browser/components/sidebar/ExampleSidebar.tsx @@ -1,4 +1,5 @@ import React, { useState } from "react"; + import "./ExampleSidebar.scss"; export default function Sidebar({ children }: { children: React.ReactNode }) { diff --git a/examples/with-script-in-browser/index.tsx b/examples/with-script-in-browser/index.tsx index 25ad96e37..8f92e7cc5 100644 --- a/examples/with-script-in-browser/index.tsx +++ b/examples/with-script-in-browser/index.tsx @@ -1,10 +1,11 @@ -import App from "./components/ExampleApp"; import React, { StrictMode } from "react"; import { createRoot } from "react-dom/client"; +import "@excalidraw/excalidraw/index.css"; + import type * as TExcalidraw from "@excalidraw/excalidraw"; -import "@excalidraw/excalidraw/index.css"; +import App from "./components/ExampleApp"; declare global { interface Window { diff --git a/examples/with-script-in-browser/utils.ts b/examples/with-script-in-browser/utils.ts index a77b93fb0..285e9652d 100644 --- a/examples/with-script-in-browser/utils.ts +++ b/examples/with-script-in-browser/utils.ts @@ -1,6 +1,6 @@ -import { unstable_batchedUpdates } from "react-dom"; -import { fileOpen as _fileOpen } from "browser-fs-access"; import { MIME_TYPES } from "@excalidraw/excalidraw"; +import { fileOpen as _fileOpen } from "browser-fs-access"; +import { unstable_batchedUpdates } from "react-dom"; type FILE_EXTENSION = Exclude; diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx index 2cb6e7715..dc399a7d0 100644 --- a/excalidraw-app/App.tsx +++ b/excalidraw-app/App.tsx @@ -1,24 +1,3 @@ -import polyfill from "@excalidraw/excalidraw/polyfill"; -import { useCallback, useEffect, useRef, useState } from "react"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; -import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; -import { TopErrorBoundary } from "./components/TopErrorBoundary"; -import { - APP_NAME, - EVENT, - THEME, - TITLE_TIMEOUT, - VERSION_TIMEOUT, -} from "@excalidraw/excalidraw/constants"; -import { loadFromBlob } from "@excalidraw/excalidraw/data/blob"; -import type { - FileId, - NonDeletedExcalidrawElement, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; -import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState"; -import { t } from "@excalidraw/excalidraw/i18n"; import { Excalidraw, LiveCollaborationTrigger, @@ -26,14 +5,29 @@ import { CaptureUpdateAction, reconcileElements, } from "@excalidraw/excalidraw"; -import type { - AppState, - ExcalidrawImperativeAPI, - BinaryFiles, - ExcalidrawInitialDataState, - UIAppState, -} from "@excalidraw/excalidraw/types"; -import type { ResolvablePromise } from "@excalidraw/excalidraw/utils"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; +import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; +import { + CommandPalette, + DEFAULT_CATEGORIES, +} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette"; +import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; +import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm"; +import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState"; +import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog"; +import Trans from "@excalidraw/excalidraw/components/Trans"; +import { + APP_NAME, + EVENT, + THEME, + TITLE_TIMEOUT, + VERSION_TIMEOUT, +} from "@excalidraw/excalidraw/constants"; +import polyfill from "@excalidraw/excalidraw/polyfill"; +import { useCallback, useEffect, useRef, useState } from "react"; +import { loadFromBlob } from "@excalidraw/excalidraw/data/blob"; +import { useCallbackRefState } from "@excalidraw/excalidraw/hooks/useCallbackRefState"; +import { t } from "@excalidraw/excalidraw/i18n"; import { debounce, getVersion, @@ -43,74 +37,6 @@ import { resolvablePromise, isRunningInIframe, } from "@excalidraw/excalidraw/utils"; -import { - FIREBASE_STORAGE_PREFIXES, - isExcalidrawPlusSignedUser, - STORAGE_KEYS, - SYNC_BROWSER_TABS_TIMEOUT, -} from "./app_constants"; -import type { CollabAPI } from "./collab/Collab"; -import Collab, { - collabAPIAtom, - isCollaboratingAtom, - isOfflineAtom, -} from "./collab/Collab"; -import { - exportToBackend, - getCollaborationLinkData, - isCollaborationLink, - loadScene, -} from "./data"; -import { - importFromLocalStorage, - importUsernameFromLocalStorage, -} from "./data/localStorage"; -import CustomStats from "./CustomStats"; -import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore"; -import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore"; -import { - ExportToExcalidrawPlus, - exportToExcalidrawPlus, -} from "./components/ExportToExcalidrawPlus"; -import { updateStaleImageStatuses } from "./data/FileManager"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; -import { loadFilesFromFirebase } from "./data/firebase"; -import { - LibraryIndexedDBAdapter, - LibraryLocalStorageMigrationAdapter, - LocalData, -} from "./data/LocalData"; -import { isBrowserStorageStateNewer } from "./data/tabSync"; -import clsx from "clsx"; -import { - parseLibraryTokensFromUrl, - useHandleLibrary, -} from "@excalidraw/excalidraw/data/library"; -import { AppMainMenu } from "./components/AppMainMenu"; -import { AppWelcomeScreen } from "./components/AppWelcomeScreen"; -import { AppFooter } from "./components/AppFooter"; -import { - Provider, - useAtom, - useAtomValue, - useAtomWithInitialValue, - appJotaiStore, -} from "./app-jotai"; - -import "./index.scss"; -import type { ResolutionType } from "@excalidraw/excalidraw/utility-types"; -import { ShareableLinkDialog } from "@excalidraw/excalidraw/components/ShareableLinkDialog"; -import { openConfirmModal } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirmState"; -import { OverwriteConfirmDialog } from "@excalidraw/excalidraw/components/OverwriteConfirm/OverwriteConfirm"; -import Trans from "@excalidraw/excalidraw/components/Trans"; -import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog"; -import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError"; -import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; -import { - CommandPalette, - DEFAULT_CATEGORIES, -} from "@excalidraw/excalidraw/components/CommandPalette/CommandPalette"; import { GithubIcon, XBrandIcon, @@ -121,6 +47,83 @@ import { share, youtubeIcon, } from "@excalidraw/excalidraw/components/icons"; +import { isElementLink } from "@excalidraw/excalidraw/element/elementLink"; +import { restore, restoreAppState } from "@excalidraw/excalidraw/data/restore"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import clsx from "clsx"; +import { + parseLibraryTokensFromUrl, + useHandleLibrary, +} from "@excalidraw/excalidraw/data/library"; + +import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; +import type { RestoredDataState } from "@excalidraw/excalidraw/data/restore"; +import type { + FileId, + NonDeletedExcalidrawElement, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + ExcalidrawImperativeAPI, + BinaryFiles, + ExcalidrawInitialDataState, + UIAppState, +} from "@excalidraw/excalidraw/types"; +import type { ResolutionType } from "@excalidraw/excalidraw/utility-types"; +import type { ResolvablePromise } from "@excalidraw/excalidraw/utils"; + +import CustomStats from "./CustomStats"; +import { + Provider, + useAtom, + useAtomValue, + useAtomWithInitialValue, + appJotaiStore, +} from "./app-jotai"; +import { + FIREBASE_STORAGE_PREFIXES, + isExcalidrawPlusSignedUser, + STORAGE_KEYS, + SYNC_BROWSER_TABS_TIMEOUT, +} from "./app_constants"; +import Collab, { + collabAPIAtom, + isCollaboratingAtom, + isOfflineAtom, +} from "./collab/Collab"; +import { AppFooter } from "./components/AppFooter"; +import { AppMainMenu } from "./components/AppMainMenu"; +import { AppWelcomeScreen } from "./components/AppWelcomeScreen"; +import { + ExportToExcalidrawPlus, + exportToExcalidrawPlus, +} from "./components/ExportToExcalidrawPlus"; +import { TopErrorBoundary } from "./components/TopErrorBoundary"; + +import { + exportToBackend, + getCollaborationLinkData, + isCollaborationLink, + loadScene, +} from "./data"; + +import { updateStaleImageStatuses } from "./data/FileManager"; +import { + importFromLocalStorage, + importUsernameFromLocalStorage, +} from "./data/localStorage"; + +import { loadFilesFromFirebase } from "./data/firebase"; +import { + LibraryIndexedDBAdapter, + LibraryLocalStorageMigrationAdapter, + LocalData, +} from "./data/LocalData"; +import { isBrowserStorageStateNewer } from "./data/tabSync"; +import { ShareDialog, shareDialogStateAtom } from "./share/ShareDialog"; +import CollabError, { collabErrorIndicatorAtom } from "./collab/CollabError"; import { useHandleAppTheme } from "./useHandleAppTheme"; import { getPreferredLanguage } from "./app-language/language-detector"; import { useAppLangCode } from "./app-language/language-state"; @@ -131,7 +134,10 @@ import DebugCanvas, { } from "./components/DebugCanvas"; import { AIComponents } from "./components/AI"; import { ExcalidrawPlusIframeExport } from "./ExcalidrawPlusIframeExport"; -import { isElementLink } from "@excalidraw/excalidraw/element/elementLink"; + +import "./index.scss"; + +import type { CollabAPI } from "./collab/Collab"; polyfill(); diff --git a/excalidraw-app/CustomStats.tsx b/excalidraw-app/CustomStats.tsx index 96ca55d67..c57f297fe 100644 --- a/excalidraw-app/CustomStats.tsx +++ b/excalidraw-app/CustomStats.tsx @@ -1,15 +1,17 @@ -import { useEffect, useState } from "react"; +import { Stats } from "@excalidraw/excalidraw"; +import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; +import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants"; +import { t } from "@excalidraw/excalidraw/i18n"; import { debounce, getVersion, nFormatter } from "@excalidraw/excalidraw/utils"; +import { useEffect, useState } from "react"; + +import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { UIAppState } from "@excalidraw/excalidraw/types"; + import { getElementsStorageSize, getTotalStorageSize, } from "./data/localStorage"; -import { DEFAULT_VERSION } from "@excalidraw/excalidraw/constants"; -import { t } from "@excalidraw/excalidraw/i18n"; -import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; -import type { NonDeletedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import type { UIAppState } from "@excalidraw/excalidraw/types"; -import { Stats } from "@excalidraw/excalidraw"; type StorageSizes = { scene: number; total: number }; diff --git a/excalidraw-app/ExcalidrawPlusIframeExport.tsx b/excalidraw-app/ExcalidrawPlusIframeExport.tsx index 1f9cd631c..be046f795 100644 --- a/excalidraw-app/ExcalidrawPlusIframeExport.tsx +++ b/excalidraw-app/ExcalidrawPlusIframeExport.tsx @@ -1,13 +1,15 @@ +import { base64urlToString } from "@excalidraw/excalidraw/data/encode"; +import { ExcalidrawError } from "@excalidraw/excalidraw/errors"; import { useLayoutEffect, useRef } from "react"; -import { STORAGE_KEYS } from "./app_constants"; -import { LocalData } from "./data/LocalData"; + import type { FileId, OrderedExcalidrawElement, } from "@excalidraw/excalidraw/element/types"; import type { AppState, BinaryFileData } from "@excalidraw/excalidraw/types"; -import { ExcalidrawError } from "@excalidraw/excalidraw/errors"; -import { base64urlToString } from "@excalidraw/excalidraw/data/encode"; + +import { STORAGE_KEYS } from "./app_constants"; +import { LocalData } from "./data/LocalData"; const EVENT_REQUEST_SCENE = "REQUEST_SCENE"; diff --git a/excalidraw-app/app-language/LanguageList.tsx b/excalidraw-app/app-language/LanguageList.tsx index 001d4ea17..b4682f353 100644 --- a/excalidraw-app/app-language/LanguageList.tsx +++ b/excalidraw-app/app-language/LanguageList.tsx @@ -1,6 +1,8 @@ -import React from "react"; import { useI18n, languages } from "@excalidraw/excalidraw/i18n"; +import React from "react"; + import { useSetAtom } from "../app-jotai"; + import { appLangCodeAtom } from "./language-state"; export const LanguageList = ({ style }: { style?: React.CSSProperties }) => { diff --git a/excalidraw-app/app-language/language-detector.ts b/excalidraw-app/app-language/language-detector.ts index 52da4908f..535189d0a 100644 --- a/excalidraw-app/app-language/language-detector.ts +++ b/excalidraw-app/app-language/language-detector.ts @@ -1,5 +1,5 @@ -import LanguageDetector from "i18next-browser-languagedetector"; import { defaultLang, languages } from "@excalidraw/excalidraw"; +import LanguageDetector from "i18next-browser-languagedetector"; export const languageDetector = new LanguageDetector(); diff --git a/excalidraw-app/app-language/language-state.ts b/excalidraw-app/app-language/language-state.ts index f491c2215..d9ec90322 100644 --- a/excalidraw-app/app-language/language-state.ts +++ b/excalidraw-app/app-language/language-state.ts @@ -1,5 +1,7 @@ import { useEffect } from "react"; + import { atom, useAtom } from "../app-jotai"; + import { getPreferredLanguage, languageDetector } from "./language-detector"; export const appLangCodeAtom = atom(getPreferredLanguage()); diff --git a/excalidraw-app/collab/Collab.tsx b/excalidraw-app/collab/Collab.tsx index 9a16e0569..0964a7365 100644 --- a/excalidraw-app/collab/Collab.tsx +++ b/excalidraw-app/collab/Collab.tsx @@ -1,21 +1,3 @@ -import throttle from "lodash.throttle"; -import { PureComponent } from "react"; -import type { - BinaryFileData, - ExcalidrawImperativeAPI, - SocketId, - Collaborator, - Gesture, -} from "@excalidraw/excalidraw/types"; -import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; -import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants"; -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import type { - ExcalidrawElement, - FileId, - InitializedExcalidrawImageElement, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; import { CaptureUpdateAction, getSceneVersion, @@ -23,12 +5,53 @@ import { zoomToFitBounds, reconcileElements, } from "@excalidraw/excalidraw"; +import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; +import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants"; +import { + IDLE_THRESHOLD, + ACTIVE_THRESHOLD, + UserIdleState, +} from "@excalidraw/excalidraw/constants"; +import { decryptData } from "@excalidraw/excalidraw/data/encryption"; +import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import { + isImageElement, + isInitializedImageElement, +} from "@excalidraw/excalidraw/element/typeChecks"; +import { AbortError } from "@excalidraw/excalidraw/errors"; +import { t } from "@excalidraw/excalidraw/i18n"; +import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils"; import { assertNever, preventUnload, resolvablePromise, throttleRAF, } from "@excalidraw/excalidraw/utils"; +import throttle from "lodash.throttle"; +import { PureComponent } from "react"; + +import type { + ReconciledExcalidrawElement, + RemoteExcalidrawElement, +} from "@excalidraw/excalidraw/data/reconcile"; +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; +import type { + ExcalidrawElement, + FileId, + InitializedExcalidrawImageElement, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + BinaryFileData, + ExcalidrawImperativeAPI, + SocketId, + Collaborator, + Gesture, +} from "@excalidraw/excalidraw/types"; +import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types"; + +import { appJotaiStore, atom } from "../app-jotai"; import { CURSOR_SYNC_TIMEOUT, FILE_UPLOAD_MAX_BYTES, @@ -39,15 +62,17 @@ import { SYNC_FULL_SCENE_INTERVAL_MS, WS_EVENTS, } from "../app_constants"; -import type { - SocketUpdateDataSource, - SyncableExcalidrawElement, -} from "../data"; import { generateCollaborationLinkData, getCollaborationLink, getSyncableElements, } from "../data"; +import { + encodeFilesForUpload, + FileManager, + updateStaleImageStatuses, +} from "../data/FileManager"; +import { LocalData } from "../data/LocalData"; import { isSavedToFirebase, loadFilesFromFirebase, @@ -59,36 +84,15 @@ import { importUsernameFromLocalStorage, saveUsernameToLocalStorage, } from "../data/localStorage"; -import Portal from "./Portal"; -import { t } from "@excalidraw/excalidraw/i18n"; -import { - IDLE_THRESHOLD, - ACTIVE_THRESHOLD, - UserIdleState, -} from "@excalidraw/excalidraw/constants"; -import { - encodeFilesForUpload, - FileManager, - updateStaleImageStatuses, -} from "../data/FileManager"; -import { AbortError } from "@excalidraw/excalidraw/errors"; -import { - isImageElement, - isInitializedImageElement, -} from "@excalidraw/excalidraw/element/typeChecks"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { decryptData } from "@excalidraw/excalidraw/data/encryption"; import { resetBrowserStateVersions } from "../data/tabSync"; -import { LocalData } from "../data/LocalData"; -import { appJotaiStore, atom } from "../app-jotai"; -import type { Mutable, ValueOf } from "@excalidraw/excalidraw/utility-types"; -import { getVisibleSceneBounds } from "@excalidraw/excalidraw/element/bounds"; -import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils"; + import { collabErrorIndicatorAtom } from "./CollabError"; +import Portal from "./Portal"; + import type { - ReconciledExcalidrawElement, - RemoteExcalidrawElement, -} from "@excalidraw/excalidraw/data/reconcile"; + SocketUpdateDataSource, + SyncableExcalidrawElement, +} from "../data"; export const collabAPIAtom = atom(null); export const isCollaboratingAtom = atom(false); diff --git a/excalidraw-app/collab/CollabError.tsx b/excalidraw-app/collab/CollabError.tsx index 76828cf1a..eb6f391bc 100644 --- a/excalidraw-app/collab/CollabError.tsx +++ b/excalidraw-app/collab/CollabError.tsx @@ -2,6 +2,7 @@ import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip"; import { warning } from "@excalidraw/excalidraw/components/icons"; import clsx from "clsx"; import { useEffect, useRef, useState } from "react"; + import { atom } from "../app-jotai"; import "./CollabError.scss"; diff --git a/excalidraw-app/collab/Portal.tsx b/excalidraw-app/collab/Portal.tsx index 1788d39f7..037bca314 100644 --- a/excalidraw-app/collab/Portal.tsx +++ b/excalidraw-app/collab/Portal.tsx @@ -1,25 +1,26 @@ +import { CaptureUpdateAction } from "@excalidraw/excalidraw"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; +import { encryptData } from "@excalidraw/excalidraw/data/encryption"; +import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; +import throttle from "lodash.throttle"; + +import type { UserIdleState } from "@excalidraw/excalidraw/constants"; +import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { + OnUserFollowedPayload, + SocketId, +} from "@excalidraw/excalidraw/types"; + +import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants"; +import { isSyncableElement } from "../data"; + import type { SocketUpdateData, SocketUpdateDataSource, SyncableExcalidrawElement, } from "../data"; -import { isSyncableElement } from "../data"; - import type { TCollabClass } from "./Collab"; - -import type { OrderedExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import { WS_EVENTS, FILE_UPLOAD_TIMEOUT, WS_SUBTYPES } from "../app_constants"; -import type { - OnUserFollowedPayload, - SocketId, -} from "@excalidraw/excalidraw/types"; -import type { UserIdleState } from "@excalidraw/excalidraw/constants"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import throttle from "lodash.throttle"; -import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; -import { encryptData } from "@excalidraw/excalidraw/data/encryption"; import type { Socket } from "socket.io-client"; -import { CaptureUpdateAction } from "@excalidraw/excalidraw"; class Portal { collab: TCollabClass; diff --git a/excalidraw-app/components/AI.tsx b/excalidraw-app/components/AI.tsx index fa5d12fa2..c9b6684b3 100644 --- a/excalidraw-app/components/AI.tsx +++ b/excalidraw-app/components/AI.tsx @@ -1,4 +1,3 @@ -import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; import { DiagramToCodePlugin, exportToBlob, @@ -9,6 +8,8 @@ import { import { getDataURL } from "@excalidraw/excalidraw/data/blob"; import { safelyParseJSON } from "@excalidraw/excalidraw/utils"; +import type { ExcalidrawImperativeAPI } from "@excalidraw/excalidraw/types"; + export const AIComponents = ({ excalidrawAPI, }: { diff --git a/excalidraw-app/components/AppFooter.tsx b/excalidraw-app/components/AppFooter.tsx index e81df7c41..7d42d46bf 100644 --- a/excalidraw-app/components/AppFooter.tsx +++ b/excalidraw-app/components/AppFooter.tsx @@ -1,9 +1,11 @@ -import React from "react"; import { Footer } from "@excalidraw/excalidraw/index"; +import React from "react"; + +import { isExcalidrawPlusSignedUser } from "../app_constants"; + +import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas"; import { EncryptedIcon } from "./EncryptedIcon"; import { ExcalidrawPlusAppLink } from "./ExcalidrawPlusAppLink"; -import { isExcalidrawPlusSignedUser } from "../app_constants"; -import { DebugFooter, isVisualDebuggerEnabled } from "./DebugCanvas"; export const AppFooter = React.memo( ({ onChange }: { onChange: () => void }) => { diff --git a/excalidraw-app/components/AppMainMenu.tsx b/excalidraw-app/components/AppMainMenu.tsx index cb741cf25..996d6912d 100644 --- a/excalidraw-app/components/AppMainMenu.tsx +++ b/excalidraw-app/components/AppMainMenu.tsx @@ -1,13 +1,16 @@ -import React from "react"; import { loginIcon, ExcalLogo, eyeIcon, } from "@excalidraw/excalidraw/components/icons"; -import type { Theme } from "@excalidraw/excalidraw/element/types"; import { MainMenu } from "@excalidraw/excalidraw/index"; -import { isExcalidrawPlusSignedUser } from "../app_constants"; +import React from "react"; + +import type { Theme } from "@excalidraw/excalidraw/element/types"; + import { LanguageList } from "../app-language/LanguageList"; +import { isExcalidrawPlusSignedUser } from "../app_constants"; + import { saveDebugState } from "./DebugCanvas"; export const AppMainMenu: React.FC<{ diff --git a/excalidraw-app/components/AppWelcomeScreen.tsx b/excalidraw-app/components/AppWelcomeScreen.tsx index bdc9859f8..c33de092a 100644 --- a/excalidraw-app/components/AppWelcomeScreen.tsx +++ b/excalidraw-app/components/AppWelcomeScreen.tsx @@ -1,9 +1,10 @@ -import React from "react"; import { loginIcon } from "@excalidraw/excalidraw/components/icons"; +import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants"; import { useI18n } from "@excalidraw/excalidraw/i18n"; import { WelcomeScreen } from "@excalidraw/excalidraw/index"; +import React from "react"; + import { isExcalidrawPlusSignedUser } from "../app_constants"; -import { POINTER_EVENTS } from "@excalidraw/excalidraw/constants"; export const AppWelcomeScreen: React.FC<{ onCollabDialogOpen: () => any; diff --git a/excalidraw-app/components/DebugCanvas.tsx b/excalidraw-app/components/DebugCanvas.tsx index 31898ba57..af1a2b140 100644 --- a/excalidraw-app/components/DebugCanvas.tsx +++ b/excalidraw-app/components/DebugCanvas.tsx @@ -1,24 +1,27 @@ -import { useCallback, useImperativeHandle, useRef } from "react"; -import { type AppState } from "@excalidraw/excalidraw/types"; -import { throttleRAF } from "@excalidraw/excalidraw/utils"; -import { - bootstrapCanvas, - getNormalizedCanvasDimensions, -} from "@excalidraw/excalidraw/renderer/helpers"; -import type { DebugElement } from "@excalidraw/excalidraw/visualdebug"; import { ArrowheadArrowIcon, CloseIcon, TrashIcon, } from "@excalidraw/excalidraw/components/icons"; -import { STORAGE_KEYS } from "../app_constants"; -import type { Curve } from "../../packages/math"; +import { + bootstrapCanvas, + getNormalizedCanvasDimensions, +} from "@excalidraw/excalidraw/renderer/helpers"; +import { type AppState } from "@excalidraw/excalidraw/types"; +import { throttleRAF } from "@excalidraw/excalidraw/utils"; +import { useCallback, useImperativeHandle, useRef } from "react"; + +import type { DebugElement } from "@excalidraw/excalidraw/visualdebug"; + import { isLineSegment, type GlobalPoint, type LineSegment, } from "../../packages/math"; import { isCurve } from "../../packages/math/curve"; +import { STORAGE_KEYS } from "../app_constants"; + +import type { Curve } from "../../packages/math"; const renderLine = ( context: CanvasRenderingContext2D, diff --git a/excalidraw-app/components/EncryptedIcon.tsx b/excalidraw-app/components/EncryptedIcon.tsx index a3a841783..552e7ca82 100644 --- a/excalidraw-app/components/EncryptedIcon.tsx +++ b/excalidraw-app/components/EncryptedIcon.tsx @@ -1,5 +1,5 @@ -import { shield } from "@excalidraw/excalidraw/components/icons"; import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip"; +import { shield } from "@excalidraw/excalidraw/components/icons"; import { useI18n } from "@excalidraw/excalidraw/i18n"; export const EncryptedIcon = () => { diff --git a/excalidraw-app/components/ExportToExcalidrawPlus.tsx b/excalidraw-app/components/ExportToExcalidrawPlus.tsx index 782ecd963..a630f804f 100644 --- a/excalidraw-app/components/ExportToExcalidrawPlus.tsx +++ b/excalidraw-app/components/ExportToExcalidrawPlus.tsx @@ -1,8 +1,20 @@ -import React from "react"; +import { trackEvent } from "@excalidraw/excalidraw/analytics"; import { Card } from "@excalidraw/excalidraw/components/Card"; +import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo"; import { ToolButton } from "@excalidraw/excalidraw/components/ToolButton"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import { + encryptData, + generateEncryptionKey, +} from "@excalidraw/excalidraw/data/encryption"; import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; -import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase"; +import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { useI18n } from "@excalidraw/excalidraw/i18n"; +import { getFrame } from "@excalidraw/excalidraw/utils"; +import { uploadBytes, ref } from "firebase/storage"; +import { nanoid } from "nanoid"; +import React from "react"; + import type { FileId, NonDeletedExcalidrawElement, @@ -12,20 +24,10 @@ import type { BinaryFileData, BinaryFiles, } from "@excalidraw/excalidraw/types"; -import { nanoid } from "nanoid"; -import { useI18n } from "@excalidraw/excalidraw/i18n"; -import { - encryptData, - generateEncryptionKey, -} from "@excalidraw/excalidraw/data/encryption"; -import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; + import { FILE_UPLOAD_MAX_BYTES } from "../app_constants"; import { encodeFilesForUpload } from "../data/FileManager"; -import { uploadBytes, ref } from "firebase/storage"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getFrame } from "@excalidraw/excalidraw/utils"; -import { ExcalidrawLogo } from "@excalidraw/excalidraw/components/ExcalidrawLogo"; +import { loadFirebaseStorage, saveFilesToFirebase } from "../data/firebase"; export const exportToExcalidrawPlus = async ( elements: readonly NonDeletedExcalidrawElement[], diff --git a/excalidraw-app/components/GitHubCorner.tsx b/excalidraw-app/components/GitHubCorner.tsx index 4d74242d1..b1c17f29e 100644 --- a/excalidraw-app/components/GitHubCorner.tsx +++ b/excalidraw-app/components/GitHubCorner.tsx @@ -1,6 +1,7 @@ +import { THEME } from "@excalidraw/excalidraw/constants"; import oc from "open-color"; import React from "react"; -import { THEME } from "@excalidraw/excalidraw/constants"; + import type { Theme } from "@excalidraw/excalidraw/element/types"; // https://github.com/tholman/github-corners diff --git a/excalidraw-app/components/TopErrorBoundary.tsx b/excalidraw-app/components/TopErrorBoundary.tsx index e7e00be3b..77d9e5f4f 100644 --- a/excalidraw-app/components/TopErrorBoundary.tsx +++ b/excalidraw-app/components/TopErrorBoundary.tsx @@ -1,7 +1,7 @@ -import React from "react"; -import * as Sentry from "@sentry/browser"; -import { t } from "@excalidraw/excalidraw/i18n"; import Trans from "@excalidraw/excalidraw/components/Trans"; +import { t } from "@excalidraw/excalidraw/i18n"; +import * as Sentry from "@sentry/browser"; +import React from "react"; interface TopErrorBoundaryState { hasError: boolean; diff --git a/excalidraw-app/data/FileManager.ts b/excalidraw-app/data/FileManager.ts index f5f4eaca9..93d7ddec8 100644 --- a/excalidraw-app/data/FileManager.ts +++ b/excalidraw-app/data/FileManager.ts @@ -2,13 +2,14 @@ import { CaptureUpdateAction } from "@excalidraw/excalidraw"; import { compressData } from "@excalidraw/excalidraw/data/encode"; import { newElementWith } from "@excalidraw/excalidraw/element/mutateElement"; import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { t } from "@excalidraw/excalidraw/i18n"; + import type { ExcalidrawElement, ExcalidrawImageElement, FileId, InitializedExcalidrawImageElement, } from "@excalidraw/excalidraw/element/types"; -import { t } from "@excalidraw/excalidraw/i18n"; import type { BinaryFileData, BinaryFileMetadata, diff --git a/excalidraw-app/data/LocalData.ts b/excalidraw-app/data/LocalData.ts index 3ab0ad931..6b53cc482 100644 --- a/excalidraw-app/data/LocalData.ts +++ b/excalidraw-app/data/LocalData.ts @@ -10,6 +10,13 @@ * (localStorage, indexedDB). */ +import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState"; +import { + CANVAS_SEARCH_TAB, + DEFAULT_SIDEBAR, +} from "@excalidraw/excalidraw/constants"; +import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; +import { debounce } from "@excalidraw/excalidraw/utils"; import { createStore, entries, @@ -19,14 +26,9 @@ import { setMany, get, } from "idb-keyval"; -import { clearAppStateForLocalStorage } from "@excalidraw/excalidraw/appState"; -import { - CANVAS_SEARCH_TAB, - DEFAULT_SIDEBAR, -} from "@excalidraw/excalidraw/constants"; + import type { LibraryPersistedData } from "@excalidraw/excalidraw/data/library"; import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; import type { ExcalidrawElement, FileId, @@ -37,8 +39,9 @@ import type { BinaryFiles, } from "@excalidraw/excalidraw/types"; import type { MaybePromise } from "@excalidraw/excalidraw/utility-types"; -import { debounce } from "@excalidraw/excalidraw/utils"; + import { SAVE_TO_LOCAL_STORAGE_TIMEOUT, STORAGE_KEYS } from "../app_constants"; + import { FileManager } from "./FileManager"; import { Locker } from "./Locker"; import { updateBrowserStateVersion } from "./tabSync"; diff --git a/excalidraw-app/data/firebase.ts b/excalidraw-app/data/firebase.ts index a871b4895..66893b513 100644 --- a/excalidraw-app/data/firebase.ts +++ b/excalidraw-app/data/firebase.ts @@ -1,27 +1,12 @@ import { reconcileElements } from "@excalidraw/excalidraw"; -import type { - ExcalidrawElement, - FileId, - OrderedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; -import { getSceneVersion } from "@excalidraw/excalidraw/element"; -import type Portal from "../collab/Portal"; -import { restoreElements } from "@excalidraw/excalidraw/data/restore"; -import type { - AppState, - BinaryFileData, - BinaryFileMetadata, - DataURL, -} from "@excalidraw/excalidraw/types"; -import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; import { decompressData } from "@excalidraw/excalidraw/data/encode"; import { encryptData, decryptData, } from "@excalidraw/excalidraw/data/encryption"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import type { SyncableExcalidrawElement } from "."; -import { getSyncableElements } from "."; +import { restoreElements } from "@excalidraw/excalidraw/data/restore"; +import { getSceneVersion } from "@excalidraw/excalidraw/element"; import { initializeApp } from "firebase/app"; import { getFirestore, @@ -31,8 +16,27 @@ import { Bytes, } from "firebase/firestore"; import { getStorage, ref, uploadBytes } from "firebase/storage"; -import type { Socket } from "socket.io-client"; + import type { RemoteExcalidrawElement } from "@excalidraw/excalidraw/data/reconcile"; +import type { + ExcalidrawElement, + FileId, + OrderedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { + AppState, + BinaryFileData, + BinaryFileMetadata, + DataURL, +} from "@excalidraw/excalidraw/types"; + +import { FILE_CACHE_MAX_AGE_SEC } from "../app_constants"; + +import { getSyncableElements } from "."; + +import type { SyncableExcalidrawElement } from "."; +import type Portal from "../collab/Portal"; +import type { Socket } from "socket.io-client"; // private // ----------------------------------------------------------------------------- diff --git a/excalidraw-app/data/index.ts b/excalidraw-app/data/index.ts index 6ecb98f77..e8fbc1f4d 100644 --- a/excalidraw-app/data/index.ts +++ b/excalidraw-app/data/index.ts @@ -9,34 +9,38 @@ import { } from "@excalidraw/excalidraw/data/encryption"; import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; import { restore } from "@excalidraw/excalidraw/data/restore"; -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds"; import { isInvisiblySmallElement } from "@excalidraw/excalidraw/element/sizeHelpers"; import { isInitializedImageElement } from "@excalidraw/excalidraw/element/typeChecks"; +import { t } from "@excalidraw/excalidraw/i18n"; +import { bytesToHexString } from "@excalidraw/excalidraw/utils"; + +import type { UserIdleState } from "@excalidraw/excalidraw/constants"; +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; +import type { SceneBounds } from "@excalidraw/excalidraw/element/bounds"; import type { ExcalidrawElement, FileId, OrderedExcalidrawElement, } from "@excalidraw/excalidraw/element/types"; -import { t } from "@excalidraw/excalidraw/i18n"; import type { AppState, BinaryFileData, BinaryFiles, SocketId, } from "@excalidraw/excalidraw/types"; -import type { UserIdleState } from "@excalidraw/excalidraw/constants"; import type { MakeBrand } from "@excalidraw/excalidraw/utility-types"; -import { bytesToHexString } from "@excalidraw/excalidraw/utils"; -import type { WS_SUBTYPES } from "../app_constants"; + import { DELETED_ELEMENT_TIMEOUT, FILE_UPLOAD_MAX_BYTES, ROOM_ID_BYTES, } from "../app_constants"; + import { encodeFilesForUpload } from "./FileManager"; import { saveFilesToFirebase } from "./firebase"; +import type { WS_SUBTYPES } from "../app_constants"; + export type SyncableExcalidrawElement = OrderedExcalidrawElement & MakeBrand<"SyncableExcalidrawElement">; diff --git a/excalidraw-app/data/localStorage.ts b/excalidraw-app/data/localStorage.ts index 640dfdb60..ac1206498 100644 --- a/excalidraw-app/data/localStorage.ts +++ b/excalidraw-app/data/localStorage.ts @@ -1,10 +1,12 @@ -import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types"; -import type { AppState } from "@excalidraw/excalidraw/types"; import { clearAppStateForLocalStorage, getDefaultAppState, } from "@excalidraw/excalidraw/appState"; import { clearElementsForLocalStorage } from "@excalidraw/excalidraw/element"; + +import type { ExcalidrawElement } from "@excalidraw/excalidraw/element/types"; +import type { AppState } from "@excalidraw/excalidraw/types"; + import { STORAGE_KEYS } from "../app_constants"; export const saveUsernameToLocalStorage = (username: string) => { diff --git a/excalidraw-app/index.tsx b/excalidraw-app/index.tsx index a28bd9e49..98c902e36 100644 --- a/excalidraw-app/index.tsx +++ b/excalidraw-app/index.tsx @@ -1,9 +1,11 @@ import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import ExcalidrawApp from "./App"; import { registerSW } from "virtual:pwa-register"; import "../excalidraw-app/sentry"; + +import ExcalidrawApp from "./App"; + window.__EXCALIDRAW_SHA__ = import.meta.env.VITE_APP_GIT_SHA; const rootElement = document.getElementById("root")!; const root = createRoot(rootElement); diff --git a/excalidraw-app/share/ShareDialog.tsx b/excalidraw-app/share/ShareDialog.tsx index bba7e3678..de77c6079 100644 --- a/excalidraw-app/share/ShareDialog.tsx +++ b/excalidraw-app/share/ShareDialog.tsx @@ -1,10 +1,8 @@ -import { useEffect, useRef, useState } from "react"; -import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; import { trackEvent } from "@excalidraw/excalidraw/analytics"; -import { getFrame } from "@excalidraw/excalidraw/utils"; -import { useI18n } from "@excalidraw/excalidraw/i18n"; -import { KEYS } from "@excalidraw/excalidraw/keys"; +import { copyTextToSystemClipboard } from "@excalidraw/excalidraw/clipboard"; import { Dialog } from "@excalidraw/excalidraw/components/Dialog"; +import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton"; +import { TextField } from "@excalidraw/excalidraw/components/TextField"; import { copyIcon, LinkIcon, @@ -14,16 +12,20 @@ import { shareIOS, shareWindows, } from "@excalidraw/excalidraw/components/icons"; -import { TextField } from "@excalidraw/excalidraw/components/TextField"; -import { FilledButton } from "@excalidraw/excalidraw/components/FilledButton"; -import type { CollabAPI } from "../collab/Collab"; -import { activeRoomLinkAtom } from "../collab/Collab"; import { useUIAppState } from "@excalidraw/excalidraw/context/ui-appState"; import { useCopyStatus } from "@excalidraw/excalidraw/hooks/useCopiedIndicator"; +import { useI18n } from "@excalidraw/excalidraw/i18n"; +import { KEYS } from "@excalidraw/excalidraw/keys"; +import { getFrame } from "@excalidraw/excalidraw/utils"; +import { useEffect, useRef, useState } from "react"; + import { atom, useAtom, useAtomValue } from "../app-jotai"; +import { activeRoomLinkAtom } from "../collab/Collab"; import "./ShareDialog.scss"; +import type { CollabAPI } from "../collab/Collab"; + type OnExportToBackend = () => void; type ShareDialogType = "share" | "collaborationOnly"; diff --git a/excalidraw-app/tests/MobileMenu.test.tsx b/excalidraw-app/tests/MobileMenu.test.tsx index a6eef3b51..3b05e7296 100644 --- a/excalidraw-app/tests/MobileMenu.test.tsx +++ b/excalidraw-app/tests/MobileMenu.test.tsx @@ -1,11 +1,11 @@ -import ExcalidrawApp from "../App"; +import { UI } from "@excalidraw/excalidraw/tests/helpers/ui"; import { mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, } from "@excalidraw/excalidraw/tests/test-utils"; -import { UI } from "@excalidraw/excalidraw/tests/helpers/ui"; +import ExcalidrawApp from "../App"; describe("Test MobileMenu", () => { const { h } = window; diff --git a/excalidraw-app/tests/collab.test.tsx b/excalidraw-app/tests/collab.test.tsx index 80cf4b0b9..f6cd68fab 100644 --- a/excalidraw-app/tests/collab.test.tsx +++ b/excalidraw-app/tests/collab.test.tsx @@ -1,13 +1,14 @@ -import { vi } from "vitest"; -import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils"; -import ExcalidrawApp from "../App"; -import { API } from "@excalidraw/excalidraw/tests/helpers/api"; -import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex"; +import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw"; import { createRedoAction, createUndoAction, } from "@excalidraw/excalidraw/actions/actionHistory"; -import { CaptureUpdateAction, newElementWith } from "@excalidraw/excalidraw"; +import { syncInvalidIndices } from "@excalidraw/excalidraw/fractionalIndex"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; +import { act, render, waitFor } from "@excalidraw/excalidraw/tests/test-utils"; +import { vi } from "vitest"; + +import ExcalidrawApp from "../App"; const { h } = window; diff --git a/excalidraw-app/useHandleAppTheme.ts b/excalidraw-app/useHandleAppTheme.ts index e31961174..6fc2ff54f 100644 --- a/excalidraw-app/useHandleAppTheme.ts +++ b/excalidraw-app/useHandleAppTheme.ts @@ -1,8 +1,10 @@ -import { useEffect, useLayoutEffect, useState } from "react"; import { THEME } from "@excalidraw/excalidraw"; import { EVENT } from "@excalidraw/excalidraw/constants"; -import type { Theme } from "@excalidraw/excalidraw/element/types"; import { CODES, KEYS } from "@excalidraw/excalidraw/keys"; +import { useEffect, useLayoutEffect, useState } from "react"; + +import type { Theme } from "@excalidraw/excalidraw/element/types"; + import { STORAGE_KEYS } from "./app_constants"; const getDarkThemeMediaQuery = (): MediaQueryList | undefined => diff --git a/package.json b/package.json index aaa8027a8..9ff4379d1 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "dotenv": "16.0.1", "eslint-config-prettier": "8.5.0", "eslint-config-react-app": "7.0.1", + "eslint-plugin-import": "2.31.0", "eslint-plugin-prettier": "3.3.1", "http-server": "14.1.1", "husky": "7.0.4", diff --git a/packages/excalidraw/actions/actionAddToLibrary.ts b/packages/excalidraw/actions/actionAddToLibrary.ts index 3186e3bcb..b246918a0 100644 --- a/packages/excalidraw/actions/actionAddToLibrary.ts +++ b/packages/excalidraw/actions/actionAddToLibrary.ts @@ -1,10 +1,11 @@ -import { register } from "./register"; -import { deepCopyElement } from "../element/newElement"; -import { randomId } from "../random"; -import { t } from "../i18n"; import { LIBRARY_DISABLED_TYPES } from "../constants"; +import { deepCopyElement } from "../element/newElement"; +import { t } from "../i18n"; +import { randomId } from "../random"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionAddToLibrary = register({ name: "addToLibrary", trackEvent: { category: "element" }, diff --git a/packages/excalidraw/actions/actionAlign.tsx b/packages/excalidraw/actions/actionAlign.tsx index 53e8e618b..b42122a50 100644 --- a/packages/excalidraw/actions/actionAlign.tsx +++ b/packages/excalidraw/actions/actionAlign.tsx @@ -1,5 +1,5 @@ -import type { Alignment } from "../align"; import { alignElements } from "../align"; +import { ToolButton } from "../components/ToolButton"; import { AlignBottomIcon, AlignLeftIcon, @@ -8,19 +8,21 @@ import { CenterHorizontallyIcon, CenterVerticallyIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties, AppState, UIAppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; + import { register } from "./register"; +import type { Alignment } from "../align"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState, UIAppState } from "../types"; + export const alignActionsPredicate = ( appState: UIAppState, app: AppClassProperties, diff --git a/packages/excalidraw/actions/actionBoundText.tsx b/packages/excalidraw/actions/actionBoundText.tsx index b72ddee64..4da3f99a1 100644 --- a/packages/excalidraw/actions/actionBoundText.tsx +++ b/packages/excalidraw/actions/actionBoundText.tsx @@ -5,6 +5,11 @@ import { VERTICAL_ALIGN, } from "../constants"; import { isTextElement, newElement } from "../element"; +import { + getOriginalContainerHeightFromCache, + resetOriginalContainerCache, + updateOriginalContainerCache, +} from "../element/containerCache"; import { mutateElement } from "../element/mutateElement"; import { computeBoundTextPosition, @@ -12,16 +17,18 @@ import { getBoundTextElement, redrawTextBoundingBox, } from "../element/textElement"; -import { - getOriginalContainerHeightFromCache, - resetOriginalContainerCache, - updateOriginalContainerCache, -} from "../element/containerCache"; +import { measureText } from "../element/textMeasurements"; import { hasBoundTextElement, isTextBindableContainer, isUsingAdaptiveRadius, } from "../element/typeChecks"; +import { syncMovedIndices } from "../fractionalIndex"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap, getFontString } from "../utils"; + +import { register } from "./register"; + import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -30,11 +37,6 @@ import type { } from "../element/types"; import type { AppState } from "../types"; import type { Mutable } from "../utility-types"; -import { arrayToMap, getFontString } from "../utils"; -import { register } from "./register"; -import { syncMovedIndices } from "../fractionalIndex"; -import { CaptureUpdateAction } from "../store"; -import { measureText } from "../element/textMeasurements"; export const actionUnbindText = register({ name: "unbindText", diff --git a/packages/excalidraw/actions/actionCanvas.tsx b/packages/excalidraw/actions/actionCanvas.tsx index 903a6d84a..f3e0a8a32 100644 --- a/packages/excalidraw/actions/actionCanvas.tsx +++ b/packages/excalidraw/actions/actionCanvas.tsx @@ -1,4 +1,14 @@ +import { clamp, roundToStep } from "@excalidraw/math"; + +import { + getDefaultAppState, + isEraserActive, + isHandToolActive, +} from "../appState"; +import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors"; import { ColorPicker } from "../components/ColorPicker/ColorPicker"; +import { ToolButton } from "../components/ToolButton"; +import { Tooltip } from "../components/Tooltip"; import { handIcon, MoonIcon, @@ -9,7 +19,6 @@ import { ZoomOutIcon, ZoomResetIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { CURSOR_TYPE, MAX_ZOOM, @@ -17,28 +26,22 @@ import { THEME, ZOOM_STEP, } from "../constants"; +import { setCursor } from "../cursor"; import { getCommonBounds, getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; +import { newElementWith } from "../element/mutateElement"; import { t } from "../i18n"; import { CODES, KEYS } from "../keys"; import { getNormalizedZoom } from "../scene"; import { centerScrollOn } from "../scene/scroll"; import { getStateForZoom } from "../scene/zoom"; -import type { AppState, Offsets } from "../types"; -import { getShortcutKey, updateActiveTool } from "../utils"; -import { register } from "./register"; -import { Tooltip } from "../components/Tooltip"; -import { newElementWith } from "../element/mutateElement"; -import { - getDefaultAppState, - isEraserActive, - isHandToolActive, -} from "../appState"; -import { DEFAULT_CANVAS_BACKGROUND_PICKS } from "../colors"; -import type { SceneBounds } from "../element/bounds"; -import { setCursor } from "../cursor"; import { CaptureUpdateAction } from "../store"; -import { clamp, roundToStep } from "@excalidraw/math"; +import { getShortcutKey, updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { SceneBounds } from "../element/bounds"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState, Offsets } from "../types"; export const actionChangeViewBackgroundColor = register({ name: "changeViewBackgroundColor", diff --git a/packages/excalidraw/actions/actionClipboard.tsx b/packages/excalidraw/actions/actionClipboard.tsx index fffe7b377..4ce3c39dd 100644 --- a/packages/excalidraw/actions/actionClipboard.tsx +++ b/packages/excalidraw/actions/actionClipboard.tsx @@ -1,5 +1,3 @@ -import { CODES, KEYS } from "../keys"; -import { register } from "./register"; import { copyTextToSystemClipboard, copyToClipboard, @@ -8,14 +6,17 @@ import { probablySupportsClipboardWriteText, readSystemClipboard, } from "../clipboard"; -import { actionDeleteSelected } from "./actionDeleteSelected"; +import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons"; +import { isFirefox } from "../constants"; import { exportCanvas, prepareElementsForExport } from "../data/index"; import { getTextFromElements, isTextElement } from "../element"; import { t } from "../i18n"; -import { isFirefox } from "../constants"; -import { DuplicateIcon, cutIcon, pngIcon, svgIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { actionDeleteSelected } from "./actionDeleteSelected"; +import { register } from "./register"; + export const actionCopy = register({ name: "copy", label: "labels.copy", diff --git a/packages/excalidraw/actions/actionCropEditor.tsx b/packages/excalidraw/actions/actionCropEditor.tsx index 643f666ba..c377b3a02 100644 --- a/packages/excalidraw/actions/actionCropEditor.tsx +++ b/packages/excalidraw/actions/actionCropEditor.tsx @@ -1,9 +1,11 @@ -import { register } from "./register"; -import { cropIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; +import { cropIcon } from "../components/icons"; import { isImageElement } from "../element/typeChecks"; +import { t } from "../i18n"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + import type { ExcalidrawImageElement } from "../element/types"; export const actionToggleCropEditor = register({ diff --git a/packages/excalidraw/actions/actionDeleteSelected.test.tsx b/packages/excalidraw/actions/actionDeleteSelected.test.tsx index d48646fac..090c81941 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.test.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.test.tsx @@ -1,7 +1,9 @@ import React from "react"; + import { Excalidraw, mutateElement } from "../index"; -import { act, assertElements, render } from "../tests/test-utils"; import { API } from "../tests/helpers/api"; +import { act, assertElements, render } from "../tests/test-utils"; + import { actionDeleteSelected } from "./actionDeleteSelected"; const { h } = window; diff --git a/packages/excalidraw/actions/actionDeleteSelected.tsx b/packages/excalidraw/actions/actionDeleteSelected.tsx index c640f9256..fe3f8c5d7 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.tsx @@ -1,25 +1,27 @@ -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { KEYS } from "../keys"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import { register } from "./register"; +import { TrashIcon } from "../components/icons"; import { getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; -import { mutateElement, newElementWith } from "../element/mutateElement"; -import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups"; -import { LinearElementEditor } from "../element/linearElementEditor"; import { fixBindingsAfterDeletion } from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { mutateElement, newElementWith } from "../element/mutateElement"; +import { getContainerElement } from "../element/textElement"; import { isBoundToContainer, isElbowArrow, isFrameLikeElement, } from "../element/typeChecks"; -import { updateActiveTool } from "../utils"; -import { TrashIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { getContainerElement } from "../element/textElement"; import { getFrameChildren } from "../frame"; +import { getElementsInGroup, selectGroupsForSelectedElements } from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; const deleteSelectedElements = ( elements: readonly ExcalidrawElement[], diff --git a/packages/excalidraw/actions/actionDistribute.tsx b/packages/excalidraw/actions/actionDistribute.tsx index 15d33b1f1..c96bdaa3e 100644 --- a/packages/excalidraw/actions/actionDistribute.tsx +++ b/packages/excalidraw/actions/actionDistribute.tsx @@ -1,22 +1,24 @@ +import { ToolButton } from "../components/ToolButton"; import { DistributeHorizontallyIcon, DistributeVerticallyIcon, } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; -import type { Distribution } from "../distribute"; import { distributeElements } from "../distribute"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { updateFrameMembershipOfSelectedElements } from "../frame"; import { t } from "../i18n"; import { CODES, KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties, AppState } from "../types"; import { arrayToMap, getShortcutKey } from "../utils"; + import { register } from "./register"; +import type { Distribution } from "../distribute"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; + const enableActionGroup = (appState: AppState, app: AppClassProperties) => { const selectedElements = app.scene.getSelectedElements(appState); return ( diff --git a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx index dc471df37..2c1d44e92 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx @@ -1,14 +1,16 @@ +import React from "react"; + +import { ORIG_ID } from "../constants"; import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; import { act, assertElements, getCloneByOrigId, render, } from "../tests/test-utils"; -import { API } from "../tests/helpers/api"; + import { actionDuplicateSelection } from "./actionDuplicateSelection"; -import React from "react"; -import { ORIG_ID } from "../constants"; const { h } = window; diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index b28e831c8..ce225a1d6 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -1,27 +1,8 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import type { ExcalidrawElement } from "../element/types"; -import { duplicateElement, getNonDeletedElements } from "../element"; -import { isSomeElementSelected } from "../scene"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import { - arrayToMap, - castArray, - findLastIndex, - getShortcutKey, - invariant, -} from "../utils"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { - selectGroupsForSelectedElements, - getSelectedGroupForElement, - getElementsInGroup, -} from "../groups"; -import type { AppState } from "../types"; -import { fixBindingsAfterDuplication } from "../element/binding"; -import type { ActionResult } from "./types"; +import { DuplicateIcon } from "../components/icons"; import { DEFAULT_GRID_SIZE } from "../constants"; +import { duplicateElement, getNonDeletedElements } from "../element"; +import { fixBindingsAfterDuplication } from "../element/binding"; import { bindTextToShapeAfterDuplication, getBoundTextElement, @@ -33,16 +14,37 @@ import { isFrameLikeElement, } from "../element/typeChecks"; import { normalizeElementOrder } from "../element/sortElements"; -import { DuplicateIcon } from "../components/icons"; +import { LinearElementEditor } from "../element/linearElementEditor"; import { bindElementsToFramesAfterDuplication, getFrameChildren, } from "../frame"; +import { + selectGroupsForSelectedElements, + getSelectedGroupForElement, + getElementsInGroup, +} from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { isSomeElementSelected } from "../scene"; import { excludeElementsInFramesFromSelection, getSelectedElements, } from "../scene/selection"; import { CaptureUpdateAction } from "../store"; +import { + arrayToMap, + castArray, + findLastIndex, + getShortcutKey, + invariant, +} from "../utils"; + +import { register } from "./register"; + +import type { ActionResult } from "./types"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState } from "../types"; export const actionDuplicateSelection = register({ name: "duplicateSelection", diff --git a/packages/excalidraw/actions/actionElementLink.ts b/packages/excalidraw/actions/actionElementLink.ts index 91469fd63..69fc67dd3 100644 --- a/packages/excalidraw/actions/actionElementLink.ts +++ b/packages/excalidraw/actions/actionElementLink.ts @@ -8,6 +8,7 @@ import { import { t } from "../i18n"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionCopyElementLink = register({ diff --git a/packages/excalidraw/actions/actionElementLock.test.tsx b/packages/excalidraw/actions/actionElementLock.test.tsx index d6dd3f7ac..ec45ab9b2 100644 --- a/packages/excalidraw/actions/actionElementLock.test.tsx +++ b/packages/excalidraw/actions/actionElementLock.test.tsx @@ -1,9 +1,10 @@ -import React from "react"; -import { Excalidraw } from "../index"; import { queryByTestId, fireEvent } from "@testing-library/react"; -import { render } from "../tests/test-utils"; -import { Pointer, UI } from "../tests/helpers/ui"; +import React from "react"; + +import { Excalidraw } from "../index"; import { API } from "../tests/helpers/api"; +import { Pointer, UI } from "../tests/helpers/ui"; +import { render } from "../tests/test-utils"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/actions/actionElementLock.ts b/packages/excalidraw/actions/actionElementLock.ts index eba21f240..57ca1dded 100644 --- a/packages/excalidraw/actions/actionElementLock.ts +++ b/packages/excalidraw/actions/actionElementLock.ts @@ -1,13 +1,15 @@ import { LockedIcon, UnlockedIcon } from "../components/icons"; import { newElementWith } from "../element/mutateElement"; import { isFrameLikeElement } from "../element/typeChecks"; -import type { ExcalidrawElement } from "../element/types"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; import { arrayToMap } from "../utils"; + import { register } from "./register"; +import type { ExcalidrawElement } from "../element/types"; + const shouldLock = (elements: readonly ExcalidrawElement[]) => elements.every((el) => !el.locked); diff --git a/packages/excalidraw/actions/actionExport.tsx b/packages/excalidraw/actions/actionExport.tsx index 8d18acd89..c9d70fc46 100644 --- a/packages/excalidraw/actions/actionExport.tsx +++ b/packages/excalidraw/actions/actionExport.tsx @@ -1,25 +1,27 @@ -import { ExportIcon, questionCircle, saveAs } from "../components/icons"; +import { useDevice } from "../components/App"; +import { CheckboxItem } from "../components/CheckboxItem"; +import { DarkModeToggle } from "../components/DarkModeToggle"; import { ProjectName } from "../components/ProjectName"; import { ToolButton } from "../components/ToolButton"; import { Tooltip } from "../components/Tooltip"; -import { DarkModeToggle } from "../components/DarkModeToggle"; -import { loadFromJSON, saveAsJSON } from "../data"; -import { resaveAsImageWithScene } from "../data/resave"; -import { t } from "../i18n"; -import { useDevice } from "../components/App"; -import { KEYS } from "../keys"; -import { register } from "./register"; -import { CheckboxItem } from "../components/CheckboxItem"; -import { getExportSize } from "../scene/export"; +import { ExportIcon, questionCircle, saveAs } from "../components/icons"; import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { getNonDeletedElements } from "../element"; +import { loadFromJSON, saveAsJSON } from "../data"; import { isImageFileHandle } from "../data/blob"; import { nativeFileSystemSupported } from "../data/filesystem"; -import type { Theme } from "../element/types"; +import { resaveAsImageWithScene } from "../data/resave"; +import { getNonDeletedElements } from "../element"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { getExportSize } from "../scene/export"; +import { CaptureUpdateAction } from "../store"; import "../components/ToolIcon.scss"; -import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { Theme } from "../element/types"; export const actionChangeProjectName = register({ name: "changeProjectName", diff --git a/packages/excalidraw/actions/actionFinalize.tsx b/packages/excalidraw/actions/actionFinalize.tsx index f2d8c0158..ac8a4e036 100644 --- a/packages/excalidraw/actions/actionFinalize.tsx +++ b/packages/excalidraw/actions/actionFinalize.tsx @@ -1,22 +1,25 @@ -import { KEYS } from "../keys"; -import { isInvisiblySmallElement } from "../element"; -import { arrayToMap, updateActiveTool } from "../utils"; +import { pointFrom } from "@excalidraw/math"; + import { ToolButton } from "../components/ToolButton"; import { done } from "../components/icons"; -import { t } from "../i18n"; -import { register } from "./register"; -import { mutateElement } from "../element/mutateElement"; -import { LinearElementEditor } from "../element/linearElementEditor"; +import { resetCursor } from "../cursor"; +import { isInvisiblySmallElement } from "../element"; import { maybeBindLinearElement, bindOrUnbindLinearElement, } from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { mutateElement } from "../element/mutateElement"; import { isBindingElement, isLinearElement } from "../element/typeChecks"; -import type { AppState } from "../types"; -import { resetCursor } from "../cursor"; -import { CaptureUpdateAction } from "../store"; -import { pointFrom } from "@excalidraw/math"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; import { isPathALoop } from "../shapes"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap, updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { AppState } from "../types"; export const actionFinalize = register({ name: "finalize", diff --git a/packages/excalidraw/actions/actionFlip.test.tsx b/packages/excalidraw/actions/actionFlip.test.tsx index 94e4721dd..e9953e02d 100644 --- a/packages/excalidraw/actions/actionFlip.test.tsx +++ b/packages/excalidraw/actions/actionFlip.test.tsx @@ -1,8 +1,10 @@ -import React from "react"; -import { Excalidraw } from "../index"; -import { render } from "../tests/test-utils"; -import { API } from "../tests/helpers/api"; import { pointFrom } from "@excalidraw/math"; +import React from "react"; + +import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; +import { render } from "../tests/test-utils"; + import { actionFlipHorizontal, actionFlipVertical } from "./actionFlip"; const { h } = window; diff --git a/packages/excalidraw/actions/actionFlip.ts b/packages/excalidraw/actions/actionFlip.ts index 80149b877..bfc7fb721 100644 --- a/packages/excalidraw/actions/actionFlip.ts +++ b/packages/excalidraw/actions/actionFlip.ts @@ -1,6 +1,26 @@ -import { register } from "./register"; -import { getSelectedElements } from "../scene"; +import { flipHorizontal, flipVertical } from "../components/icons"; import { getNonDeletedElements } from "../element"; +import { + bindOrUnbindLinearElements, + isBindingEnabled, +} from "../element/binding"; +import { getCommonBoundingBox } from "../element/bounds"; +import { mutateElement, newElementWith } from "../element/mutateElement"; +import { deepCopyElement } from "../element/newElement"; +import { resizeMultipleElements } from "../element/resizeElements"; +import { + isArrowElement, + isElbowArrow, + isLinearElement, +} from "../element/typeChecks"; +import { updateFrameMembershipOfSelectedElements } from "../frame"; +import { CODES, KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; + +import { register } from "./register"; + import type { ExcalidrawArrowElement, ExcalidrawElbowArrowElement, @@ -8,25 +28,7 @@ import type { NonDeleted, NonDeletedSceneElementsMap, } from "../element/types"; -import { resizeMultipleElements } from "../element/resizeElements"; import type { AppClassProperties, AppState } from "../types"; -import { arrayToMap } from "../utils"; -import { CODES, KEYS } from "../keys"; -import { - bindOrUnbindLinearElements, - isBindingEnabled, -} from "../element/binding"; -import { updateFrameMembershipOfSelectedElements } from "../frame"; -import { flipHorizontal, flipVertical } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { - isArrowElement, - isElbowArrow, - isLinearElement, -} from "../element/typeChecks"; -import { mutateElement, newElementWith } from "../element/mutateElement"; -import { deepCopyElement } from "../element/newElement"; -import { getCommonBoundingBox } from "../element/bounds"; export const actionFlipHorizontal = register({ name: "flipHorizontal", diff --git a/packages/excalidraw/actions/actionFrame.ts b/packages/excalidraw/actions/actionFrame.ts index ce05b533b..198994b29 100644 --- a/packages/excalidraw/actions/actionFrame.ts +++ b/packages/excalidraw/actions/actionFrame.ts @@ -1,19 +1,21 @@ +import { frameToolIcon } from "../components/icons"; +import { setCursorForShape } from "../cursor"; import { getCommonBounds, getNonDeletedElements } from "../element"; -import type { ExcalidrawElement } from "../element/types"; +import { mutateElement } from "../element/mutateElement"; +import { newFrameElement } from "../element/newElement"; +import { isFrameLikeElement } from "../element/typeChecks"; import { addElementsToFrame, removeAllElementsFromFrame } from "../frame"; import { getFrameChildren } from "../frame"; -import { KEYS } from "../keys"; -import type { AppClassProperties, AppState, UIAppState } from "../types"; -import { updateActiveTool } from "../utils"; -import { setCursorForShape } from "../cursor"; -import { register } from "./register"; -import { isFrameLikeElement } from "../element/typeChecks"; -import { frameToolIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; -import { getSelectedElements } from "../scene"; -import { newFrameElement } from "../element/newElement"; import { getElementsInGroup } from "../groups"; -import { mutateElement } from "../element/mutateElement"; +import { KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; +import { updateActiveTool } from "../utils"; + +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; +import type { AppClassProperties, AppState, UIAppState } from "../types"; const isSingleFrameSelected = ( appState: UIAppState, diff --git a/packages/excalidraw/actions/actionGroup.tsx b/packages/excalidraw/actions/actionGroup.tsx index 4e98c59c7..ded2f5b72 100644 --- a/packages/excalidraw/actions/actionGroup.tsx +++ b/packages/excalidraw/actions/actionGroup.tsx @@ -1,29 +1,9 @@ -import { KEYS } from "../keys"; -import { t } from "../i18n"; -import { arrayToMap, getShortcutKey } from "../utils"; -import { register } from "./register"; -import { UngroupIcon, GroupIcon } from "../components/icons"; -import { newElementWith } from "../element/mutateElement"; -import { isSomeElementSelected } from "../scene"; -import { - getSelectedGroupIds, - selectGroup, - selectGroupsForSelectedElements, - getElementsInGroup, - addToGroup, - removeFromSelectedGroups, - isElementInGroup, -} from "../groups"; -import { getNonDeletedElements } from "../element"; -import { randomId } from "../random"; import { ToolButton } from "../components/ToolButton"; -import type { - ExcalidrawElement, - ExcalidrawTextElement, - OrderedExcalidrawElement, -} from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; +import { UngroupIcon, GroupIcon } from "../components/icons"; +import { getNonDeletedElements } from "../element"; +import { newElementWith } from "../element/mutateElement"; import { isBoundToContainer } from "../element/typeChecks"; +import { syncMovedIndices } from "../fractionalIndex"; import { frameAndChildrenSelectedTogether, getElementsInResizingFrame, @@ -33,8 +13,30 @@ import { removeElementsFromFrame, replaceAllElementsInFrame, } from "../frame"; -import { syncMovedIndices } from "../fractionalIndex"; +import { + getSelectedGroupIds, + selectGroup, + selectGroupsForSelectedElements, + getElementsInGroup, + addToGroup, + removeFromSelectedGroups, + isElementInGroup, +} from "../groups"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { randomId } from "../random"; +import { isSomeElementSelected } from "../scene"; import { CaptureUpdateAction } from "../store"; +import { arrayToMap, getShortcutKey } from "../utils"; + +import { register } from "./register"; + +import type { + ExcalidrawElement, + ExcalidrawTextElement, + OrderedExcalidrawElement, +} from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; const allElementsInSameGroup = (elements: readonly ExcalidrawElement[]) => { if (elements.length >= 2) { diff --git a/packages/excalidraw/actions/actionHistory.tsx b/packages/excalidraw/actions/actionHistory.tsx index 299a09f3d..da4f80219 100644 --- a/packages/excalidraw/actions/actionHistory.tsx +++ b/packages/excalidraw/actions/actionHistory.tsx @@ -1,17 +1,18 @@ -import type { Action, ActionResult } from "./types"; -import { UndoIcon, RedoIcon } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; -import type { History } from "../history"; -import { HistoryChangedEvent } from "../history"; -import type { AppClassProperties, AppState } from "../types"; -import { KEYS, matchKey } from "../keys"; -import { arrayToMap } from "../utils"; +import { UndoIcon, RedoIcon } from "../components/icons"; import { isWindows } from "../constants"; -import type { SceneElementsMap } from "../element/types"; -import type { Store } from "../store"; -import { CaptureUpdateAction } from "../store"; +import { HistoryChangedEvent } from "../history"; import { useEmitter } from "../hooks/useEmitter"; +import { t } from "../i18n"; +import { KEYS, matchKey } from "../keys"; +import { CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; + +import type { SceneElementsMap } from "../element/types"; +import type { History } from "../history"; +import type { Store } from "../store"; +import type { AppClassProperties, AppState } from "../types"; +import type { Action, ActionResult } from "./types"; const executeHistoryAction = ( app: AppClassProperties, diff --git a/packages/excalidraw/actions/actionLinearEditor.tsx b/packages/excalidraw/actions/actionLinearEditor.tsx index 1f05755b5..f17f0e565 100644 --- a/packages/excalidraw/actions/actionLinearEditor.tsx +++ b/packages/excalidraw/actions/actionLinearEditor.tsx @@ -1,12 +1,14 @@ import { DEFAULT_CATEGORIES } from "../components/CommandPalette/CommandPalette"; +import { ToolButton } from "../components/ToolButton"; +import { lineEditorIcon } from "../components/icons"; import { LinearElementEditor } from "../element/linearElementEditor"; import { isElbowArrow, isLinearElement } from "../element/typeChecks"; -import type { ExcalidrawLinearElement } from "../element/types"; -import { CaptureUpdateAction } from "../store"; -import { register } from "./register"; -import { ToolButton } from "../components/ToolButton"; import { t } from "../i18n"; -import { lineEditorIcon } from "../components/icons"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { ExcalidrawLinearElement } from "../element/types"; export const actionToggleLinearEditor = register({ name: "toggleLinearEditor", diff --git a/packages/excalidraw/actions/actionLink.tsx b/packages/excalidraw/actions/actionLink.tsx index beb95d2c1..91d01b7a6 100644 --- a/packages/excalidraw/actions/actionLink.tsx +++ b/packages/excalidraw/actions/actionLink.tsx @@ -1,12 +1,13 @@ +import { ToolButton } from "../components/ToolButton"; import { getContextMenuLabel } from "../components/hyperlink/Hyperlink"; import { LinkIcon } from "../components/icons"; -import { ToolButton } from "../components/ToolButton"; import { isEmbeddableElement } from "../element/typeChecks"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; import { getShortcutKey } from "../utils"; + import { register } from "./register"; export const actionLink = register({ diff --git a/packages/excalidraw/actions/actionMenu.tsx b/packages/excalidraw/actions/actionMenu.tsx index 9e71fe255..15b763cb9 100644 --- a/packages/excalidraw/actions/actionMenu.tsx +++ b/packages/excalidraw/actions/actionMenu.tsx @@ -1,11 +1,12 @@ -import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons"; import { ToolButton } from "../components/ToolButton"; -import { t } from "../i18n"; +import { HamburgerMenuIcon, HelpIconThin, palette } from "../components/icons"; import { showSelectedShapeActions, getNonDeletedElements } from "../element"; -import { register } from "./register"; +import { t } from "../i18n"; import { KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionToggleCanvasMenu = register({ name: "toggleCanvasMenu", label: "buttons.menu", diff --git a/packages/excalidraw/actions/actionNavigate.tsx b/packages/excalidraw/actions/actionNavigate.tsx index 48037200c..738386839 100644 --- a/packages/excalidraw/actions/actionNavigate.tsx +++ b/packages/excalidraw/actions/actionNavigate.tsx @@ -1,6 +1,7 @@ +import clsx from "clsx"; + import { getClientColor } from "../clients"; import { Avatar } from "../components/Avatar"; -import type { GoToCollaboratorComponentProps } from "../components/UserList"; import { eyeIcon, microphoneIcon, @@ -8,9 +9,11 @@ import { } from "../components/icons"; import { t } from "../i18n"; import { CaptureUpdateAction } from "../store"; -import type { Collaborator } from "../types"; + import { register } from "./register"; -import clsx from "clsx"; + +import type { GoToCollaboratorComponentProps } from "../components/UserList"; +import type { Collaborator } from "../types"; export const actionGoToCollaborator = register({ name: "goToCollaborator", diff --git a/packages/excalidraw/actions/actionProperties.test.tsx b/packages/excalidraw/actions/actionProperties.test.tsx index 80d2ca257..c5467bb94 100644 --- a/packages/excalidraw/actions/actionProperties.test.tsx +++ b/packages/excalidraw/actions/actionProperties.test.tsx @@ -1,11 +1,12 @@ -import React from "react"; -import { Excalidraw } from "../index"; import { queryByTestId } from "@testing-library/react"; -import { render } from "../tests/test-utils"; -import { UI } from "../tests/helpers/ui"; -import { API } from "../tests/helpers/api"; +import React from "react"; + import { COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS } from "../colors"; import { FONT_FAMILY, STROKE_WIDTH } from "../constants"; +import { Excalidraw } from "../index"; +import { API } from "../tests/helpers/api"; +import { UI } from "../tests/helpers/ui"; +import { render } from "../tests/test-utils"; describe("element locking", () => { beforeEach(async () => { diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 0c2ad3bab..1e24d9bed 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -1,20 +1,23 @@ +import { pointFrom } from "@excalidraw/math"; import { useEffect, useMemo, useRef, useState } from "react"; -import type { AppClassProperties, AppState, Primitive } from "../types"; -import type { CaptureUpdateActionType } from "../store"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { trackEvent } from "../analytics"; import { DEFAULT_ELEMENT_BACKGROUND_COLOR_PALETTE, DEFAULT_ELEMENT_BACKGROUND_PICKS, DEFAULT_ELEMENT_STROKE_COLOR_PALETTE, DEFAULT_ELEMENT_STROKE_PICKS, } from "../colors"; -import { trackEvent } from "../analytics"; import { ButtonIconSelect } from "../components/ButtonIconSelect"; import { ColorPicker } from "../components/ColorPicker/ColorPicker"; -import { IconPicker } from "../components/IconPicker"; import { FontPicker } from "../components/FontPicker/FontPicker"; +import { IconPicker } from "../components/IconPicker"; // TODO barnabasmolnar/editor-redesign // TextAlignTopIcon, TextAlignBottomIcon,TextAlignMiddleIcon, // ArrowHead icons +import { Range } from "../components/Range"; import { ArrowheadArrowIcon, ArrowheadBarIcon, @@ -71,6 +74,14 @@ import { isTextElement, redrawTextBoundingBox, } from "../element"; +import { + bindLinearElement, + bindPointToSnapToElementOutline, + calculateFixedPointForElbowArrowBinding, + getHoveredElementForBinding, + updateBoundElements, +} from "../element/binding"; +import { LinearElementEditor } from "../element/linearElementEditor"; import { mutateElement, newElementWith } from "../element/mutateElement"; import { getBoundTextElement } from "../element/textElement"; import { @@ -80,17 +91,7 @@ import { isLinearElement, isUsingAdaptiveRadius, } from "../element/typeChecks"; -import type { - Arrowhead, - ExcalidrawBindableElement, - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElement, - FontFamilyValues, - TextAlign, - VerticalAlign, - NonDeletedSceneElementsMap, -} from "../element/types"; +import { Fonts, getLineHeight } from "../fonts"; import { getLanguage, t } from "../i18n"; import { KEYS } from "../keys"; import { randomInteger } from "../random"; @@ -102,26 +103,29 @@ import { isSomeElementSelected, } from "../scene"; import { hasStrokeColor } from "../scene/comparisons"; +import { CaptureUpdateAction } from "../store"; import { arrayToMap, getFontFamilyString, getShortcutKey, tupleToCoors, } from "../utils"; + import { register } from "./register"; -import { CaptureUpdateAction } from "../store"; -import { Fonts, getLineHeight } from "../fonts"; -import { - bindLinearElement, - bindPointToSnapToElementOutline, - calculateFixedPointForElbowArrowBinding, - getHoveredElementForBinding, - updateBoundElements, -} from "../element/binding"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; -import { Range } from "../components/Range"; + +import type { + Arrowhead, + ExcalidrawBindableElement, + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, + FontFamilyValues, + TextAlign, + VerticalAlign, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { CaptureUpdateActionType } from "../store"; +import type { AppClassProperties, AppState, Primitive } from "../types"; const FONT_SIZE_RELATIVE_INCREASE_STEP = 0.1; diff --git a/packages/excalidraw/actions/actionSelectAll.ts b/packages/excalidraw/actions/actionSelectAll.ts index 61c278053..5f6d7eabc 100644 --- a/packages/excalidraw/actions/actionSelectAll.ts +++ b/packages/excalidraw/actions/actionSelectAll.ts @@ -1,13 +1,15 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import { selectGroupsForSelectedElements } from "../groups"; -import { getNonDeletedElements, isTextElement } from "../element"; -import type { ExcalidrawElement } from "../element/types"; -import { isLinearElement } from "../element/typeChecks"; -import { LinearElementEditor } from "../element/linearElementEditor"; import { selectAllIcon } from "../components/icons"; +import { getNonDeletedElements, isTextElement } from "../element"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { isLinearElement } from "../element/typeChecks"; +import { selectGroupsForSelectedElements } from "../groups"; +import { KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + +import type { ExcalidrawElement } from "../element/types"; + export const actionSelectAll = register({ name: "selectAll", label: "labels.selectAll", diff --git a/packages/excalidraw/actions/actionStyles.ts b/packages/excalidraw/actions/actionStyles.ts index 01f804062..ea517c442 100644 --- a/packages/excalidraw/actions/actionStyles.ts +++ b/packages/excalidraw/actions/actionStyles.ts @@ -1,17 +1,15 @@ -import { - isTextElement, - isExcalidrawElement, - redrawTextBoundingBox, -} from "../element"; -import { CODES, KEYS } from "../keys"; -import { t } from "../i18n"; -import { register } from "./register"; -import { newElementWith } from "../element/mutateElement"; +import { paintIcon } from "../components/icons"; import { DEFAULT_FONT_SIZE, DEFAULT_FONT_FAMILY, DEFAULT_TEXT_ALIGN, } from "../constants"; +import { + isTextElement, + isExcalidrawElement, + redrawTextBoundingBox, +} from "../element"; +import { newElementWith } from "../element/mutateElement"; import { getBoundTextElement } from "../element/textElement"; import { hasBoundTextElement, @@ -20,11 +18,15 @@ import { isFrameLikeElement, isArrowElement, } from "../element/typeChecks"; -import { getSelectedElements } from "../scene"; -import type { ExcalidrawTextElement } from "../element/types"; -import { paintIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { getLineHeight } from "../fonts"; +import { t } from "../i18n"; +import { CODES, KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { ExcalidrawTextElement } from "../element/types"; // `copiedStyles` is exported only for tests. export let copiedStyles: string = "{}"; diff --git a/packages/excalidraw/actions/actionTextAutoResize.ts b/packages/excalidraw/actions/actionTextAutoResize.ts index 29f54c9a7..b9ad7783f 100644 --- a/packages/excalidraw/actions/actionTextAutoResize.ts +++ b/packages/excalidraw/actions/actionTextAutoResize.ts @@ -3,10 +3,12 @@ import { newElementWith } from "../element/mutateElement"; import { measureText } from "../element/textMeasurements"; import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; -import type { AppClassProperties } from "../types"; import { getFontString } from "../utils"; + import { register } from "./register"; +import type { AppClassProperties } from "../types"; + export const actionTextAutoResize = register({ name: "autoResize", label: "labels.autoResize", diff --git a/packages/excalidraw/actions/actionToggleGridMode.tsx b/packages/excalidraw/actions/actionToggleGridMode.tsx index 69d657057..98360e843 100644 --- a/packages/excalidraw/actions/actionToggleGridMode.tsx +++ b/packages/excalidraw/actions/actionToggleGridMode.tsx @@ -1,9 +1,11 @@ -import { CODES, KEYS } from "../keys"; -import { register } from "./register"; -import type { AppState } from "../types"; import { gridIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + +import type { AppState } from "../types"; + export const actionToggleGridMode = register({ name: "gridMode", icon: gridIcon, diff --git a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx index 1ae3cbe0b..d51124132 100644 --- a/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx +++ b/packages/excalidraw/actions/actionToggleObjectsSnapMode.tsx @@ -1,6 +1,7 @@ import { magnetIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleObjectsSnapMode = register({ diff --git a/packages/excalidraw/actions/actionToggleSearchMenu.ts b/packages/excalidraw/actions/actionToggleSearchMenu.ts index 9261e79c4..75d9074c8 100644 --- a/packages/excalidraw/actions/actionToggleSearchMenu.ts +++ b/packages/excalidraw/actions/actionToggleSearchMenu.ts @@ -1,9 +1,11 @@ -import { KEYS } from "../keys"; -import { register } from "./register"; -import type { AppState } from "../types"; import { searchIcon } from "../components/icons"; -import { CaptureUpdateAction } from "../store"; import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants"; +import { KEYS } from "../keys"; +import { CaptureUpdateAction } from "../store"; + +import { register } from "./register"; + +import type { AppState } from "../types"; export const actionToggleSearchMenu = register({ name: "searchMenu", diff --git a/packages/excalidraw/actions/actionToggleStats.tsx b/packages/excalidraw/actions/actionToggleStats.tsx index e28d099ae..d0cdc64a3 100644 --- a/packages/excalidraw/actions/actionToggleStats.tsx +++ b/packages/excalidraw/actions/actionToggleStats.tsx @@ -1,8 +1,9 @@ -import { register } from "./register"; -import { CODES, KEYS } from "../keys"; import { abacusIcon } from "../components/icons"; +import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { register } from "./register"; + export const actionToggleStats = register({ name: "stats", label: "stats.fullTitle", diff --git a/packages/excalidraw/actions/actionToggleViewMode.tsx b/packages/excalidraw/actions/actionToggleViewMode.tsx index cae3b095e..055135263 100644 --- a/packages/excalidraw/actions/actionToggleViewMode.tsx +++ b/packages/excalidraw/actions/actionToggleViewMode.tsx @@ -1,6 +1,7 @@ import { eyeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleViewMode = register({ diff --git a/packages/excalidraw/actions/actionToggleZenMode.tsx b/packages/excalidraw/actions/actionToggleZenMode.tsx index 31afd3f3a..31c72bf95 100644 --- a/packages/excalidraw/actions/actionToggleZenMode.tsx +++ b/packages/excalidraw/actions/actionToggleZenMode.tsx @@ -1,6 +1,7 @@ import { coffeeIcon } from "../components/icons"; import { CODES, KEYS } from "../keys"; import { CaptureUpdateAction } from "../store"; + import { register } from "./register"; export const actionToggleZenMode = register({ diff --git a/packages/excalidraw/actions/actionZindex.tsx b/packages/excalidraw/actions/actionZindex.tsx index 4097b2df1..82d3d77da 100644 --- a/packages/excalidraw/actions/actionZindex.tsx +++ b/packages/excalidraw/actions/actionZindex.tsx @@ -1,13 +1,3 @@ -import { - moveOneLeft, - moveOneRight, - moveAllLeft, - moveAllRight, -} from "../zindex"; -import { KEYS, CODES } from "../keys"; -import { t } from "../i18n"; -import { getShortcutKey } from "../utils"; -import { register } from "./register"; import { BringForwardIcon, BringToFrontIcon, @@ -15,7 +5,18 @@ import { SendToBackIcon, } from "../components/icons"; import { isDarwin } from "../constants"; +import { t } from "../i18n"; +import { KEYS, CODES } from "../keys"; import { CaptureUpdateAction } from "../store"; +import { getShortcutKey } from "../utils"; +import { + moveOneLeft, + moveOneRight, + moveAllLeft, + moveAllRight, +} from "../zindex"; + +import { register } from "./register"; export const actionSendBackward = register({ name: "sendBackward", diff --git a/packages/excalidraw/actions/manager.tsx b/packages/excalidraw/actions/manager.tsx index f37843800..d3609640e 100644 --- a/packages/excalidraw/actions/manager.tsx +++ b/packages/excalidraw/actions/manager.tsx @@ -1,4 +1,13 @@ import React from "react"; + +import { trackEvent } from "../analytics"; +import { isPromiseLike } from "../utils"; + +import type { + ExcalidrawElement, + OrderedExcalidrawElement, +} from "../element/types"; +import type { AppClassProperties, AppState } from "../types"; import type { Action, UpdaterFn, @@ -7,13 +16,6 @@ import type { PanelComponentProps, ActionSource, } from "./types"; -import type { - ExcalidrawElement, - OrderedExcalidrawElement, -} from "../element/types"; -import type { AppClassProperties, AppState } from "../types"; -import { trackEvent } from "../analytics"; -import { isPromiseLike } from "../utils"; const trackAction = ( action: Action, diff --git a/packages/excalidraw/actions/shortcuts.ts b/packages/excalidraw/actions/shortcuts.ts index 451609dff..89a7c5ae2 100644 --- a/packages/excalidraw/actions/shortcuts.ts +++ b/packages/excalidraw/actions/shortcuts.ts @@ -1,7 +1,8 @@ import { isDarwin } from "../constants"; import { t } from "../i18n"; -import type { SubtypeOf } from "../utility-types"; import { getShortcutKey } from "../utils"; + +import type { SubtypeOf } from "../utility-types"; import type { ActionName } from "./types"; export type ShortcutName = diff --git a/packages/excalidraw/actions/types.ts b/packages/excalidraw/actions/types.ts index 71ac9f4ab..c30f53f5e 100644 --- a/packages/excalidraw/actions/types.ts +++ b/packages/excalidraw/actions/types.ts @@ -1,8 +1,8 @@ -import type React from "react"; import type { ExcalidrawElement, OrderedExcalidrawElement, } from "../element/types"; +import type { CaptureUpdateActionType } from "../store"; import type { AppClassProperties, AppState, @@ -10,7 +10,7 @@ import type { BinaryFiles, UIAppState, } from "../types"; -import type { CaptureUpdateActionType } from "../store"; +import type React from "react"; export type ActionSource = | "ui" diff --git a/packages/excalidraw/align.ts b/packages/excalidraw/align.ts index 113ba274c..36e5d6603 100644 --- a/packages/excalidraw/align.ts +++ b/packages/excalidraw/align.ts @@ -1,9 +1,10 @@ -import type { ElementsMap, ExcalidrawElement } from "./element/types"; -import { mutateElement } from "./element/mutateElement"; -import type { BoundingBox } from "./element/bounds"; -import { getCommonBoundingBox } from "./element/bounds"; -import { getMaximumGroups } from "./groups"; import { updateBoundElements } from "./element/binding"; +import { getCommonBoundingBox } from "./element/bounds"; +import { mutateElement } from "./element/mutateElement"; +import { getMaximumGroups } from "./groups"; + +import type { BoundingBox } from "./element/bounds"; +import type { ElementsMap, ExcalidrawElement } from "./element/types"; import type Scene from "./scene/Scene"; export interface Alignment { diff --git a/packages/excalidraw/animated-trail.ts b/packages/excalidraw/animated-trail.ts index 97a005461..a20460771 100644 --- a/packages/excalidraw/animated-trail.ts +++ b/packages/excalidraw/animated-trail.ts @@ -1,10 +1,13 @@ -import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; import { LaserPointer } from "@excalidraw/laser-pointer"; -import type { AnimationFrameHandler } from "./animation-frame-handler"; -import type { AppState } from "./types"; -import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils"; -import type App from "./components/App"; + +import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; + import { SVG_NS } from "./constants"; +import { getSvgPathFromStroke, sceneCoordsToViewportCoords } from "./utils"; + +import type { AnimationFrameHandler } from "./animation-frame-handler"; +import type App from "./components/App"; +import type { AppState } from "./types"; export interface Trail { start(container: SVGSVGElement): void; diff --git a/packages/excalidraw/appState.ts b/packages/excalidraw/appState.ts index 644949e7c..acda8468b 100644 --- a/packages/excalidraw/appState.ts +++ b/packages/excalidraw/appState.ts @@ -11,6 +11,7 @@ import { THEME, DEFAULT_GRID_STEP, } from "./constants"; + import type { AppState, NormalizedZoomValue } from "./types"; const defaultExportScale = EXPORT_SCALES.includes(devicePixelRatio) diff --git a/packages/excalidraw/change.ts b/packages/excalidraw/change.ts index 1cbf39e89..206f3dcc7 100644 --- a/packages/excalidraw/change.ts +++ b/packages/excalidraw/change.ts @@ -1,5 +1,4 @@ import { ENV } from "./constants"; -import type { BindableProp, BindingProp } from "./element/binding"; import { BoundElement, BindableElement, @@ -7,7 +6,6 @@ import { updateBoundElements, } from "./element/binding"; import { LinearElementEditor } from "./element/linearElementEditor"; -import type { ElementUpdate } from "./element/mutateElement"; import { mutateElement, newElementWith } from "./element/mutateElement"; import { getBoundTextElementId, @@ -20,6 +18,19 @@ import { isImageElement, isTextElement, } from "./element/typeChecks"; +import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex"; +import { getNonDeletedGroupIds } from "./groups"; +import { getObservedAppState } from "./store"; +import { + arrayToMap, + arrayToObject, + assertNever, + isShallowEqual, + toBrandedType, +} from "./utils"; + +import type { BindableProp, BindingProp } from "./element/binding"; +import type { ElementUpdate } from "./element/mutateElement"; import type { ExcalidrawElement, ExcalidrawImageElement, @@ -30,9 +41,6 @@ import type { OrderedExcalidrawElement, SceneElementsMap, } from "./element/types"; -import { orderByFractionalIndex, syncMovedIndices } from "./fractionalIndex"; -import { getNonDeletedGroupIds } from "./groups"; -import { getObservedAppState } from "./store"; import type { AppState, ObservedAppState, @@ -40,13 +48,6 @@ import type { ObservedStandaloneAppState, } from "./types"; import type { SubtypeOf, ValueOf } from "./utility-types"; -import { - arrayToMap, - arrayToObject, - assertNever, - isShallowEqual, - toBrandedType, -} from "./utils"; /** * Represents the difference between two objects of the same type. diff --git a/packages/excalidraw/charts.test.ts b/packages/excalidraw/charts.test.ts index fcd8823a9..94fa92fa0 100644 --- a/packages/excalidraw/charts.test.ts +++ b/packages/excalidraw/charts.test.ts @@ -1,6 +1,7 @@ -import type { Spreadsheet } from "./charts"; import { tryParseCells, tryParseNumber, VALID_SPREADSHEET } from "./charts"; +import type { Spreadsheet } from "./charts"; + describe("charts", () => { describe("tryParseNumber", () => { it.each<[string, number]>([ diff --git a/packages/excalidraw/charts.ts b/packages/excalidraw/charts.ts index 65d17e228..e54c55f28 100644 --- a/packages/excalidraw/charts.ts +++ b/packages/excalidraw/charts.ts @@ -1,5 +1,7 @@ -import type { Radians } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + import { COLOR_PALETTE, DEFAULT_CHART_COLOR_INDEX, @@ -11,9 +13,10 @@ import { VERTICAL_ALIGN, } from "./constants"; import { newElement, newLinearElement, newTextElement } from "./element"; -import type { NonDeletedExcalidrawElement } from "./element/types"; import { randomId } from "./random"; +import type { NonDeletedExcalidrawElement } from "./element/types"; + export type ChartElements = readonly NonDeletedExcalidrawElement[]; const BAR_WIDTH = 32; diff --git a/packages/excalidraw/clients.ts b/packages/excalidraw/clients.ts index 29d240011..6cf4613a8 100644 --- a/packages/excalidraw/clients.ts +++ b/packages/excalidraw/clients.ts @@ -6,6 +6,7 @@ import { UserIdleState, } from "./constants"; import { roundRect } from "./renderer/roundRect"; + import type { InteractiveCanvasRenderConfig } from "./scene/types"; import type { Collaborator, diff --git a/packages/excalidraw/clipboard.ts b/packages/excalidraw/clipboard.ts index 296a3415a..1b0e9942a 100644 --- a/packages/excalidraw/clipboard.ts +++ b/packages/excalidraw/clipboard.ts @@ -1,25 +1,26 @@ -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "./element/types"; -import type { BinaryFiles } from "./types"; -import type { Spreadsheet } from "./charts"; import { tryParseSpreadsheet, VALID_SPREADSHEET } from "./charts"; import { ALLOWED_PASTE_MIME_TYPES, EXPORT_DATA_TYPES, MIME_TYPES, } from "./constants"; +import { createFile, isSupportedImageFileType } from "./data/blob"; +import { mutateElement } from "./element/mutateElement"; +import { deepCopyElement } from "./element/newElement"; import { isFrameLikeElement, isInitializedImageElement, } from "./element/typeChecks"; -import { deepCopyElement } from "./element/newElement"; -import { mutateElement } from "./element/mutateElement"; +import { ExcalidrawError } from "./errors"; import { getContainingFrame } from "./frame"; import { arrayToMap, isMemberOf, isPromiseLike } from "./utils"; -import { createFile, isSupportedImageFileType } from "./data/blob"; -import { ExcalidrawError } from "./errors"; + +import type { Spreadsheet } from "./charts"; +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "./element/types"; +import type { BinaryFiles } from "./types"; type ElementsClipboard = { type: typeof EXPORT_DATA_TYPES.excalidrawClipboard; diff --git a/packages/excalidraw/colors.ts b/packages/excalidraw/colors.ts index e4cd67a94..84d04bcf4 100644 --- a/packages/excalidraw/colors.ts +++ b/packages/excalidraw/colors.ts @@ -1,4 +1,5 @@ import oc from "open-color"; + import type { Merge } from "./utility-types"; // FIXME can't put to utils.ts rn because of circular dependency diff --git a/packages/excalidraw/components/Actions.tsx b/packages/excalidraw/components/Actions.tsx index cd9120fbc..c74c1ad85 100644 --- a/packages/excalidraw/components/Actions.tsx +++ b/packages/excalidraw/components/Actions.tsx @@ -1,13 +1,25 @@ +import clsx from "clsx"; import { useState } from "react"; -import type { ActionManager } from "../actions/manager"; -import type { - ExcalidrawElement, - ExcalidrawElementType, - NonDeletedElementsMap, - NonDeletedSceneElementsMap, -} from "../element/types"; + +import { actionToggleZenMode } from "../actions"; + +import { KEYS } from "../keys"; +import { CLASSES } from "../constants"; +import { alignActionsPredicate } from "../actions/actionAlign"; +import { trackEvent } from "../analytics"; +import { useTunnels } from "../context/tunnels"; +import { + shouldAllowVerticalAlign, + suppportsHorizontalAlign, +} from "../element/textElement"; +import { + hasBoundTextElement, + isElbowArrow, + isImageElement, + isLinearElement, + isTextElement, +} from "../element/typeChecks"; import { t } from "../i18n"; -import { useDevice } from "./App"; import { canChangeRoundness, canHaveArrowheads, @@ -16,29 +28,16 @@ import { hasStrokeStyle, hasStrokeWidth, } from "../scene"; -import { SHAPES } from "../shapes"; -import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types"; -import { capitalizeString, isTransparent } from "../utils"; -import Stack from "./Stack"; -import { ToolButton } from "./ToolButton"; import { hasStrokeColor, toolIsArrow } from "../scene/comparisons"; -import { trackEvent } from "../analytics"; -import { - hasBoundTextElement, - isElbowArrow, - isImageElement, - isLinearElement, - isTextElement, -} from "../element/typeChecks"; -import clsx from "clsx"; -import { actionToggleZenMode } from "../actions"; -import { Tooltip } from "./Tooltip"; -import { - shouldAllowVerticalAlign, - suppportsHorizontalAlign, -} from "../element/textElement"; +import { SHAPES } from "../shapes"; +import { capitalizeString, isTransparent } from "../utils"; import "./Actions.scss"; + +import { useDevice } from "./App"; +import Stack from "./Stack"; +import { ToolButton } from "./ToolButton"; +import { Tooltip } from "./Tooltip"; import DropdownMenu from "./dropdownMenu/DropdownMenu"; import { EmbedIcon, @@ -48,10 +47,15 @@ import { laserPointerToolIcon, MagicIcon, } from "./icons"; -import { KEYS } from "../keys"; -import { useTunnels } from "../context/tunnels"; -import { CLASSES } from "../constants"; -import { alignActionsPredicate } from "../actions/actionAlign"; + +import type { + ExcalidrawElement, + ExcalidrawElementType, + NonDeletedElementsMap, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { AppClassProperties, AppProps, UIAppState, Zoom } from "../types"; +import type { ActionManager } from "../actions/manager"; export const canChangeStrokeColor = ( appState: UIAppState, diff --git a/packages/excalidraw/components/ActiveConfirmDialog.tsx b/packages/excalidraw/components/ActiveConfirmDialog.tsx index 699fbc61f..00c6ad579 100644 --- a/packages/excalidraw/components/ActiveConfirmDialog.tsx +++ b/packages/excalidraw/components/ActiveConfirmDialog.tsx @@ -1,6 +1,7 @@ import { actionClearCanvas } from "../actions"; -import { t } from "../i18n"; import { atom, useAtom } from "../editor-jotai"; +import { t } from "../i18n"; + import { useExcalidrawActionManager } from "./App"; import ConfirmDialog from "./ConfirmDialog"; diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index dc6d28782..6017b73b7 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -1,10 +1,26 @@ +import { + clamp, + pointFrom, + pointDistance, + vector, + pointRotateRads, + vectorScale, + vectorFromPoint, + vectorSubtract, + vectorDot, + vectorNormalize, +} from "@excalidraw/math"; +import { isPointInShape } from "@excalidraw/utils/collision"; +import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape"; +import clsx from "clsx"; +import throttle from "lodash.throttle"; +import { nanoid } from "nanoid"; import React, { useContext } from "react"; import { flushSync } from "react-dom"; - -import type { RoughCanvas } from "roughjs/bin/canvas"; import rough from "roughjs/bin/rough"; -import clsx from "clsx"; -import { nanoid } from "nanoid"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + import { actionAddToLibrary, actionBringForward, @@ -37,17 +53,29 @@ import { actionToggleObjectsSnapMode, actionToggleCropEditor, } from "../actions"; +import { actionWrapTextInContainer } from "../actions/actionBoundText"; +import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas"; +import { actionPaste } from "../actions/actionClipboard"; +import { actionCopyElementLink } from "../actions/actionElementLink"; +import { actionUnlockAllElements } from "../actions/actionElementLock"; +import { + actionRemoveAllElementsFromFrame, + actionSelectAllElementsInFrame, + actionWrapSelectionInFrame, +} from "../actions/actionFrame"; import { createRedoAction, createUndoAction } from "../actions/actionHistory"; +import { actionTextAutoResize } from "../actions/actionTextAutoResize"; +import { actionToggleViewMode } from "../actions/actionToggleViewMode"; import { ActionManager } from "../actions/manager"; import { actions } from "../actions/register"; -import type { Action, ActionResult } from "../actions/types"; +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { trackEvent } from "../analytics"; +import { AnimationFrameHandler } from "../animation-frame-handler"; import { getDefaultAppState, isEraserActive, isHandToolActive, } from "../appState"; -import type { PastedMixedContent } from "../clipboard"; import { copyTextToSystemClipboard, parseClipboard } from "../clipboard"; import { APP_NAME, @@ -92,7 +120,6 @@ import { isSafari, type EXPORT_IMAGE_TYPES, } from "../constants"; -import type { ExportedElements } from "../data"; import { exportCanvas, loadFromBlob } from "../data"; import Library, { distributeLibraryItemsOnSquareGrid } from "../data/library"; import { restore, restoreElements } from "../data/restore"; @@ -167,30 +194,6 @@ import { isFlowchartNodeElement, isBindableElement, } from "../element/typeChecks"; -import type { - ExcalidrawBindableElement, - ExcalidrawElement, - ExcalidrawFreeDrawElement, - ExcalidrawGenericElement, - ExcalidrawLinearElement, - ExcalidrawTextElement, - NonDeleted, - InitializedExcalidrawImageElement, - ExcalidrawImageElement, - FileId, - NonDeletedExcalidrawElement, - ExcalidrawTextContainer, - ExcalidrawFrameLikeElement, - ExcalidrawMagicFrameElement, - ExcalidrawIframeLikeElement, - IframeData, - ExcalidrawIframeElement, - ExcalidrawEmbeddableElement, - Ordered, - MagicGenerationData, - ExcalidrawNonSelectionElement, - ExcalidrawArrowElement, -} from "../element/types"; import { getCenter, getDistance } from "../gesture"; import { editGroupForSelectedElement, @@ -224,10 +227,6 @@ import { isSomeElementSelected, } from "../scene"; import Scene from "../scene/Scene"; -import type { - RenderInteractiveSceneCallback, - ScrollBars, -} from "../scene/types"; import { getStateForZoom } from "../scene/zoom"; import { findShapeByKey, @@ -236,36 +235,6 @@ import { getElementShape, isPathALoop, } from "../shapes"; -import { getSelectionBoxShape } from "@excalidraw/utils/geometry/shape"; -import { isPointInShape } from "@excalidraw/utils/collision"; -import type { - AppClassProperties, - AppProps, - AppState, - BinaryFileData, - DataURL, - ExcalidrawImperativeAPI, - BinaryFiles, - Gesture, - GestureEvent, - LibraryItems, - PointerDownState, - SceneData, - Device, - FrameNameBoundsCache, - SidebarName, - SidebarTabName, - KeyboardModifiersObject, - CollaboratorPointer, - ToolType, - OnUserFollowedPayload, - UnsubscribeCallback, - EmbedsValidationStatus, - ElementsPendingErasure, - GenerateDiagramToCode, - NullableGridSize, - Offsets, -} from "../types"; import { debounce, distance, @@ -299,11 +268,6 @@ import { maybeParseEmbedSrc, getEmbedLink, } from "../element/embeddable"; -import type { ContextMenuItems } from "./ContextMenu"; -import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu"; -import LayerUI from "./LayerUI"; -import { Toast } from "./Toast"; -import { actionToggleViewMode } from "../actions/actionToggleViewMode"; import { dataURLToFile, dataURLToString, @@ -326,8 +290,6 @@ import { normalizeSVG, updateImageCache as _updateImageCache, } from "../element/image"; -import throttle from "lodash.throttle"; -import type { FileSystemHandle } from "../data/filesystem"; import { fileOpen } from "../data/filesystem"; import { bindTextToShapeAfterDuplication, @@ -343,7 +305,6 @@ import { } from "../components/hyperlink/Hyperlink"; import { isLocalLink, normalizeLink, toValidURL } from "../data/url"; import { shouldShowBoundingBox } from "../element/transformHandles"; -import { actionUnlockAllElements } from "../actions/actionElementLock"; import { Fonts, getLineHeight } from "../fonts"; import { getFrameChildren, @@ -366,15 +327,7 @@ import { excludeElementsInFramesFromSelection, makeNextSelectedElementIds, } from "../scene/selection"; -import { actionPaste } from "../actions/actionClipboard"; -import { - actionRemoveAllElementsFromFrame, - actionSelectAllElementsInFrame, - actionWrapSelectionInFrame, -} from "../actions/actionFrame"; -import { actionToggleHandTool, zoomToFit } from "../actions/actionCanvas"; import { editorJotaiStore } from "../editor-jotai"; -import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; import { ImageSceneDataError } from "../errors"; import { getSnapLinesAtPointer, @@ -389,17 +342,9 @@ import { isGridModeEnabled, getGridPoint, } from "../snapping"; -import { actionWrapTextInContainer } from "../actions/actionBoundText"; -import BraveMeasureTextError from "./BraveMeasureTextError"; -import { activeEyeDropperAtom } from "./EyeDropper"; -import type { ExcalidrawElementSkeleton } from "../data/transform"; import { convertToExcalidrawElements } from "../data/transform"; -import type { ValueOf } from "../utility-types"; -import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; -import { StaticCanvas, InteractiveCanvas } from "./canvases"; import { Renderer } from "../scene/Renderer"; import { ShapeCache } from "../scene/ShapeCache"; -import { SVGLayer } from "./SVGLayer"; import { setEraserCursor, setCursor, @@ -409,11 +354,7 @@ import { import { Emitter } from "../emitter"; import { ElementCanvasButtons } from "../element/ElementCanvasButtons"; import { COLOR_PALETTE } from "../colors"; -import { ElementCanvasButton } from "./MagicButton"; -import { MagicIcon, copyIcon, fullscreenIcon } from "./icons"; -import FollowMode from "./FollowMode/FollowMode"; import { Store, CaptureUpdateAction } from "../store"; -import { AnimationFrameHandler } from "../animation-frame-handler"; import { AnimatedTrail } from "../animated-trail"; import { LaserTrails } from "../laser-trails"; import { withBatchedUpdates, withBatchedUpdatesThrottled } from "../reactUtils"; @@ -426,37 +367,15 @@ import { import { textWysiwyg } from "../element/textWysiwyg"; import { isOverScrollBars } from "../scene/scrollbars"; import { syncInvalidIndices, syncMovedIndices } from "../fractionalIndex"; -import { - isPointHittingLink, - isPointHittingLinkIcon, -} from "./hyperlink/helpers"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; -import { actionTextAutoResize } from "../actions/actionTextAutoResize"; import { getVisibleSceneBounds } from "../element/bounds"; import { isMaybeMermaidDefinition } from "../mermaid"; -import NewElementCanvas from "./canvases/NewElementCanvas"; import { FlowChartCreator, FlowChartNavigator, getLinkDirectionFromKey, } from "../element/flowchart"; -import { searchItemInFocusAtom } from "./SearchMenu"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { - clamp, - pointFrom, - pointDistance, - vector, - pointRotateRads, - vectorScale, - vectorFromPoint, - vectorSubtract, - vectorDot, - vectorNormalize, -} from "@excalidraw/math"; import { cropElement } from "../element/cropElement"; import { wrapText } from "../element/textWrapping"; -import { actionCopyElementLink } from "../actions/actionElementLink"; import { isElementLink, parseElementLinkFromURL } from "../element/elementLink"; import { isMeasureTextSupported, @@ -468,6 +387,90 @@ import { getMinTextElementWidth, } from "../element/textMeasurements"; +import { activeConfirmDialogAtom } from "./ActiveConfirmDialog"; +import BraveMeasureTextError from "./BraveMeasureTextError"; +import { ContextMenu, CONTEXT_MENU_SEPARATOR } from "./ContextMenu"; +import { activeEyeDropperAtom } from "./EyeDropper"; +import FollowMode from "./FollowMode/FollowMode"; +import LayerUI from "./LayerUI"; +import { ElementCanvasButton } from "./MagicButton"; +import { SVGLayer } from "./SVGLayer"; +import { searchItemInFocusAtom } from "./SearchMenu"; +import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; +import { StaticCanvas, InteractiveCanvas } from "./canvases"; +import NewElementCanvas from "./canvases/NewElementCanvas"; +import { + isPointHittingLink, + isPointHittingLinkIcon, +} from "./hyperlink/helpers"; +import { MagicIcon, copyIcon, fullscreenIcon } from "./icons"; +import { Toast } from "./Toast"; + +import type { Action, ActionResult } from "../actions/types"; +import type { PastedMixedContent } from "../clipboard"; +import type { ExportedElements } from "../data"; +import type { ContextMenuItems } from "./ContextMenu"; +import type { FileSystemHandle } from "../data/filesystem"; +import type { ExcalidrawElementSkeleton } from "../data/transform"; +import type { + ExcalidrawBindableElement, + ExcalidrawElement, + ExcalidrawFreeDrawElement, + ExcalidrawGenericElement, + ExcalidrawLinearElement, + ExcalidrawTextElement, + NonDeleted, + InitializedExcalidrawImageElement, + ExcalidrawImageElement, + FileId, + NonDeletedExcalidrawElement, + ExcalidrawTextContainer, + ExcalidrawFrameLikeElement, + ExcalidrawMagicFrameElement, + ExcalidrawIframeLikeElement, + IframeData, + ExcalidrawIframeElement, + ExcalidrawEmbeddableElement, + Ordered, + MagicGenerationData, + ExcalidrawNonSelectionElement, + ExcalidrawArrowElement, +} from "../element/types"; +import type { + RenderInteractiveSceneCallback, + ScrollBars, +} from "../scene/types"; +import type { + AppClassProperties, + AppProps, + AppState, + BinaryFileData, + DataURL, + ExcalidrawImperativeAPI, + BinaryFiles, + Gesture, + GestureEvent, + LibraryItems, + PointerDownState, + SceneData, + Device, + FrameNameBoundsCache, + SidebarName, + SidebarTabName, + KeyboardModifiersObject, + CollaboratorPointer, + ToolType, + OnUserFollowedPayload, + UnsubscribeCallback, + EmbedsValidationStatus, + ElementsPendingErasure, + GenerateDiagramToCode, + NullableGridSize, + Offsets, +} from "../types"; +import type { ValueOf } from "../utility-types"; +import type { RoughCanvas } from "roughjs/bin/canvas"; + const AppContext = React.createContext(null!); const AppPropsContext = React.createContext(null!); diff --git a/packages/excalidraw/components/Avatar.tsx b/packages/excalidraw/components/Avatar.tsx index 9ddc319c6..648fb5fce 100644 --- a/packages/excalidraw/components/Avatar.tsx +++ b/packages/excalidraw/components/Avatar.tsx @@ -1,8 +1,9 @@ -import "./Avatar.scss"; - -import React, { useState } from "react"; -import { getNameInitial } from "../clients"; import clsx from "clsx"; +import React, { useState } from "react"; + +import { getNameInitial } from "../clients"; + +import "./Avatar.scss"; type AvatarProps = { onClick: (e: React.MouseEvent) => void; diff --git a/packages/excalidraw/components/Button.tsx b/packages/excalidraw/components/Button.tsx index 779cee582..9512d607f 100644 --- a/packages/excalidraw/components/Button.tsx +++ b/packages/excalidraw/components/Button.tsx @@ -1,6 +1,8 @@ import clsx from "clsx"; import React from "react"; + import { composeEventHandlers } from "../utils"; + import "./Button.scss"; interface ButtonProps diff --git a/packages/excalidraw/components/ButtonIcon.tsx b/packages/excalidraw/components/ButtonIcon.tsx index cbbd73df9..27b4dc3d8 100644 --- a/packages/excalidraw/components/ButtonIcon.tsx +++ b/packages/excalidraw/components/ButtonIcon.tsx @@ -1,9 +1,10 @@ -import { forwardRef } from "react"; -import type { JSX } from "react"; import clsx from "clsx"; +import { forwardRef } from "react"; import "./ButtonIcon.scss"; +import type { JSX } from "react"; + interface ButtonIconProps { icon: JSX.Element; title: string; diff --git a/packages/excalidraw/components/ButtonIconCycle.tsx b/packages/excalidraw/components/ButtonIconCycle.tsx index b73a8ec5a..53c5e12bd 100644 --- a/packages/excalidraw/components/ButtonIconCycle.tsx +++ b/packages/excalidraw/components/ButtonIconCycle.tsx @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import clsx from "clsx"; +import type { JSX } from "react"; + export const ButtonIconCycle = ({ options, value, diff --git a/packages/excalidraw/components/ButtonIconSelect.tsx b/packages/excalidraw/components/ButtonIconSelect.tsx index 26191b50b..45665e4ca 100644 --- a/packages/excalidraw/components/ButtonIconSelect.tsx +++ b/packages/excalidraw/components/ButtonIconSelect.tsx @@ -1,7 +1,9 @@ -import type { JSX } from "react"; import clsx from "clsx"; + import { ButtonIcon } from "./ButtonIcon"; +import type { JSX } from "react"; + // TODO: It might be "clever" to add option.icon to the existing component export const ButtonIconSelect = ( props: { diff --git a/packages/excalidraw/components/CheckboxItem.tsx b/packages/excalidraw/components/CheckboxItem.tsx index 21c5cfafd..9c757eab5 100644 --- a/packages/excalidraw/components/CheckboxItem.tsx +++ b/packages/excalidraw/components/CheckboxItem.tsx @@ -1,5 +1,6 @@ -import React from "react"; import clsx from "clsx"; +import React from "react"; + import { checkIcon } from "./icons"; import "./CheckboxItem.scss"; diff --git a/packages/excalidraw/components/ColorPicker/ColorInput.tsx b/packages/excalidraw/components/ColorPicker/ColorInput.tsx index 837c88709..dc7d572a3 100644 --- a/packages/excalidraw/components/ColorPicker/ColorInput.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorInput.tsx @@ -1,15 +1,18 @@ -import { useCallback, useEffect, useRef, useState } from "react"; -import { getColor } from "./ColorPicker"; -import type { ColorPickerType } from "./colorPickerUtils"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; -import { eyeDropperIcon } from "../icons"; -import { useAtom } from "../../editor-jotai"; -import { KEYS } from "../../keys"; -import { activeEyeDropperAtom } from "../EyeDropper"; import clsx from "clsx"; +import { useCallback, useEffect, useRef, useState } from "react"; + +import { useAtom } from "../../editor-jotai"; import { t } from "../../i18n"; -import { useDevice } from "../App"; +import { KEYS } from "../../keys"; import { getShortcutKey } from "../../utils"; +import { useDevice } from "../App"; +import { activeEyeDropperAtom } from "../EyeDropper"; +import { eyeDropperIcon } from "../icons"; + +import { getColor } from "./ColorPicker"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + +import type { ColorPickerType } from "./colorPickerUtils"; interface ColorInputProps { color: string; diff --git a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx index 74d552701..7f6ee8a85 100644 --- a/packages/excalidraw/components/ColorPicker/ColorPicker.tsx +++ b/packages/excalidraw/components/ColorPicker/ColorPicker.tsx @@ -1,26 +1,29 @@ -import { isTransparent } from "../../utils"; -import type { ExcalidrawElement } from "../../element/types"; -import type { AppState } from "../../types"; -import { TopPicks } from "./TopPicks"; -import { ButtonSeparator } from "../ButtonSeparator"; -import { Picker } from "./Picker"; import * as Popover from "@radix-ui/react-popover"; -import type { ColorPickerType } from "./colorPickerUtils"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; -import { useExcalidrawContainer } from "../App"; -import type { ColorTuple, ColorPaletteCustom } from "../../colors"; -import { COLOR_PALETTE } from "../../colors"; -import PickerHeading from "./PickerHeading"; -import { t } from "../../i18n"; import clsx from "clsx"; import { useRef } from "react"; + +import { COLOR_PALETTE } from "../../colors"; import { useAtom } from "../../editor-jotai"; -import { ColorInput } from "./ColorInput"; +import { t } from "../../i18n"; +import { isTransparent } from "../../utils"; +import { useExcalidrawContainer } from "../App"; +import { ButtonSeparator } from "../ButtonSeparator"; import { activeEyeDropperAtom } from "../EyeDropper"; import { PropertiesPopover } from "../PropertiesPopover"; +import { ColorInput } from "./ColorInput"; +import { Picker } from "./Picker"; +import PickerHeading from "./PickerHeading"; +import { TopPicks } from "./TopPicks"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + import "./ColorPicker.scss"; +import type { ColorPickerType } from "./colorPickerUtils"; +import type { ColorTuple, ColorPaletteCustom } from "../../colors"; +import type { ExcalidrawElement } from "../../element/types"; +import type { AppState } from "../../types"; + const isValidColor = (color: string) => { const style = new Option().style; style.color = color; diff --git a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx index 5fe1e3e53..2c735102a 100644 --- a/packages/excalidraw/components/ColorPicker/CustomColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/CustomColorList.tsx @@ -1,8 +1,10 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; -import { activeColorPickerSectionAtom } from "./colorPickerUtils"; + +import { useAtom } from "../../editor-jotai"; + import HotkeyLabel from "./HotkeyLabel"; +import { activeColorPickerSectionAtom } from "./colorPickerUtils"; interface CustomColorListProps { colors: string[]; diff --git a/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx b/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx index 145060d19..6e4d5e39c 100644 --- a/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx +++ b/packages/excalidraw/components/ColorPicker/HotkeyLabel.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { getContrastYIQ } from "./colorPickerUtils"; interface HotkeyLabelProps { diff --git a/packages/excalidraw/components/ColorPicker/Picker.tsx b/packages/excalidraw/components/ColorPicker/Picker.tsx index 88d687670..9f311e9c1 100644 --- a/packages/excalidraw/components/ColorPicker/Picker.tsx +++ b/packages/excalidraw/components/ColorPicker/Picker.tsx @@ -1,28 +1,29 @@ import React, { useEffect, useState } from "react"; -import { t } from "../../i18n"; -import type { ExcalidrawElement } from "../../element/types"; -import { ShadeList } from "./ShadeList"; - -import PickerColorList from "./PickerColorList"; +import { + DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, + DEFAULT_ELEMENT_STROKE_COLOR_INDEX, +} from "../../colors"; +import { EVENT } from "../../constants"; import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; +import { KEYS } from "../../keys"; + import { CustomColorList } from "./CustomColorList"; -import { colorPickerKeyNavHandler } from "./keyboardNavHandlers"; +import PickerColorList from "./PickerColorList"; import PickerHeading from "./PickerHeading"; -import type { ColorPickerType } from "./colorPickerUtils"; +import { ShadeList } from "./ShadeList"; import { activeColorPickerSectionAtom, getColorNameAndShadeFromColor, getMostUsedCustomColors, isCustomColor, } from "./colorPickerUtils"; +import { colorPickerKeyNavHandler } from "./keyboardNavHandlers"; + +import type { ColorPickerType } from "./colorPickerUtils"; import type { ColorPaletteCustom } from "../../colors"; -import { - DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, - DEFAULT_ELEMENT_STROKE_COLOR_INDEX, -} from "../../colors"; -import { KEYS } from "../../keys"; -import { EVENT } from "../../constants"; +import type { ExcalidrawElement } from "../../element/types"; interface PickerProps { color: string; diff --git a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx index f43559d95..b355228f1 100644 --- a/packages/excalidraw/components/ColorPicker/PickerColorList.tsx +++ b/packages/excalidraw/components/ColorPicker/PickerColorList.tsx @@ -1,15 +1,18 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; + +import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; + +import HotkeyLabel from "./HotkeyLabel"; import { activeColorPickerSectionAtom, colorPickerHotkeyBindings, getColorNameAndShadeFromColor, } from "./colorPickerUtils"; -import HotkeyLabel from "./HotkeyLabel"; + import type { ColorPaletteCustom } from "../../colors"; import type { TranslationKeys } from "../../i18n"; -import { t } from "../../i18n"; interface PickerColorListProps { palette: ColorPaletteCustom; diff --git a/packages/excalidraw/components/ColorPicker/ShadeList.tsx b/packages/excalidraw/components/ColorPicker/ShadeList.tsx index 8d3d4cc2a..35d89ea80 100644 --- a/packages/excalidraw/components/ColorPicker/ShadeList.tsx +++ b/packages/excalidraw/components/ColorPicker/ShadeList.tsx @@ -1,12 +1,15 @@ import clsx from "clsx"; -import { useAtom } from "../../editor-jotai"; import { useEffect, useRef } from "react"; + +import { useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; + +import HotkeyLabel from "./HotkeyLabel"; import { activeColorPickerSectionAtom, getColorNameAndShadeFromColor, } from "./colorPickerUtils"; -import HotkeyLabel from "./HotkeyLabel"; -import { t } from "../../i18n"; + import type { ColorPaletteCustom } from "../../colors"; interface ShadeListProps { diff --git a/packages/excalidraw/components/ColorPicker/TopPicks.tsx b/packages/excalidraw/components/ColorPicker/TopPicks.tsx index 5c69d1e43..9bd8fdb9a 100644 --- a/packages/excalidraw/components/ColorPicker/TopPicks.tsx +++ b/packages/excalidraw/components/ColorPicker/TopPicks.tsx @@ -1,11 +1,13 @@ import clsx from "clsx"; -import type { ColorPickerType } from "./colorPickerUtils"; + import { DEFAULT_CANVAS_BACKGROUND_PICKS, DEFAULT_ELEMENT_BACKGROUND_PICKS, DEFAULT_ELEMENT_STROKE_PICKS, } from "../../colors"; +import type { ColorPickerType } from "./colorPickerUtils"; + interface TopPicksProps { onChange: (color: string) => void; type: ColorPickerType; diff --git a/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts b/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts index 2733b7aba..bbb4e587d 100644 --- a/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts +++ b/packages/excalidraw/components/ColorPicker/colorPickerUtils.ts @@ -1,8 +1,9 @@ -import type { ExcalidrawElement } from "../../element/types"; -import type { ColorPickerColor, ColorPaletteCustom } from "../../colors"; import { MAX_CUSTOM_COLORS_USED_IN_CANVAS } from "../../colors"; import { atom } from "../../editor-jotai"; +import type { ColorPickerColor, ColorPaletteCustom } from "../../colors"; +import type { ExcalidrawElement } from "../../element/types"; + export const getColorNameAndShadeFromColor = ({ palette, color, diff --git a/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts b/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts index 7767692ed..c4e321700 100644 --- a/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts +++ b/packages/excalidraw/components/ColorPicker/keyboardNavHandlers.ts @@ -1,16 +1,18 @@ +import { COLORS_PER_ROW, COLOR_PALETTE } from "../../colors"; import { KEYS } from "../../keys"; + +import { + colorPickerHotkeyBindings, + getColorNameAndShadeFromColor, +} from "./colorPickerUtils"; + +import type { ActiveColorPickerSectionAtomType } from "./colorPickerUtils"; import type { ColorPickerColor, ColorPalette, ColorPaletteCustom, } from "../../colors"; -import { COLORS_PER_ROW, COLOR_PALETTE } from "../../colors"; import type { ValueOf } from "../../utility-types"; -import type { ActiveColorPickerSectionAtomType } from "./colorPickerUtils"; -import { - colorPickerHotkeyBindings, - getColorNameAndShadeFromColor, -} from "./colorPickerUtils"; const arrowHandler = ( eventKey: string, diff --git a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx index cc3c782c4..7febb61c9 100644 --- a/packages/excalidraw/components/CommandPalette/CommandPalette.tsx +++ b/packages/excalidraw/components/CommandPalette/CommandPalette.tsx @@ -1,21 +1,34 @@ +import clsx from "clsx"; +import fuzzy from "fuzzy"; import { useEffect, useRef, useState } from "react"; + +import { + actionClearCanvas, + actionLink, + actionToggleSearchMenu, +} from "../../actions"; +import { + actionCopyElementLink, + actionLinkToElement, +} from "../../actions/actionElementLink"; +import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { trackEvent } from "../../analytics"; +import { DEFAULT_SIDEBAR, EVENT } from "../../constants"; +import { useUIAppState } from "../../context/ui-appState"; +import { deburr } from "../../deburr"; +import { atom, useAtom, editorJotaiStore } from "../../editor-jotai"; +import { t } from "../../i18n"; +import { KEYS } from "../../keys"; import { useApp, useAppProps, useExcalidrawActionManager, useExcalidrawSetAppState, } from "../App"; -import { KEYS } from "../../keys"; import { Dialog } from "../Dialog"; +import { InlineIcon } from "../InlineIcon"; import { TextField } from "../TextField"; -import clsx from "clsx"; import { getSelectedElements } from "../../scene"; -import type { Action } from "../../actions/types"; -import type { TranslationKeys } from "../../i18n"; -import { t } from "../../i18n"; -import type { ShortcutName } from "../../actions/shortcuts"; -import { getShortcutFromShortcutName } from "../../actions/shortcuts"; -import { DEFAULT_SIDEBAR, EVENT } from "../../constants"; import { LockedIcon, UnlockedIcon, @@ -28,37 +41,29 @@ import { brainIconThin, LibraryIcon, } from "../icons"; -import fuzzy from "fuzzy"; -import { useUIAppState } from "../../context/ui-appState"; -import type { AppProps, AppState, UIAppState } from "../../types"; + import { capitalizeString, getShortcutKey, isWritableElement, } from "../../utils"; -import { atom, useAtom, editorJotaiStore } from "../../editor-jotai"; -import { deburr } from "../../deburr"; -import type { MarkRequired } from "../../utility-types"; -import { InlineIcon } from "../InlineIcon"; + import { SHAPES } from "../../shapes"; import { canChangeBackgroundColor, canChangeStrokeColor } from "../Actions"; import { useStableCallback } from "../../hooks/useStableCallback"; -import { - actionClearCanvas, - actionLink, - actionToggleSearchMenu, -} from "../../actions"; import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; -import type { CommandPaletteItem } from "./types"; -import * as defaultItems from "./defaultCommandPaletteItems"; -import { trackEvent } from "../../analytics"; import { useStable } from "../../hooks/useStable"; +import * as defaultItems from "./defaultCommandPaletteItems"; + import "./CommandPalette.scss"; -import { - actionCopyElementLink, - actionLinkToElement, -} from "../../actions/actionElementLink"; + +import type { CommandPaletteItem } from "./types"; +import type { AppProps, AppState, UIAppState } from "../../types"; +import type { MarkRequired } from "../../utility-types"; +import type { ShortcutName } from "../../actions/shortcuts"; +import type { TranslationKeys } from "../../i18n"; +import type { Action } from "../../actions/types"; const lastUsedPaletteItem = atom(null); diff --git a/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts b/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts index dea14ff26..485e1767c 100644 --- a/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts +++ b/packages/excalidraw/components/CommandPalette/defaultCommandPaletteItems.ts @@ -1,4 +1,5 @@ import { actionToggleTheme } from "../../actions"; + import type { CommandPaletteItem } from "./types"; export const toggleTheme: CommandPaletteItem = { diff --git a/packages/excalidraw/components/ConfirmDialog.tsx b/packages/excalidraw/components/ConfirmDialog.tsx index 81073ecdb..cb402dd97 100644 --- a/packages/excalidraw/components/ConfirmDialog.tsx +++ b/packages/excalidraw/components/ConfirmDialog.tsx @@ -1,13 +1,16 @@ import { flushSync } from "react-dom"; -import { t } from "../i18n"; -import type { DialogProps } from "./Dialog"; -import { Dialog } from "./Dialog"; -import "./ConfirmDialog.scss"; +import { useSetAtom } from "../editor-jotai"; +import { t } from "../i18n"; + +import { Dialog } from "./Dialog"; import DialogActionButton from "./DialogActionButton"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; import { useExcalidrawContainer, useExcalidrawSetAppState } from "./App"; -import { useSetAtom } from "../editor-jotai"; + +import "./ConfirmDialog.scss"; + +import type { DialogProps } from "./Dialog"; interface Props extends Omit { onConfirm: () => void; diff --git a/packages/excalidraw/components/ContextMenu.tsx b/packages/excalidraw/components/ContextMenu.tsx index 517e5faed..3295d1d09 100644 --- a/packages/excalidraw/components/ContextMenu.tsx +++ b/packages/excalidraw/components/ContextMenu.tsx @@ -1,15 +1,20 @@ import clsx from "clsx"; -import { Popover } from "./Popover"; -import type { TranslationKeys } from "../i18n"; +import React from "react"; + +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { t } from "../i18n"; -import "./ContextMenu.scss"; -import type { ShortcutName } from "../actions/shortcuts"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; -import type { Action } from "../actions/types"; -import type { ActionManager } from "../actions/manager"; import { useExcalidrawAppState, useExcalidrawElements } from "./App"; -import React from "react"; + +import { Popover } from "./Popover"; + +import "./ContextMenu.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { ShortcutName } from "../actions/shortcuts"; +import type { Action } from "../actions/types"; + +import type { TranslationKeys } from "../i18n"; export type ContextMenuItem = typeof CONTEXT_MENU_SEPARATOR | Action; diff --git a/packages/excalidraw/components/DarkModeToggle.tsx b/packages/excalidraw/components/DarkModeToggle.tsx index 6292ba5ed..f04712944 100644 --- a/packages/excalidraw/components/DarkModeToggle.tsx +++ b/packages/excalidraw/components/DarkModeToggle.tsx @@ -1,8 +1,10 @@ +import { THEME } from "../constants"; +import { t } from "../i18n"; + +import { ToolButton } from "./ToolButton"; + import "./ToolIcon.scss"; -import { t } from "../i18n"; -import { ToolButton } from "./ToolButton"; -import { THEME } from "../constants"; import type { Theme } from "../element/types"; // We chose to use only explicit toggle and not a third option for system value, diff --git a/packages/excalidraw/components/DefaultSidebar.test.tsx b/packages/excalidraw/components/DefaultSidebar.test.tsx index ac1e2961c..f8bc0dbbb 100644 --- a/packages/excalidraw/components/DefaultSidebar.test.tsx +++ b/packages/excalidraw/components/DefaultSidebar.test.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { DEFAULT_SIDEBAR } from "../constants"; import { DefaultSidebar } from "../index"; import { @@ -6,6 +7,7 @@ import { waitFor, withExcalidrawDimensions, } from "../tests/test-utils"; + import { assertExcalidrawWithSidebar, assertSidebarDockButton, diff --git a/packages/excalidraw/components/DefaultSidebar.tsx b/packages/excalidraw/components/DefaultSidebar.tsx index 70b0c2d6c..cd9683c60 100644 --- a/packages/excalidraw/components/DefaultSidebar.tsx +++ b/packages/excalidraw/components/DefaultSidebar.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import { CANVAS_SEARCH_TAB, DEFAULT_SIDEBAR, @@ -6,17 +7,20 @@ import { } from "../constants"; import { useTunnels } from "../context/tunnels"; import { useUIAppState } from "../context/ui-appState"; -import type { MarkOptional, Merge } from "../utility-types"; import { composeEventHandlers } from "../utils"; -import { useExcalidrawSetAppState } from "./App"; -import { withInternalFallback } from "./hoc/withInternalFallback"; -import { LibraryMenu } from "./LibraryMenu"; -import type { SidebarProps, SidebarTriggerProps } from "./Sidebar/common"; -import { Sidebar } from "./Sidebar/Sidebar"; + import "../components/dropdownMenu/DropdownMenu.scss"; + +import { useExcalidrawSetAppState } from "./App"; +import { LibraryMenu } from "./LibraryMenu"; import { SearchMenu } from "./SearchMenu"; +import { Sidebar } from "./Sidebar/Sidebar"; +import { withInternalFallback } from "./hoc/withInternalFallback"; import { LibraryIcon, searchIcon } from "./icons"; +import type { MarkOptional, Merge } from "../utility-types"; +import type { SidebarProps, SidebarTriggerProps } from "./Sidebar/common"; + const DefaultSidebarTrigger = withInternalFallback( "DefaultSidebarTrigger", ( diff --git a/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx b/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx index 950599963..e225ca193 100644 --- a/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx +++ b/packages/excalidraw/components/DiagramToCodePlugin/DiagramToCodePlugin.tsx @@ -1,5 +1,7 @@ import { useLayoutEffect } from "react"; + import { useApp } from "../App"; + import type { GenerateDiagramToCode } from "../../types"; export const DiagramToCodePlugin = (props: { diff --git a/packages/excalidraw/components/Dialog.tsx b/packages/excalidraw/components/Dialog.tsx index 0a105cf8d..cf6b1254a 100644 --- a/packages/excalidraw/components/Dialog.tsx +++ b/packages/excalidraw/components/Dialog.tsx @@ -1,21 +1,24 @@ import clsx from "clsx"; import React, { useEffect, useState } from "react"; + +import { useSetAtom } from "../editor-jotai"; import { useCallbackRefState } from "../hooks/useCallbackRefState"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { queryFocusableElements } from "../utils"; + import { useExcalidrawContainer, useDevice, useExcalidrawSetAppState, } from "./App"; -import { KEYS } from "../keys"; -import "./Dialog.scss"; import { Island } from "./Island"; -import { Modal } from "./Modal"; -import { queryFocusableElements } from "../utils"; import { isLibraryMenuOpenAtom } from "./LibraryMenu"; -import { useSetAtom } from "../editor-jotai"; -import { t } from "../i18n"; +import { Modal } from "./Modal"; import { CloseIcon } from "./icons"; +import "./Dialog.scss"; + export type DialogSize = number | "small" | "regular" | "wide" | undefined; export interface DialogProps { diff --git a/packages/excalidraw/components/DialogActionButton.tsx b/packages/excalidraw/components/DialogActionButton.tsx index 0c4f9d589..1637fc31a 100644 --- a/packages/excalidraw/components/DialogActionButton.tsx +++ b/packages/excalidraw/components/DialogActionButton.tsx @@ -1,8 +1,11 @@ import clsx from "clsx"; -import type { ReactNode } from "react"; -import "./DialogActionButton.scss"; + import Spinner from "./Spinner"; +import "./DialogActionButton.scss"; + +import type { ReactNode } from "react"; + interface DialogActionButtonProps { label: string; children?: ReactNode; diff --git a/packages/excalidraw/components/ElementLinkDialog.tsx b/packages/excalidraw/components/ElementLinkDialog.tsx index 2ec3eaa0b..7cf329633 100644 --- a/packages/excalidraw/components/ElementLinkDialog.tsx +++ b/packages/excalidraw/components/ElementLinkDialog.tsx @@ -1,21 +1,24 @@ -import { TextField } from "./TextField"; -import type { AppProps, AppState, UIAppState } from "../types"; -import DialogActionButton from "./DialogActionButton"; -import { getSelectedElements } from "../scene"; +import { useCallback, useEffect, useState } from "react"; + +import { normalizeLink } from "../data/url"; import { defaultGetElementLinkFromSelection, getLinkIdAndTypeFromSelection, } from "../element/elementLink"; import { mutateElement } from "../element/mutateElement"; -import { useCallback, useEffect, useState } from "react"; import { t } from "../i18n"; -import type { ElementsMap, ExcalidrawElement } from "../element/types"; +import { KEYS } from "../keys"; +import { getSelectedElements } from "../scene"; + +import DialogActionButton from "./DialogActionButton"; +import { TextField } from "./TextField"; import { ToolButton } from "./ToolButton"; import { TrashIcon } from "./icons"; -import { KEYS } from "../keys"; import "./ElementLinkDialog.scss"; -import { normalizeLink } from "../data/url"; + +import type { ElementsMap, ExcalidrawElement } from "../element/types"; +import type { AppProps, AppState, UIAppState } from "../types"; const ElementLinkDialog = ({ sourceElementId, diff --git a/packages/excalidraw/components/ErrorDialog.tsx b/packages/excalidraw/components/ErrorDialog.tsx index 74d265f73..132b292b9 100644 --- a/packages/excalidraw/components/ErrorDialog.tsx +++ b/packages/excalidraw/components/ErrorDialog.tsx @@ -1,8 +1,9 @@ import React, { useState } from "react"; + import { t } from "../i18n"; -import { Dialog } from "./Dialog"; import { useExcalidrawContainer } from "./App"; +import { Dialog } from "./Dialog"; export const ErrorDialog = ({ children, diff --git a/packages/excalidraw/components/EyeDropper.tsx b/packages/excalidraw/components/EyeDropper.tsx index 429c68a4a..8c4a73e32 100644 --- a/packages/excalidraw/components/EyeDropper.tsx +++ b/packages/excalidraw/components/EyeDropper.tsx @@ -1,19 +1,23 @@ import { useEffect, useRef } from "react"; import { createPortal } from "react-dom"; + import { rgbToHex } from "../colors"; import { EVENT } from "../constants"; import { useUIAppState } from "../context/ui-appState"; +import { atom } from "../editor-jotai"; import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; import { useOutsideClick } from "../hooks/useOutsideClick"; +import { useStable } from "../hooks/useStable"; import { KEYS } from "../keys"; import { getSelectedElements } from "../scene"; + import { useApp, useExcalidrawContainer, useExcalidrawElements } from "./App"; -import { useStable } from "../hooks/useStable"; import "./EyeDropper.scss"; -import type { ColorPickerType } from "./ColorPicker/colorPickerUtils"; + import type { ExcalidrawElement } from "../element/types"; -import { atom } from "../editor-jotai"; + +import type { ColorPickerType } from "./ColorPicker/colorPickerUtils"; export type EyeDropperProperties = { keepOpenOnAlt: boolean; diff --git a/packages/excalidraw/components/FilledButton.tsx b/packages/excalidraw/components/FilledButton.tsx index 136090848..4e5b3e3ba 100644 --- a/packages/excalidraw/components/FilledButton.tsx +++ b/packages/excalidraw/components/FilledButton.tsx @@ -1,11 +1,13 @@ -import React, { forwardRef, useState } from "react"; import clsx from "clsx"; +import React, { forwardRef, useState } from "react"; + +import { AbortError } from "../errors"; +import { isPromiseLike } from "../utils"; + +import Spinner from "./Spinner"; +import { tablerCheckIcon } from "./icons"; import "./FilledButton.scss"; -import { AbortError } from "../errors"; -import Spinner from "./Spinner"; -import { isPromiseLike } from "../utils"; -import { tablerCheckIcon } from "./icons"; export type ButtonVariant = "filled" | "outlined" | "icon"; export type ButtonColor = diff --git a/packages/excalidraw/components/FixedSideContainer.tsx b/packages/excalidraw/components/FixedSideContainer.tsx index 76aee9989..3130d78e9 100644 --- a/packages/excalidraw/components/FixedSideContainer.tsx +++ b/packages/excalidraw/components/FixedSideContainer.tsx @@ -1,8 +1,8 @@ -import "./FixedSideContainer.scss"; - import React from "react"; import clsx from "clsx"; +import "./FixedSideContainer.scss"; + type FixedSideContainerProps = { children: React.ReactNode; side: "top" | "left" | "right"; diff --git a/packages/excalidraw/components/FollowMode/FollowMode.tsx b/packages/excalidraw/components/FollowMode/FollowMode.tsx index 89581bfa4..e862cb4ea 100644 --- a/packages/excalidraw/components/FollowMode/FollowMode.tsx +++ b/packages/excalidraw/components/FollowMode/FollowMode.tsx @@ -1,7 +1,9 @@ -import type { UserToFollow } from "../../types"; import { CloseIcon } from "../icons"; + import "./FollowMode.scss"; +import type { UserToFollow } from "../../types"; + interface FollowModeProps { width: number; height: number; diff --git a/packages/excalidraw/components/FontPicker/FontPicker.tsx b/packages/excalidraw/components/FontPicker/FontPicker.tsx index 4585c5841..4018ad243 100644 --- a/packages/excalidraw/components/FontPicker/FontPicker.tsx +++ b/packages/excalidraw/components/FontPicker/FontPicker.tsx @@ -1,21 +1,23 @@ -import React, { useCallback, useMemo } from "react"; import * as Popover from "@radix-ui/react-popover"; +import React, { useCallback, useMemo } from "react"; -import { FontPickerList } from "./FontPickerList"; -import { FontPickerTrigger } from "./FontPickerTrigger"; +import { FONT_FAMILY } from "../../constants"; +import { t } from "../../i18n"; import { ButtonIconSelect } from "../ButtonIconSelect"; +import { ButtonSeparator } from "../ButtonSeparator"; import { FontFamilyCodeIcon, FontFamilyNormalIcon, FreedrawIcon, } from "../icons"; -import { ButtonSeparator } from "../ButtonSeparator"; -import type { FontFamilyValues } from "../../element/types"; -import { FONT_FAMILY } from "../../constants"; -import { t } from "../../i18n"; + +import { FontPickerList } from "./FontPickerList"; +import { FontPickerTrigger } from "./FontPickerTrigger"; import "./FontPicker.scss"; +import type { FontFamilyValues } from "../../element/types"; + export const DEFAULT_FONTS = [ { value: FONT_FAMILY.Excalifont, diff --git a/packages/excalidraw/components/FontPicker/FontPickerList.tsx b/packages/excalidraw/components/FontPicker/FontPickerList.tsx index 3a680b8fe..d93b08695 100644 --- a/packages/excalidraw/components/FontPicker/FontPickerList.tsx +++ b/packages/excalidraw/components/FontPicker/FontPickerList.tsx @@ -1,4 +1,3 @@ -import type { JSX } from "react"; import React, { useMemo, useState, @@ -7,6 +6,11 @@ import React, { useCallback, type KeyboardEventHandler, } from "react"; + +import { type FontFamilyValues } from "../../element/types"; +import { Fonts } from "../../fonts"; +import { t } from "../../i18n"; +import { arrayToList, debounce, getFontFamilyString } from "../../utils"; import { useApp, useAppProps, useExcalidrawContainer } from "../App"; import { PropertiesPopover } from "../PropertiesPopover"; import { QuickSearch } from "../QuickSearch"; @@ -16,14 +20,13 @@ import DropdownMenuItem, { DropDownMenuItemBadgeType, DropDownMenuItemBadge, } from "../dropdownMenu/DropdownMenuItem"; -import { type FontFamilyValues } from "../../element/types"; -import { arrayToList, debounce, getFontFamilyString } from "../../utils"; -import { t } from "../../i18n"; -import { fontPickerKeyHandler } from "./keyboardNavHandlers"; -import { Fonts } from "../../fonts"; -import type { ValueOf } from "../../utility-types"; import { FontFamilyNormalIcon } from "../icons"; +import { fontPickerKeyHandler } from "./keyboardNavHandlers"; + +import type { ValueOf } from "../../utility-types"; +import type { JSX } from "react"; + export interface FontDescriptor { value: number; icon: JSX.Element; diff --git a/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx b/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx index 8652dabcd..d83dda0fd 100644 --- a/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx +++ b/packages/excalidraw/components/FontPicker/FontPickerTrigger.tsx @@ -1,11 +1,14 @@ import * as Popover from "@radix-ui/react-popover"; import { useMemo } from "react"; + +import { t } from "../../i18n"; import { ButtonIcon } from "../ButtonIcon"; import { TextIcon } from "../icons"; -import type { FontFamilyValues } from "../../element/types"; -import { t } from "../../i18n"; + import { isDefaultFont } from "./FontPicker"; +import type { FontFamilyValues } from "../../element/types"; + interface FontPickerTriggerProps { selectedFontFamily: FontFamilyValues | null; } diff --git a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts index 19c4adccc..b0ecdf371 100644 --- a/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts +++ b/packages/excalidraw/components/FontPicker/keyboardNavHandlers.ts @@ -1,7 +1,9 @@ -import type { Node } from "../../utils"; import { KEYS } from "../../keys"; + import { type FontDescriptor } from "./FontPickerList"; +import type { Node } from "../../utils"; + interface FontPickerKeyNavHandlerProps { event: React.KeyboardEvent; inputRef: React.RefObject; diff --git a/packages/excalidraw/components/HandButton.tsx b/packages/excalidraw/components/HandButton.tsx index ce63791e1..4bffb1000 100644 --- a/packages/excalidraw/components/HandButton.tsx +++ b/packages/excalidraw/components/HandButton.tsx @@ -1,9 +1,11 @@ -import "./ToolIcon.scss"; - import clsx from "clsx"; + +import { KEYS } from "../keys"; + import { ToolButton } from "./ToolButton"; import { handIcon } from "./icons"; -import { KEYS } from "../keys"; + +import "./ToolIcon.scss"; type LockIconProps = { title?: string; diff --git a/packages/excalidraw/components/HelpButton.tsx b/packages/excalidraw/components/HelpButton.tsx index ce387244c..39c867cde 100644 --- a/packages/excalidraw/components/HelpButton.tsx +++ b/packages/excalidraw/components/HelpButton.tsx @@ -1,4 +1,5 @@ import { t } from "../i18n"; + import { HelpIcon } from "./icons"; type HelpButtonProps = { diff --git a/packages/excalidraw/components/HelpDialog.tsx b/packages/excalidraw/components/HelpDialog.tsx index 926096c69..19ecaa57e 100644 --- a/packages/excalidraw/components/HelpDialog.tsx +++ b/packages/excalidraw/components/HelpDialog.tsx @@ -1,14 +1,18 @@ -import type { JSX } from "react"; import React from "react"; -import { t } from "../i18n"; -import { KEYS } from "../keys"; -import { Dialog } from "./Dialog"; -import { getShortcutKey } from "../utils"; -import "./HelpDialog.scss"; -import { ExternalLinkIcon, GithubIcon, youtubeIcon } from "./icons"; + +import { getShortcutFromShortcutName } from "../actions/shortcuts"; import { probablySupportsClipboardBlob } from "../clipboard"; import { isDarwin, isFirefox, isWindows } from "../constants"; -import { getShortcutFromShortcutName } from "../actions/shortcuts"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { getShortcutKey } from "../utils"; + +import { Dialog } from "./Dialog"; +import { ExternalLinkIcon, GithubIcon, youtubeIcon } from "./icons"; + +import "./HelpDialog.scss"; + +import type { JSX } from "react"; const Header = () => (

diff --git a/packages/excalidraw/components/HintViewer.tsx b/packages/excalidraw/components/HintViewer.tsx index f09f65852..c285e361b 100644 --- a/packages/excalidraw/components/HintViewer.tsx +++ b/packages/excalidraw/components/HintViewer.tsx @@ -1,5 +1,4 @@ -import { t } from "../i18n"; -import type { AppClassProperties, Device, UIAppState } from "../types"; +import { isEraserActive } from "../appState"; import { isFlowchartNodeElement, isImageElement, @@ -7,14 +6,18 @@ import { isTextBindableContainer, isTextElement, } from "../element/typeChecks"; -import { getShortcutKey } from "../utils"; -import { isEraserActive } from "../appState"; +import { t } from "../i18n"; + +import { getShortcutKey } from "../utils"; -import "./HintViewer.scss"; import { isNodeInFlowchart } from "../element/flowchart"; import { isGridModeEnabled } from "../snapping"; import { CANVAS_SEARCH_TAB, DEFAULT_SIDEBAR } from "../constants"; +import "./HintViewer.scss"; + +import type { AppClassProperties, Device, UIAppState } from "../types"; + interface HintViewerProps { appState: UIAppState; isMobile: boolean; diff --git a/packages/excalidraw/components/IconPicker.tsx b/packages/excalidraw/components/IconPicker.tsx index ee83f905a..b91d37c23 100644 --- a/packages/excalidraw/components/IconPicker.tsx +++ b/packages/excalidraw/components/IconPicker.tsx @@ -1,15 +1,18 @@ -import type { JSX } from "react"; -import React, { useEffect } from "react"; import * as Popover from "@radix-ui/react-popover"; -import { isArrowKey, KEYS } from "../keys"; -import { getLanguage, t } from "../i18n"; import clsx from "clsx"; -import Collapsible from "./Stats/Collapsible"; +import React, { useEffect } from "react"; + import { atom, useAtom } from "../editor-jotai"; +import { getLanguage, t } from "../i18n"; +import { isArrowKey, KEYS } from "../keys"; + +import Collapsible from "./Stats/Collapsible"; import { useDevice } from "./App"; import "./IconPicker.scss"; +import type { JSX } from "react"; + const moreOptionsAtom = atom(false); type Option = { diff --git a/packages/excalidraw/components/ImageExportDialog.tsx b/packages/excalidraw/components/ImageExportDialog.tsx index d06f4a842..0d19f5b5d 100644 --- a/packages/excalidraw/components/ImageExportDialog.tsx +++ b/packages/excalidraw/components/ImageExportDialog.tsx @@ -1,8 +1,6 @@ +import { exportToCanvas } from "@excalidraw/utils/export"; import React, { useEffect, useRef, useState } from "react"; -import type { ActionManager } from "../actions/manager"; -import type { AppClassProperties, BinaryFiles, UIAppState } from "../types"; - import { actionExportWithDarkMode, actionChangeExportBackground, @@ -17,25 +15,27 @@ import { isFirefox, EXPORT_SCALES, } from "../constants"; - +import { prepareElementsForExport } from "../data"; import { canvasToBlob } from "../data/blob"; import { nativeFileSystemSupported } from "../data/filesystem"; -import type { NonDeletedExcalidrawElement } from "../element/types"; +import { useCopyStatus } from "../hooks/useCopiedIndicator"; + import { t } from "../i18n"; import { isSomeElementSelected } from "../scene"; -import { exportToCanvas } from "@excalidraw/utils/export"; +import { cloneJSON } from "../utils"; import { copyIcon, downloadIcon, helpIcon } from "./icons"; import { Dialog } from "./Dialog"; import { RadioGroup } from "./RadioGroup"; import { Switch } from "./Switch"; import { Tooltip } from "./Tooltip"; +import { FilledButton } from "./FilledButton"; import "./ImageExportDialog.scss"; -import { FilledButton } from "./FilledButton"; -import { cloneJSON } from "../utils"; -import { prepareElementsForExport } from "../data"; -import { useCopyStatus } from "../hooks/useCopiedIndicator"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { AppClassProperties, BinaryFiles, UIAppState } from "../types"; const supportsContextFilters = "filter" in document.createElement("canvas").getContext("2d")!; diff --git a/packages/excalidraw/components/InitializeApp.tsx b/packages/excalidraw/components/InitializeApp.tsx index 41f90ceeb..efc83a55b 100644 --- a/packages/excalidraw/components/InitializeApp.tsx +++ b/packages/excalidraw/components/InitializeApp.tsx @@ -1,9 +1,11 @@ import React, { useEffect, useState } from "react"; -import { LoadingMessage } from "./LoadingMessage"; -import type { Language } from "../i18n"; import { defaultLang, languages, setLanguage } from "../i18n"; + +import { LoadingMessage } from "./LoadingMessage"; + import type { Theme } from "../element/types"; +import type { Language } from "../i18n"; interface Props { langCode: Language["code"]; diff --git a/packages/excalidraw/components/Island.tsx b/packages/excalidraw/components/Island.tsx index 7baf307a0..8219e5fc7 100644 --- a/packages/excalidraw/components/Island.tsx +++ b/packages/excalidraw/components/Island.tsx @@ -1,8 +1,8 @@ -import "./Island.scss"; - import React from "react"; import clsx from "clsx"; +import "./Island.scss"; + type IslandProps = { children: React.ReactNode; padding?: number; diff --git a/packages/excalidraw/components/JSONExportDialog.tsx b/packages/excalidraw/components/JSONExportDialog.tsx index 527ad5746..ae203d3e4 100644 --- a/packages/excalidraw/components/JSONExportDialog.tsx +++ b/packages/excalidraw/components/JSONExportDialog.tsx @@ -1,19 +1,22 @@ import React from "react"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import { t } from "../i18n"; -import type { ExportOpts, BinaryFiles, UIAppState } from "../types"; -import { Dialog } from "./Dialog"; -import { exportToFileIcon, LinkIcon } from "./icons"; -import { ToolButton } from "./ToolButton"; import { actionSaveFileToDisk } from "../actions/actionExport"; + +import { trackEvent } from "../analytics"; +import { nativeFileSystemSupported } from "../data/filesystem"; +import { t } from "../i18n"; +import { getFrame } from "../utils"; + import { Card } from "./Card"; +import { Dialog } from "./Dialog"; +import { ToolButton } from "./ToolButton"; +import { exportToFileIcon, LinkIcon } from "./icons"; import "./ExportDialog.scss"; -import { nativeFileSystemSupported } from "../data/filesystem"; -import { trackEvent } from "../analytics"; + import type { ActionManager } from "../actions/manager"; -import { getFrame } from "../utils"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { ExportOpts, BinaryFiles, UIAppState } from "../types"; export type ExportCB = ( elements: readonly NonDeletedExcalidrawElement[], diff --git a/packages/excalidraw/components/LaserPointerButton.tsx b/packages/excalidraw/components/LaserPointerButton.tsx index 35470f6e7..237d0831c 100644 --- a/packages/excalidraw/components/LaserPointerButton.tsx +++ b/packages/excalidraw/components/LaserPointerButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { laserPointerToolIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type LaserPointerIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/LayerUI.tsx b/packages/excalidraw/components/LayerUI.tsx index 11914d09a..83ac7ae9c 100644 --- a/packages/excalidraw/components/LayerUI.tsx +++ b/packages/excalidraw/components/LayerUI.tsx @@ -1,12 +1,58 @@ import clsx from "clsx"; import React from "react"; -import type { ActionManager } from "../actions/manager"; + +import { mutateElement } from "../element/mutateElement"; +import { ShapeCache } from "../scene/ShapeCache"; +import Scene from "../scene/Scene"; +import { actionToggleStats } from "../actions"; +import { trackEvent } from "../analytics"; +import { isHandToolActive } from "../appState"; import { CLASSES, DEFAULT_SIDEBAR, TOOL_TYPE } from "../constants"; +import { TunnelsContext, useInitializeTunnels } from "../context/tunnels"; +import { UIAppStateContext } from "../context/ui-appState"; +import { useAtom, useAtomValue } from "../editor-jotai"; import { showSelectedShapeActions } from "../element"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import type { Language } from "../i18n"; import { t } from "../i18n"; import { calculateScrollCenter } from "../scene"; +import { capitalizeString, isShallowEqual } from "../utils"; + +import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; +import { LoadingMessage } from "./LoadingMessage"; +import { LockButton } from "./LockButton"; +import { MobileMenu } from "./MobileMenu"; +import { PasteChartDialog } from "./PasteChartDialog"; +import { Section } from "./Section"; +import Stack from "./Stack"; +import { UserList } from "./UserList"; +import { PenModeButton } from "./PenModeButton"; +import Footer from "./footer/Footer"; +import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; +import MainMenu from "./main-menu/MainMenu"; +import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; +import { useDevice } from "./App"; +import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm"; +import { LibraryIcon } from "./icons"; +import { DefaultSidebar } from "./DefaultSidebar"; +import { TTDDialog } from "./TTDDialog/TTDDialog"; +import { Stats } from "./Stats"; +import ElementLinkDialog from "./ElementLinkDialog"; +import { ErrorDialog } from "./ErrorDialog"; +import { EyeDropper, activeEyeDropperAtom } from "./EyeDropper"; +import { FixedSideContainer } from "./FixedSideContainer"; +import { HandButton } from "./HandButton"; +import { HelpDialog } from "./HelpDialog"; +import { HintViewer } from "./HintViewer"; +import { ImageExportDialog } from "./ImageExportDialog"; +import { Island } from "./Island"; +import { JSONExportDialog } from "./JSONExportDialog"; +import { LaserPointerButton } from "./LaserPointerButton"; + +import "./LayerUI.scss"; +import "./Toolbar.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; +import type { Language } from "../i18n"; import type { AppProps, AppState, @@ -15,49 +61,6 @@ import type { UIAppState, AppClassProperties, } from "../types"; -import { capitalizeString, isShallowEqual } from "../utils"; -import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import { ErrorDialog } from "./ErrorDialog"; -import { ImageExportDialog } from "./ImageExportDialog"; -import { FixedSideContainer } from "./FixedSideContainer"; -import { HintViewer } from "./HintViewer"; -import { Island } from "./Island"; -import { LoadingMessage } from "./LoadingMessage"; -import { LockButton } from "./LockButton"; -import { MobileMenu } from "./MobileMenu"; -import { PasteChartDialog } from "./PasteChartDialog"; -import { Section } from "./Section"; -import { HelpDialog } from "./HelpDialog"; -import Stack from "./Stack"; -import { UserList } from "./UserList"; -import { JSONExportDialog } from "./JSONExportDialog"; -import { PenModeButton } from "./PenModeButton"; -import { trackEvent } from "../analytics"; -import { useDevice } from "./App"; -import Footer from "./footer/Footer"; -import { isSidebarDockedAtom } from "./Sidebar/Sidebar"; -import { useAtom, useAtomValue } from "../editor-jotai"; -import MainMenu from "./main-menu/MainMenu"; -import { ActiveConfirmDialog } from "./ActiveConfirmDialog"; -import { OverwriteConfirmDialog } from "./OverwriteConfirm/OverwriteConfirm"; -import { HandButton } from "./HandButton"; -import { isHandToolActive } from "../appState"; -import { TunnelsContext, useInitializeTunnels } from "../context/tunnels"; -import { LibraryIcon } from "./icons"; -import { UIAppStateContext } from "../context/ui-appState"; -import { DefaultSidebar } from "./DefaultSidebar"; -import { EyeDropper, activeEyeDropperAtom } from "./EyeDropper"; -import { mutateElement } from "../element/mutateElement"; -import { ShapeCache } from "../scene/ShapeCache"; -import Scene from "../scene/Scene"; -import { LaserPointerButton } from "./LaserPointerButton"; -import { TTDDialog } from "./TTDDialog/TTDDialog"; -import { Stats } from "./Stats"; -import { actionToggleStats } from "../actions"; -import ElementLinkDialog from "./ElementLinkDialog"; - -import "./LayerUI.scss"; -import "./Toolbar.scss"; interface LayerUIProps { actionManager: ActionManager; diff --git a/packages/excalidraw/components/LibraryMenu.tsx b/packages/excalidraw/components/LibraryMenu.tsx index 0162d93a0..03c476e47 100644 --- a/packages/excalidraw/components/LibraryMenu.tsx +++ b/packages/excalidraw/components/LibraryMenu.tsx @@ -6,13 +6,36 @@ import React, { memo, useRef, } from "react"; -import type Library from "../data/library"; + +import { trackEvent } from "../analytics"; +import { LIBRARY_DISABLED_TYPES } from "../constants"; +import { useUIAppState } from "../context/ui-appState"; import { distributeLibraryItemsOnSquareGrid, libraryItemsAtom, } from "../data/library"; +import { atom, useAtom } from "../editor-jotai"; import { t } from "../i18n"; import { randomId } from "../random"; +import { getSelectedElements } from "../scene"; +import { isShallowEqual } from "../utils"; + +import { + useApp, + useAppProps, + useExcalidrawElements, + useExcalidrawSetAppState, +} from "./App"; +import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; +import LibraryMenuItems from "./LibraryMenuItems"; +import Spinner from "./Spinner"; + +import "./LibraryMenu.scss"; + +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "../element/types"; import type { LibraryItems, LibraryItem, @@ -20,27 +43,7 @@ import type { UIAppState, AppClassProperties, } from "../types"; -import LibraryMenuItems from "./LibraryMenuItems"; -import { trackEvent } from "../analytics"; -import { atom, useAtom } from "../editor-jotai"; -import Spinner from "./Spinner"; -import { - useApp, - useAppProps, - useExcalidrawElements, - useExcalidrawSetAppState, -} from "./App"; -import { getSelectedElements } from "../scene"; -import { useUIAppState } from "../context/ui-appState"; - -import "./LibraryMenu.scss"; -import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "../element/types"; -import { LIBRARY_DISABLED_TYPES } from "../constants"; -import { isShallowEqual } from "../utils"; +import type Library from "../data/library"; export const isLibraryMenuOpenAtom = atom(false); diff --git a/packages/excalidraw/components/LibraryMenuBrowseButton.tsx b/packages/excalidraw/components/LibraryMenuBrowseButton.tsx index 43fbedd77..2b2623ed1 100644 --- a/packages/excalidraw/components/LibraryMenuBrowseButton.tsx +++ b/packages/excalidraw/components/LibraryMenuBrowseButton.tsx @@ -1,5 +1,6 @@ import { VERSIONS } from "../constants"; import { t } from "../i18n"; + import type { ExcalidrawProps, UIAppState } from "../types"; const LibraryMenuBrowseButton = ({ diff --git a/packages/excalidraw/components/LibraryMenuControlButtons.tsx b/packages/excalidraw/components/LibraryMenuControlButtons.tsx index b467ca39c..1ea722168 100644 --- a/packages/excalidraw/components/LibraryMenuControlButtons.tsx +++ b/packages/excalidraw/components/LibraryMenuControlButtons.tsx @@ -1,7 +1,9 @@ -import type { ExcalidrawProps, UIAppState } from "../types"; -import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton"; import clsx from "clsx"; +import LibraryMenuBrowseButton from "./LibraryMenuBrowseButton"; + +import type { ExcalidrawProps, UIAppState } from "../types"; + export const LibraryMenuControlButtons = ({ libraryReturnUrl, theme, diff --git a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx index bec31aa36..cc6c942ae 100644 --- a/packages/excalidraw/components/LibraryMenuHeaderContent.tsx +++ b/packages/excalidraw/components/LibraryMenuHeaderContent.tsx @@ -1,12 +1,23 @@ +import clsx from "clsx"; import { useCallback, useState } from "react"; -import { t } from "../i18n"; -import Trans from "./Trans"; -import { useAtom } from "../editor-jotai"; -import type { LibraryItem, LibraryItems, UIAppState } from "../types"; -import { useApp, useExcalidrawSetAppState } from "./App"; + +import { useUIAppState } from "../context/ui-appState"; +import { fileOpen } from "../data/filesystem"; import { saveLibraryAsJSON } from "../data/json"; -import type Library from "../data/library"; import { libraryItemsAtom } from "../data/library"; +import { useAtom } from "../editor-jotai"; +import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import { t } from "../i18n"; +import { muteFSAbortError } from "../utils"; + +import { useApp, useExcalidrawSetAppState } from "./App"; +import ConfirmDialog from "./ConfirmDialog"; +import { Dialog } from "./Dialog"; +import { isLibraryMenuOpenAtom } from "./LibraryMenu"; +import PublishLibrary from "./PublishLibrary"; +import { ToolButton } from "./ToolButton"; +import Trans from "./Trans"; +import DropdownMenu from "./dropdownMenu/DropdownMenu"; import { DotsIcon, ExportIcon, @@ -14,17 +25,9 @@ import { publishIcon, TrashIcon, } from "./icons"; -import { ToolButton } from "./ToolButton"; -import { fileOpen } from "../data/filesystem"; -import { muteFSAbortError } from "../utils"; -import ConfirmDialog from "./ConfirmDialog"; -import PublishLibrary from "./PublishLibrary"; -import { Dialog } from "./Dialog"; -import DropdownMenu from "./dropdownMenu/DropdownMenu"; -import { isLibraryMenuOpenAtom } from "./LibraryMenu"; -import { useUIAppState } from "../context/ui-appState"; -import clsx from "clsx"; -import { useLibraryCache } from "../hooks/useLibraryItemSvg"; + +import type Library from "../data/library"; +import type { LibraryItem, LibraryItems, UIAppState } from "../types"; const getSelectedItems = ( libraryItems: LibraryItems, diff --git a/packages/excalidraw/components/LibraryMenuItems.tsx b/packages/excalidraw/components/LibraryMenuItems.tsx index aa2c3e68e..af5b9d3e6 100644 --- a/packages/excalidraw/components/LibraryMenuItems.tsx +++ b/packages/excalidraw/components/LibraryMenuItems.tsx @@ -5,30 +5,33 @@ import React, { useRef, useState, } from "react"; -import { serializeLibraryAsJSON } from "../data/json"; -import { t } from "../i18n"; -import type { - ExcalidrawProps, - LibraryItem, - LibraryItems, - UIAppState, -} from "../types"; -import { arrayToMap } from "../utils"; -import Stack from "./Stack"; + import { MIME_TYPES } from "../constants"; -import Spinner from "./Spinner"; +import { serializeLibraryAsJSON } from "../data/json"; import { duplicateElements } from "../element/newElement"; +import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import { useScrollPosition } from "../hooks/useScrollPosition"; +import { t } from "../i18n"; +import { arrayToMap } from "../utils"; + import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent"; import { LibraryMenuSection, LibraryMenuSectionGrid, } from "./LibraryMenuSection"; -import { useScrollPosition } from "../hooks/useScrollPosition"; -import { useLibraryCache } from "../hooks/useLibraryItemSvg"; +import Spinner from "./Spinner"; +import Stack from "./Stack"; import "./LibraryMenuItems.scss"; +import type { + ExcalidrawProps, + LibraryItem, + LibraryItems, + UIAppState, +} from "../types"; + // using an odd number of items per batch so the rendering creates an irregular // pattern which looks more organic const ITEMS_RENDERED_PER_BATCH = 17; diff --git a/packages/excalidraw/components/LibraryMenuSection.tsx b/packages/excalidraw/components/LibraryMenuSection.tsx index b07d6b1cc..5f7de2b09 100644 --- a/packages/excalidraw/components/LibraryMenuSection.tsx +++ b/packages/excalidraw/components/LibraryMenuSection.tsx @@ -1,10 +1,13 @@ -import type { ReactNode } from "react"; import React, { memo, useEffect, useState } from "react"; + +import { useTransition } from "../hooks/useTransition"; + import { EmptyLibraryUnit, LibraryUnit } from "./LibraryUnit"; -import type { LibraryItem } from "../types"; + import type { ExcalidrawElement, NonDeleted } from "../element/types"; import type { SvgCache } from "../hooks/useLibraryItemSvg"; -import { useTransition } from "../hooks/useTransition"; +import type { LibraryItem } from "../types"; +import type { ReactNode } from "react"; type LibraryOrPendingItem = ( | LibraryItem diff --git a/packages/excalidraw/components/LibraryUnit.tsx b/packages/excalidraw/components/LibraryUnit.tsx index 71e1a00f5..9cd891715 100644 --- a/packages/excalidraw/components/LibraryUnit.tsx +++ b/packages/excalidraw/components/LibraryUnit.tsx @@ -1,12 +1,16 @@ import clsx from "clsx"; import { memo, useEffect, useRef, useState } from "react"; + +import { useLibraryItemSvg } from "../hooks/useLibraryItemSvg"; + import { useDevice } from "./App"; -import type { LibraryItem } from "../types"; -import "./LibraryUnit.scss"; import { CheckboxItem } from "./CheckboxItem"; import { PlusIcon } from "./icons"; + +import "./LibraryUnit.scss"; + +import type { LibraryItem } from "../types"; import type { SvgCache } from "../hooks/useLibraryItemSvg"; -import { useLibraryItemSvg } from "../hooks/useLibraryItemSvg"; export const LibraryUnit = memo( ({ diff --git a/packages/excalidraw/components/LoadingMessage.tsx b/packages/excalidraw/components/LoadingMessage.tsx index b00725257..bdcc5a341 100644 --- a/packages/excalidraw/components/LoadingMessage.tsx +++ b/packages/excalidraw/components/LoadingMessage.tsx @@ -1,8 +1,11 @@ -import { t } from "../i18n"; -import { useState, useEffect } from "react"; -import Spinner from "./Spinner"; import clsx from "clsx"; +import { useState, useEffect } from "react"; + import { THEME } from "../constants"; +import { t } from "../i18n"; + +import Spinner from "./Spinner"; + import type { Theme } from "../element/types"; export const LoadingMessage: React.FC<{ delay?: number; theme?: Theme }> = ({ diff --git a/packages/excalidraw/components/LockButton.tsx b/packages/excalidraw/components/LockButton.tsx index f7913d12d..8363ffa0c 100644 --- a/packages/excalidraw/components/LockButton.tsx +++ b/packages/excalidraw/components/LockButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { LockedIcon, UnlockedIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type LockIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/MagicButton.tsx b/packages/excalidraw/components/MagicButton.tsx index eedc63b3d..b2bbd03e2 100644 --- a/packages/excalidraw/components/MagicButton.tsx +++ b/packages/excalidraw/components/MagicButton.tsx @@ -1,9 +1,10 @@ -import type { JSX } from "react"; import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import "./ToolIcon.scss"; +import type { ToolButtonSize } from "./ToolButton"; +import type { JSX } from "react"; + const DEFAULT_SIZE: ToolButtonSize = "small"; export const ElementCanvasButton = (props: { diff --git a/packages/excalidraw/components/MobileMenu.tsx b/packages/excalidraw/components/MobileMenu.tsx index bef99a91a..08a20174c 100644 --- a/packages/excalidraw/components/MobileMenu.tsx +++ b/packages/excalidraw/components/MobileMenu.tsx @@ -1,5 +1,24 @@ -import type { JSX } from "react"; import React from "react"; + +import { isHandToolActive } from "../appState"; +import { useTunnels } from "../context/tunnels"; +import { showSelectedShapeActions } from "../element"; +import { t } from "../i18n"; +import { calculateScrollCenter } from "../scene"; +import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars"; + +import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; +import { FixedSideContainer } from "./FixedSideContainer"; +import { HandButton } from "./HandButton"; +import { HintViewer } from "./HintViewer"; +import { Island } from "./Island"; +import { LockButton } from "./LockButton"; +import { PenModeButton } from "./PenModeButton"; +import { Section } from "./Section"; +import Stack from "./Stack"; + +import type { ActionManager } from "../actions/manager"; +import type { NonDeletedExcalidrawElement } from "../element/types"; import type { AppClassProperties, AppProps, @@ -8,23 +27,7 @@ import type { ExcalidrawProps, UIAppState, } from "../types"; -import type { ActionManager } from "../actions/manager"; -import { t } from "../i18n"; -import Stack from "./Stack"; -import { showSelectedShapeActions } from "../element"; -import type { NonDeletedExcalidrawElement } from "../element/types"; -import { FixedSideContainer } from "./FixedSideContainer"; -import { Island } from "./Island"; -import { HintViewer } from "./HintViewer"; -import { calculateScrollCenter } from "../scene"; -import { SelectedShapeActions, ShapesSwitcher } from "./Actions"; -import { Section } from "./Section"; -import { SCROLLBAR_WIDTH, SCROLLBAR_MARGIN } from "../scene/scrollbars"; -import { LockButton } from "./LockButton"; -import { PenModeButton } from "./PenModeButton"; -import { HandButton } from "./HandButton"; -import { isHandToolActive } from "../appState"; -import { useTunnels } from "../context/tunnels"; +import type { JSX } from "react"; type MobileMenuProps = { appState: UIAppState; diff --git a/packages/excalidraw/components/Modal.tsx b/packages/excalidraw/components/Modal.tsx index e8fff195b..a5ade9efa 100644 --- a/packages/excalidraw/components/Modal.tsx +++ b/packages/excalidraw/components/Modal.tsx @@ -1,11 +1,13 @@ +import clsx from "clsx"; +import { useRef } from "react"; +import { createPortal } from "react-dom"; + +import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; +import { KEYS } from "../keys"; + import "./Modal.scss"; -import { createPortal } from "react-dom"; -import clsx from "clsx"; -import { KEYS } from "../keys"; import type { AppState } from "../types"; -import { useCreatePortalContainer } from "../hooks/useCreatePortalContainer"; -import { useRef } from "react"; export const Modal: React.FC<{ className?: string; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx index 4bf8d6717..f2de877e0 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirm.tsx @@ -3,12 +3,13 @@ import React from "react"; import { useTunnels } from "../../context/tunnels"; import { useAtom } from "../../editor-jotai"; import { Dialog } from "../Dialog"; +import { FilledButton } from "../FilledButton"; import { withInternalFallback } from "../hoc/withInternalFallback"; +import { alertTriangleIcon } from "../icons"; + +import { Actions, Action } from "./OverwriteConfirmActions"; import { overwriteConfirmStateAtom } from "./OverwriteConfirmState"; -import { FilledButton } from "../FilledButton"; -import { alertTriangleIcon } from "../icons"; -import { Actions, Action } from "./OverwriteConfirmActions"; import "./OverwriteConfirm.scss"; export type OverwriteConfirmDialogProps = { diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx index 5da0a08ef..e5fb56d85 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmActions.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { FilledButton } from "../FilledButton"; -import { useExcalidrawActionManager, useExcalidrawSetAppState } from "../App"; + import { actionSaveFileToDisk } from "../../actions"; -import { useI18n } from "../../i18n"; import { actionChangeExportEmbedScene } from "../../actions/actionExport"; +import { useI18n } from "../../i18n"; +import { useExcalidrawActionManager, useExcalidrawSetAppState } from "../App"; +import { FilledButton } from "../FilledButton"; export type ActionProps = { title: string; diff --git a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts index 04616aa8d..cefb2153a 100644 --- a/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts +++ b/packages/excalidraw/components/OverwriteConfirm/OverwriteConfirmState.ts @@ -1,4 +1,5 @@ import { atom, editorJotaiStore } from "../../editor-jotai"; + import type React from "react"; export type OverwriteConfirmState = diff --git a/packages/excalidraw/components/PasteChartDialog.tsx b/packages/excalidraw/components/PasteChartDialog.tsx index 08a5634a9..58bd5a385 100644 --- a/packages/excalidraw/components/PasteChartDialog.tsx +++ b/packages/excalidraw/components/PasteChartDialog.tsx @@ -1,17 +1,20 @@ import oc from "open-color"; import React, { useLayoutEffect, useRef, useState } from "react"; + import { trackEvent } from "../analytics"; -import type { ChartElements, Spreadsheet } from "../charts"; import { renderSpreadsheet } from "../charts"; -import type { ChartType } from "../element/types"; import { t } from "../i18n"; import { exportToSvg } from "../scene/export"; -import type { UIAppState } from "../types"; + import { useApp } from "./App"; import { Dialog } from "./Dialog"; import "./PasteChartDialog.scss"; +import type { ChartElements, Spreadsheet } from "../charts"; +import type { ChartType } from "../element/types"; +import type { UIAppState } from "../types"; + type OnInsertChart = (chartType: ChartType, elements: ChartElements) => void; const ChartPreviewBtn = (props: { diff --git a/packages/excalidraw/components/PenModeButton.tsx b/packages/excalidraw/components/PenModeButton.tsx index ca5ceb2b6..e5df8ac9b 100644 --- a/packages/excalidraw/components/PenModeButton.tsx +++ b/packages/excalidraw/components/PenModeButton.tsx @@ -1,9 +1,11 @@ +import clsx from "clsx"; + import "./ToolIcon.scss"; -import clsx from "clsx"; -import type { ToolButtonSize } from "./ToolButton"; import { PenModeIcon } from "./icons"; +import type { ToolButtonSize } from "./ToolButton"; + type PenModeIconProps = { title?: string; name?: string; diff --git a/packages/excalidraw/components/Popover.tsx b/packages/excalidraw/components/Popover.tsx index 987e9fb91..2bd72b20b 100644 --- a/packages/excalidraw/components/Popover.tsx +++ b/packages/excalidraw/components/Popover.tsx @@ -1,8 +1,10 @@ import React, { useLayoutEffect, useRef, useEffect } from "react"; -import "./Popover.scss"; import { unstable_batchedUpdates } from "react-dom"; -import { queryFocusableElements } from "../utils"; + import { KEYS } from "../keys"; +import { queryFocusableElements } from "../utils"; + +import "./Popover.scss"; type Props = { top?: number; diff --git a/packages/excalidraw/components/ProjectName.tsx b/packages/excalidraw/components/ProjectName.tsx index 592961793..0d60ddd66 100644 --- a/packages/excalidraw/components/ProjectName.tsx +++ b/packages/excalidraw/components/ProjectName.tsx @@ -1,12 +1,13 @@ -import "./TextInput.scss"; - import React, { useState } from "react"; -import { focusNearestParent } from "../utils"; -import "./ProjectName.scss"; -import { useExcalidrawContainer } from "./App"; +import { focusNearestParent } from "../utils"; import { KEYS } from "../keys"; +import { useExcalidrawContainer } from "./App"; + +import "./TextInput.scss"; +import "./ProjectName.scss"; + type Props = { value: string; onChange: (value: string) => void; diff --git a/packages/excalidraw/components/PropertiesPopover.tsx b/packages/excalidraw/components/PropertiesPopover.tsx index 455af1184..a30f1374d 100644 --- a/packages/excalidraw/components/PropertiesPopover.tsx +++ b/packages/excalidraw/components/PropertiesPopover.tsx @@ -1,10 +1,11 @@ -import React, { type ReactNode } from "react"; -import clsx from "clsx"; import * as Popover from "@radix-ui/react-popover"; +import clsx from "clsx"; +import React, { type ReactNode } from "react"; + +import { isInteractive } from "../utils"; import { useDevice } from "./App"; import { Island } from "./Island"; -import { isInteractive } from "../utils"; interface PropertiesPopoverProps { className?: string; diff --git a/packages/excalidraw/components/PublishLibrary.tsx b/packages/excalidraw/components/PublishLibrary.tsx index fe68f880d..8a7188b63 100644 --- a/packages/excalidraw/components/PublishLibrary.tsx +++ b/packages/excalidraw/components/PublishLibrary.tsx @@ -1,13 +1,7 @@ -import type { ReactNode } from "react"; -import { useCallback, useEffect, useRef, useState } from "react"; -import OpenColor from "open-color"; - -import { Dialog } from "./Dialog"; -import { t } from "../i18n"; -import Trans from "./Trans"; - -import type { LibraryItems, LibraryItem, UIAppState } from "../types"; import { exportToCanvas, exportToSvg } from "@excalidraw/utils/export"; +import OpenColor from "open-color"; +import { useCallback, useEffect, useRef, useState } from "react"; + import { EDITOR_LS_KEYS, EXPORT_DATA_TYPES, @@ -15,16 +9,23 @@ import { MIME_TYPES, VERSIONS, } from "../constants"; -import type { ExportedLibraryData } from "../data/types"; -import { canvasToBlob, resizeImageFile } from "../data/blob"; -import { chunk } from "../utils"; -import DialogActionButton from "./DialogActionButton"; -import { CloseIcon } from "./icons"; -import { ToolButton } from "./ToolButton"; import { EditorLocalStorage } from "../data/EditorLocalStorage"; +import { canvasToBlob, resizeImageFile } from "../data/blob"; +import { t } from "../i18n"; +import { chunk } from "../utils"; + +import { Dialog } from "./Dialog"; +import DialogActionButton from "./DialogActionButton"; +import { ToolButton } from "./ToolButton"; +import Trans from "./Trans"; +import { CloseIcon } from "./icons"; import "./PublishLibrary.scss"; +import type { ReactNode } from "react"; +import type { ExportedLibraryData } from "../data/types"; +import type { LibraryItems, LibraryItem, UIAppState } from "../types"; + interface PublishLibraryDataParams { authorName: string; githubHandle: string; diff --git a/packages/excalidraw/components/QuickSearch.tsx b/packages/excalidraw/components/QuickSearch.tsx index c7ec78b50..83b65183f 100644 --- a/packages/excalidraw/components/QuickSearch.tsx +++ b/packages/excalidraw/components/QuickSearch.tsx @@ -1,5 +1,6 @@ import clsx from "clsx"; import React from "react"; + import { searchIcon } from "./icons"; import "./QuickSearch.scss"; diff --git a/packages/excalidraw/components/RadioGroup.tsx b/packages/excalidraw/components/RadioGroup.tsx index 64d4d587d..c08355aa2 100644 --- a/packages/excalidraw/components/RadioGroup.tsx +++ b/packages/excalidraw/components/RadioGroup.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import "./RadioGroup.scss"; export type RadioGroupChoice = { diff --git a/packages/excalidraw/components/Range.tsx b/packages/excalidraw/components/Range.tsx index cd1869cc0..3ab9ede15 100644 --- a/packages/excalidraw/components/Range.tsx +++ b/packages/excalidraw/components/Range.tsx @@ -1,6 +1,8 @@ import React, { useEffect } from "react"; + import { getFormValue } from "../actions/actionProperties"; import { t } from "../i18n"; + import "./Range.scss"; export type RangeProps = { diff --git a/packages/excalidraw/components/SVGLayer.tsx b/packages/excalidraw/components/SVGLayer.tsx index 667b89ab7..815d463a3 100644 --- a/packages/excalidraw/components/SVGLayer.tsx +++ b/packages/excalidraw/components/SVGLayer.tsx @@ -1,8 +1,9 @@ import { useEffect, useRef } from "react"; -import type { Trail } from "../animated-trail"; import "./SVGLayer.scss"; +import type { Trail } from "../animated-trail"; + type SVGLayerProps = { trails: Trail[]; }; diff --git a/packages/excalidraw/components/SearchMenu.tsx b/packages/excalidraw/components/SearchMenu.tsx index 873de5adb..70d3f4f27 100644 --- a/packages/excalidraw/components/SearchMenu.tsx +++ b/packages/excalidraw/components/SearchMenu.tsx @@ -1,25 +1,29 @@ -import { Fragment, memo, useEffect, useRef, useState } from "react"; -import { collapseDownIcon, upIcon, searchIcon } from "./icons"; -import { TextField } from "./TextField"; -import { Button } from "./Button"; -import { useApp, useExcalidrawSetAppState } from "./App"; -import debounce from "lodash.debounce"; -import type { AppClassProperties } from "../types"; -import { isTextElement, newTextElement } from "../element"; -import type { ExcalidrawTextElement } from "../element/types"; -import { addEventListener, getFontString } from "../utils"; -import { KEYS } from "../keys"; +import { round } from "@excalidraw/math"; import clsx from "clsx"; -import { atom, useAtom } from "../editor-jotai"; -import { t } from "../i18n"; -import { isElementCompletelyInViewport } from "../element/sizeHelpers"; -import { randomInteger } from "../random"; +import debounce from "lodash.debounce"; +import { Fragment, memo, useEffect, useRef, useState } from "react"; + import { CLASSES, EVENT } from "../constants"; +import { atom, useAtom } from "../editor-jotai"; +import { isTextElement, newTextElement } from "../element"; +import { isElementCompletelyInViewport } from "../element/sizeHelpers"; + +import { measureText } from "../element/textMeasurements"; import { useStable } from "../hooks/useStable"; +import { t } from "../i18n"; +import { KEYS } from "../keys"; +import { randomInteger } from "../random"; +import { addEventListener, getFontString } from "../utils"; + +import { useApp, useExcalidrawSetAppState } from "./App"; +import { Button } from "./Button"; +import { TextField } from "./TextField"; +import { collapseDownIcon, upIcon, searchIcon } from "./icons"; import "./SearchMenu.scss"; -import { round } from "@excalidraw/math"; -import { measureText } from "../element/textMeasurements"; + +import type { ExcalidrawTextElement } from "../element/types"; +import type { AppClassProperties } from "../types"; const searchQueryAtom = atom(""); export const searchItemInFocusAtom = atom(null); diff --git a/packages/excalidraw/components/Section.tsx b/packages/excalidraw/components/Section.tsx index 8cd0aaab5..e7e357bb5 100644 --- a/packages/excalidraw/components/Section.tsx +++ b/packages/excalidraw/components/Section.tsx @@ -1,5 +1,7 @@ import React from "react"; + import { t } from "../i18n"; + import { useExcalidrawContainer } from "./App"; export const Section: React.FC<{ diff --git a/packages/excalidraw/components/ShareableLinkDialog.tsx b/packages/excalidraw/components/ShareableLinkDialog.tsx index 987c7bf61..514a77632 100644 --- a/packages/excalidraw/components/ShareableLinkDialog.tsx +++ b/packages/excalidraw/components/ShareableLinkDialog.tsx @@ -1,12 +1,12 @@ import { useRef, useState } from "react"; import { copyTextToSystemClipboard } from "../clipboard"; +import { useCopyStatus } from "../hooks/useCopiedIndicator"; import { useI18n } from "../i18n"; import { Dialog } from "./Dialog"; -import { TextField } from "./TextField"; import { FilledButton } from "./FilledButton"; -import { useCopyStatus } from "../hooks/useCopiedIndicator"; +import { TextField } from "./TextField"; import { copyIcon } from "./icons"; import "./ShareableLinkDialog.scss"; diff --git a/packages/excalidraw/components/Sidebar/Sidebar.test.tsx b/packages/excalidraw/components/Sidebar/Sidebar.test.tsx index b61529d9e..39a1cbc63 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.test.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.test.tsx @@ -1,4 +1,6 @@ import React from "react"; +import { vi } from "vitest"; + import { DEFAULT_SIDEBAR } from "../../constants"; import { Excalidraw, Sidebar } from "../../index"; import { @@ -10,7 +12,7 @@ import { waitFor, withExcalidrawDimensions, } from "../../tests/test-utils"; -import { vi } from "vitest"; + import { assertExcalidrawWithSidebar, assertSidebarDockButton, diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index 7c747d2f4..8a008fd9f 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -1,3 +1,4 @@ +import clsx from "clsx"; import React, { useEffect, useLayoutEffect, @@ -7,26 +8,28 @@ import React, { useImperativeHandle, useCallback, } from "react"; -import { Island } from "../Island"; -import { atom, useSetAtom } from "../../editor-jotai"; -import type { SidebarProps, SidebarPropsContextValue } from "./common"; -import { SidebarPropsContext } from "./common"; -import { SidebarHeader } from "./SidebarHeader"; -import clsx from "clsx"; -import { useDevice, useExcalidrawSetAppState } from "../App"; -import { updateObject } from "../../utils"; -import { KEYS } from "../../keys"; + import { EVENT } from "../../constants"; -import { SidebarTrigger } from "./SidebarTrigger"; -import { SidebarTabTriggers } from "./SidebarTabTriggers"; +import { useUIAppState } from "../../context/ui-appState"; +import { atom, useSetAtom } from "../../editor-jotai"; +import { useOutsideClick } from "../../hooks/useOutsideClick"; +import { KEYS } from "../../keys"; +import { updateObject } from "../../utils"; +import { useDevice, useExcalidrawSetAppState } from "../App"; +import { Island } from "../Island"; + +import { SidebarHeader } from "./SidebarHeader"; import { SidebarTabTrigger } from "./SidebarTabTrigger"; +import { SidebarTabTriggers } from "./SidebarTabTriggers"; +import { SidebarTrigger } from "./SidebarTrigger"; +import { SidebarPropsContext } from "./common"; import { SidebarTabs } from "./SidebarTabs"; import { SidebarTab } from "./SidebarTab"; -import { useUIAppState } from "../../context/ui-appState"; -import { useOutsideClick } from "../../hooks/useOutsideClick"; import "./Sidebar.scss"; +import type { SidebarProps, SidebarPropsContextValue } from "./common"; + /** * Flags whether the currently rendered Sidebar is docked or not, for use * in upstream components that need to act on this (e.g. LayerUI to shift the diff --git a/packages/excalidraw/components/Sidebar/SidebarHeader.tsx b/packages/excalidraw/components/Sidebar/SidebarHeader.tsx index 6d046aba3..9c9e51cf5 100644 --- a/packages/excalidraw/components/Sidebar/SidebarHeader.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarHeader.tsx @@ -1,11 +1,13 @@ import clsx from "clsx"; import { useContext } from "react"; + import { t } from "../../i18n"; import { useDevice } from "../App"; -import { SidebarPropsContext } from "./common"; -import { CloseIcon, PinIcon } from "../icons"; -import { Tooltip } from "../Tooltip"; import { Button } from "../Button"; +import { Tooltip } from "../Tooltip"; +import { CloseIcon, PinIcon } from "../icons"; + +import { SidebarPropsContext } from "./common"; export const SidebarHeader = ({ children, diff --git a/packages/excalidraw/components/Sidebar/SidebarTab.tsx b/packages/excalidraw/components/Sidebar/SidebarTab.tsx index 6fddab0d6..0525662f7 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTab.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTab.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import type { SidebarTabName } from "../../types"; export const SidebarTab = ({ diff --git a/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx b/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx index 8509ef23d..9f2c09bcc 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTabTrigger.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import type { SidebarTabName } from "../../types"; export const SidebarTabTrigger = ({ diff --git a/packages/excalidraw/components/Sidebar/SidebarTabs.tsx b/packages/excalidraw/components/Sidebar/SidebarTabs.tsx index a681b5ee5..448840c4a 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTabs.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTabs.tsx @@ -1,4 +1,5 @@ import * as RadixTabs from "@radix-ui/react-tabs"; + import { useUIAppState } from "../../context/ui-appState"; import { useExcalidrawSetAppState } from "../App"; diff --git a/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx b/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx index a26e52d23..6e8bf374c 100644 --- a/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx +++ b/packages/excalidraw/components/Sidebar/SidebarTrigger.tsx @@ -1,10 +1,12 @@ -import { useExcalidrawSetAppState } from "../App"; -import type { SidebarTriggerProps } from "./common"; -import { useUIAppState } from "../../context/ui-appState"; import clsx from "clsx"; +import { useUIAppState } from "../../context/ui-appState"; +import { useExcalidrawSetAppState } from "../App"; + import "./SidebarTrigger.scss"; +import type { SidebarTriggerProps } from "./common"; + export const SidebarTrigger = ({ name, tab, diff --git a/packages/excalidraw/components/Sidebar/common.ts b/packages/excalidraw/components/Sidebar/common.ts index 35c0c8bb1..239b16fc9 100644 --- a/packages/excalidraw/components/Sidebar/common.ts +++ b/packages/excalidraw/components/Sidebar/common.ts @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import React from "react"; + import type { AppState, SidebarName, SidebarTabName } from "../../types"; +import type { JSX } from "react"; export type SidebarTriggerProps = { name: SidebarName; diff --git a/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx b/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx index c2a37431b..650eca6b0 100644 --- a/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx +++ b/packages/excalidraw/components/Sidebar/siderbar.test.helpers.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { Excalidraw } from "../.."; import { GlobalTestState, diff --git a/packages/excalidraw/components/Stack.tsx b/packages/excalidraw/components/Stack.tsx index f45d47118..75e559aa3 100644 --- a/packages/excalidraw/components/Stack.tsx +++ b/packages/excalidraw/components/Stack.tsx @@ -1,8 +1,8 @@ -import "./Stack.scss"; - import React, { forwardRef } from "react"; import clsx from "clsx"; +import "./Stack.scss"; + type StackProps = { children: React.ReactNode; gap?: number; diff --git a/packages/excalidraw/components/Stats/Angle.tsx b/packages/excalidraw/components/Stats/Angle.tsx index 409476ada..10c76d519 100644 --- a/packages/excalidraw/components/Stats/Angle.tsx +++ b/packages/excalidraw/components/Stats/Angle.tsx @@ -1,15 +1,19 @@ +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; + +import type { Degrees } from "@excalidraw/math"; + import { mutateElement } from "../../element/mutateElement"; import { getBoundTextElement } from "../../element/textElement"; import { isArrowElement, isElbowArrow } from "../../element/typeChecks"; -import type { ExcalidrawElement } from "../../element/types"; import { angleIcon } from "../icons"; + import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable, updateBindings } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface AngleProps { element: ExcalidrawElement; diff --git a/packages/excalidraw/components/Stats/CanvasGrid.tsx b/packages/excalidraw/components/Stats/CanvasGrid.tsx index a08f709ae..4611365f4 100644 --- a/packages/excalidraw/components/Stats/CanvasGrid.tsx +++ b/packages/excalidraw/components/Stats/CanvasGrid.tsx @@ -1,8 +1,10 @@ +import { getNormalizedGridStep } from "../../scene"; + import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { getStepSizedValue } from "./utils"; -import { getNormalizedGridStep } from "../../scene"; interface PositionProps { property: "gridStep"; diff --git a/packages/excalidraw/components/Stats/Dimension.tsx b/packages/excalidraw/components/Stats/Dimension.tsx index ce096d280..f58c06acc 100644 --- a/packages/excalidraw/components/Stats/Dimension.tsx +++ b/packages/excalidraw/components/Stats/Dimension.tsx @@ -1,18 +1,21 @@ -import type { ExcalidrawElement } from "../../element/types"; -import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue, isPropertyEditable } from "./utils"; +import { clamp, round } from "@excalidraw/math"; + import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; -import { resizeSingleElement } from "../../element/resizeElements"; -import type Scene from "../../scene/Scene"; -import type { AppState } from "../../types"; -import { isImageElement } from "../../element/typeChecks"; import { MINIMAL_CROP_SIZE, getUncroppedWidthAndHeight, } from "../../element/cropElement"; import { mutateElement } from "../../element/mutateElement"; -import { clamp, round } from "@excalidraw/math"; +import { resizeSingleElement } from "../../element/resizeElements"; +import { isImageElement } from "../../element/typeChecks"; + +import DragInput from "./DragInput"; +import { getStepSizedValue, isPropertyEditable } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; +import type { AppState } from "../../types"; interface DimensionDragInputProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/DragInput.tsx b/packages/excalidraw/components/Stats/DragInput.tsx index 82d6419c0..fbea33e55 100644 --- a/packages/excalidraw/components/Stats/DragInput.tsx +++ b/packages/excalidraw/components/Stats/DragInput.tsx @@ -1,19 +1,22 @@ -import { useEffect, useRef, useState } from "react"; -import { EVENT } from "../../constants"; -import { KEYS } from "../../keys"; -import type { ElementsMap, ExcalidrawElement } from "../../element/types"; -import { deepCopyElement } from "../../element/newElement"; import clsx from "clsx"; +import { useEffect, useRef, useState } from "react"; + +import { EVENT } from "../../constants"; +import { deepCopyElement } from "../../element/newElement"; +import { KEYS } from "../../keys"; +import { CaptureUpdateAction } from "../../store"; +import { cloneJSON } from "../../utils"; import { useApp } from "../App"; import { InlineIcon } from "../InlineIcon"; -import type { StatsInputProperty } from "./utils"; + import { SMALLEST_DELTA } from "./utils"; -import { CaptureUpdateAction } from "../../store"; -import type Scene from "../../scene/Scene"; import "./DragInput.scss"; + +import type { StatsInputProperty } from "./utils"; +import type { ElementsMap, ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { cloneJSON } from "../../utils"; export type DragInputCallbackType< P extends StatsInputProperty, diff --git a/packages/excalidraw/components/Stats/FontSize.tsx b/packages/excalidraw/components/Stats/FontSize.tsx index 13dc6dbee..4fbdab833 100644 --- a/packages/excalidraw/components/Stats/FontSize.tsx +++ b/packages/excalidraw/components/Stats/FontSize.tsx @@ -1,17 +1,19 @@ +import { isTextElement, redrawTextBoundingBox } from "../../element"; +import { mutateElement } from "../../element/mutateElement"; +import { getBoundTextElement } from "../../element/textElement"; +import { hasBoundTextElement } from "../../element/typeChecks"; +import { fontSizeIcon } from "../icons"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; import type { ExcalidrawElement, ExcalidrawTextElement, } from "../../element/types"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { mutateElement } from "../../element/mutateElement"; -import { getStepSizedValue } from "./utils"; -import { fontSizeIcon } from "../icons"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import { isTextElement, redrawTextBoundingBox } from "../../element"; -import { hasBoundTextElement } from "../../element/typeChecks"; -import { getBoundTextElement } from "../../element/textElement"; interface FontSizeProps { element: ExcalidrawElement; diff --git a/packages/excalidraw/components/Stats/MultiAngle.tsx b/packages/excalidraw/components/Stats/MultiAngle.tsx index d9a78825a..ec314c183 100644 --- a/packages/excalidraw/components/Stats/MultiAngle.tsx +++ b/packages/excalidraw/components/Stats/MultiAngle.tsx @@ -1,16 +1,20 @@ +import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; + +import type { Degrees } from "@excalidraw/math"; + import { mutateElement } from "../../element/mutateElement"; import { getBoundTextElement } from "../../element/textElement"; import { isArrowElement } from "../../element/typeChecks"; -import type { ExcalidrawElement } from "../../element/types"; import { isInGroup } from "../../groups"; -import type Scene from "../../scene/Scene"; import { angleIcon } from "../icons"; + import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; import { getStepSizedValue, isPropertyEditable } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, radiansToDegrees } from "@excalidraw/math"; interface MultiAngleProps { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Stats/MultiDimension.tsx b/packages/excalidraw/components/Stats/MultiDimension.tsx index 04f193747..fb9cea942 100644 --- a/packages/excalidraw/components/Stats/MultiDimension.tsx +++ b/packages/excalidraw/components/Stats/MultiDimension.tsx @@ -1,4 +1,7 @@ +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; import { useMemo } from "react"; + +import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; import { getCommonBounds, isTextElement } from "../../element"; import { updateBoundElements } from "../../element/binding"; import { mutateElement } from "../../element/mutateElement"; @@ -10,6 +13,13 @@ import { getBoundTextElement, handleBindTextResize, } from "../../element/textElement"; + +import DragInput from "./DragInput"; +import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; +import { getElementsInAtomicUnit } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { AtomicUnit } from "./utils"; import type { ElementsMap, ExcalidrawElement, @@ -17,13 +27,6 @@ import type { } from "../../element/types"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; -import DragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; -import { getElementsInAtomicUnit } from "./utils"; -import type { AtomicUnit } from "./utils"; -import { MIN_WIDTH_OR_HEIGHT } from "../../constants"; -import { pointFrom, type GlobalPoint } from "@excalidraw/math"; interface MultiDimensionProps { property: "width" | "height"; diff --git a/packages/excalidraw/components/Stats/MultiFontSize.tsx b/packages/excalidraw/components/Stats/MultiFontSize.tsx index 419bbbc36..8335399ef 100644 --- a/packages/excalidraw/components/Stats/MultiFontSize.tsx +++ b/packages/excalidraw/components/Stats/MultiFontSize.tsx @@ -1,19 +1,21 @@ import { isTextElement, redrawTextBoundingBox } from "../../element"; import { mutateElement } from "../../element/mutateElement"; +import { getBoundTextElement } from "../../element/textElement"; import { hasBoundTextElement } from "../../element/typeChecks"; +import { isInGroup } from "../../groups"; +import { fontSizeIcon } from "../icons"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; import type { ExcalidrawElement, ExcalidrawTextElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { isInGroup } from "../../groups"; import type Scene from "../../scene/Scene"; -import { fontSizeIcon } from "../icons"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue } from "./utils"; import type { AppState } from "../../types"; -import { getBoundTextElement } from "../../element/textElement"; interface MultiFontSizeProps { elements: readonly ExcalidrawElement[]; diff --git a/packages/excalidraw/components/Stats/MultiPosition.tsx b/packages/excalidraw/components/Stats/MultiPosition.tsx index 8a29aa66d..a8fdacf29 100644 --- a/packages/excalidraw/components/Stats/MultiPosition.tsx +++ b/packages/excalidraw/components/Stats/MultiPosition.tsx @@ -1,3 +1,14 @@ +import { pointFrom, pointRotateRads } from "@excalidraw/math"; +import { useMemo } from "react"; + +import { getCommonBounds, isTextElement } from "../../element"; + +import StatsDragInput from "./DragInput"; +import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; +import { getElementsInAtomicUnit, moveElement } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { AtomicUnit } from "./utils"; import type { ElementsMap, ExcalidrawElement, @@ -5,15 +16,7 @@ import type { NonDeletedSceneElementsMap, } from "../../element/types"; import type Scene from "../../scene/Scene"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getAtomicUnits, getStepSizedValue, isPropertyEditable } from "./utils"; -import { getCommonBounds, isTextElement } from "../../element"; -import { useMemo } from "react"; -import { getElementsInAtomicUnit, moveElement } from "./utils"; -import type { AtomicUnit } from "./utils"; import type { AppState } from "../../types"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; interface MultiPositionProps { property: "x" | "y"; diff --git a/packages/excalidraw/components/Stats/Position.tsx b/packages/excalidraw/components/Stats/Position.tsx index 038e58ebc..08d0a8830 100644 --- a/packages/excalidraw/components/Stats/Position.tsx +++ b/packages/excalidraw/components/Stats/Position.tsx @@ -1,16 +1,19 @@ -import type { ElementsMap, ExcalidrawElement } from "../../element/types"; -import StatsDragInput from "./DragInput"; -import type { DragInputCallbackType } from "./DragInput"; -import { getStepSizedValue, moveElement } from "./utils"; -import type Scene from "../../scene/Scene"; -import type { AppState } from "../../types"; import { clamp, pointFrom, pointRotateRads, round } from "@excalidraw/math"; -import { isImageElement } from "../../element/typeChecks"; + import { getFlipAdjustedCropPosition, getUncroppedWidthAndHeight, } from "../../element/cropElement"; import { mutateElement } from "../../element/mutateElement"; +import { isImageElement } from "../../element/typeChecks"; + +import StatsDragInput from "./DragInput"; +import { getStepSizedValue, moveElement } from "./utils"; + +import type { DragInputCallbackType } from "./DragInput"; +import type { ElementsMap, ExcalidrawElement } from "../../element/types"; +import type Scene from "../../scene/Scene"; +import type { AppState } from "../../types"; interface PositionProps { property: "x" | "y"; diff --git a/packages/excalidraw/components/Stats/index.tsx b/packages/excalidraw/components/Stats/index.tsx index 2ccd93ca2..56764fefb 100644 --- a/packages/excalidraw/components/Stats/index.tsx +++ b/packages/excalidraw/components/Stats/index.tsx @@ -1,37 +1,40 @@ +import { round } from "@excalidraw/math"; +import clsx from "clsx"; +import throttle from "lodash.throttle"; import { useEffect, useMemo, useState, memo } from "react"; + +import { STATS_PANELS } from "../../constants"; import { getCommonBounds } from "../../element/bounds"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; +import { getUncroppedWidthAndHeight } from "../../element/cropElement"; +import { isElbowArrow, isImageElement } from "../../element/typeChecks"; +import { frameAndChildrenSelectedTogether } from "../../frame"; +import { elementsAreInSameGroup } from "../../groups"; import { t } from "../../i18n"; +import { isGridModeEnabled } from "../../snapping"; +import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App"; +import { Island } from "../Island"; +import { CloseIcon } from "../icons"; + +import Angle from "./Angle"; +import CanvasGrid from "./CanvasGrid"; +import Collapsible from "./Collapsible"; +import Dimension from "./Dimension"; +import FontSize from "./FontSize"; +import MultiAngle from "./MultiAngle"; +import MultiDimension from "./MultiDimension"; +import MultiFontSize from "./MultiFontSize"; +import MultiPosition from "./MultiPosition"; +import Position from "./Position"; +import { getAtomicUnits } from "./utils"; + +import "./Stats.scss"; + +import type { NonDeletedExcalidrawElement } from "../../element/types"; import type { AppClassProperties, AppState, ExcalidrawProps, } from "../../types"; -import { CloseIcon } from "../icons"; -import { Island } from "../Island"; -import throttle from "lodash.throttle"; -import Dimension from "./Dimension"; -import Angle from "./Angle"; -import FontSize from "./FontSize"; -import MultiDimension from "./MultiDimension"; -import { elementsAreInSameGroup } from "../../groups"; -import MultiAngle from "./MultiAngle"; -import MultiFontSize from "./MultiFontSize"; -import Position from "./Position"; -import MultiPosition from "./MultiPosition"; -import Collapsible from "./Collapsible"; -import { useExcalidrawAppState, useExcalidrawSetAppState } from "../App"; -import { getAtomicUnits } from "./utils"; -import { STATS_PANELS } from "../../constants"; -import { isElbowArrow, isImageElement } from "../../element/typeChecks"; -import CanvasGrid from "./CanvasGrid"; -import clsx from "clsx"; - -import "./Stats.scss"; -import { isGridModeEnabled } from "../../snapping"; -import { getUncroppedWidthAndHeight } from "../../element/cropElement"; -import { round } from "@excalidraw/math"; -import { frameAndChildrenSelectedTogether } from "../../frame"; interface StatsProps { app: AppClassProperties; diff --git a/packages/excalidraw/components/Stats/stats.test.tsx b/packages/excalidraw/components/Stats/stats.test.tsx index 49d6a625f..b1fe0d685 100644 --- a/packages/excalidraw/components/Stats/stats.test.tsx +++ b/packages/excalidraw/components/Stats/stats.test.tsx @@ -1,31 +1,35 @@ -import React from "react"; +import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math"; import { act, fireEvent, queryByTestId } from "@testing-library/react"; +import React from "react"; +import { vi } from "vitest"; + +import type { Degrees } from "@excalidraw/math"; + +import { Excalidraw, mutateElement } from "../.."; +import { actionGroup } from "../../actions"; +import { getCommonBounds, isTextElement } from "../../element"; +import { isInGroup } from "../../groups"; +import { t } from "../../i18n"; +import { reseed } from "../../random"; +import * as StaticScene from "../../renderer/staticScene"; +import { API } from "../../tests/helpers/api"; import { Keyboard, Pointer, UI } from "../../tests/helpers/ui"; -import { getStepSizedValue } from "./utils"; +import { getTextEditor, updateTextEditor } from "../../tests/queries/dom"; import { GlobalTestState, mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, } from "../../tests/test-utils"; -import * as StaticScene from "../../renderer/staticScene"; -import { vi } from "vitest"; -import { reseed } from "../../random"; import { setDateTimeForTests } from "../../utils"; -import { Excalidraw, mutateElement } from "../.."; -import { t } from "../../i18n"; + +import { getStepSizedValue } from "./utils"; + import type { ExcalidrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, } from "../../element/types"; -import { getTextEditor, updateTextEditor } from "../../tests/queries/dom"; -import { getCommonBounds, isTextElement } from "../../element"; -import { API } from "../../tests/helpers/api"; -import { actionGroup } from "../../actions"; -import { isInGroup } from "../../groups"; -import type { Degrees } from "@excalidraw/math"; -import { degreesToRadians, pointFrom, pointRotateRads } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/components/Stats/utils.ts b/packages/excalidraw/components/Stats/utils.ts index 61555baeb..219e02fa5 100644 --- a/packages/excalidraw/components/Stats/utils.ts +++ b/packages/excalidraw/components/Stats/utils.ts @@ -1,5 +1,7 @@ -import type { Radians } from "@excalidraw/math"; import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + import { bindOrUnbindLinearElements, updateBoundElements, @@ -11,17 +13,18 @@ import { isLinearElement, isTextElement, } from "../../element/typeChecks"; +import { + getSelectedGroupIds, + getElementsInGroup, + isInGroup, +} from "../../groups"; + import type { ElementsMap, ExcalidrawElement, NonDeletedExcalidrawElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { - getSelectedGroupIds, - getElementsInGroup, - isInGroup, -} from "../../groups"; import type Scene from "../../scene/Scene"; import type { AppState } from "../../types"; diff --git a/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx b/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx index 83fb91d0e..b8cd48dfa 100644 --- a/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx +++ b/packages/excalidraw/components/TTDDialog/MermaidToExcalidraw.tsx @@ -1,25 +1,29 @@ import { useState, useRef, useEffect, useDeferredValue } from "react"; -import type { BinaryFiles } from "../../types"; + import { useApp } from "../App"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; import { ArrowRightIcon } from "../icons"; -import "./MermaidToExcalidraw.scss"; +import { EDITOR_LS_KEYS } from "../../constants"; +import { EditorLocalStorage } from "../../data/EditorLocalStorage"; import { t } from "../../i18n"; +import { debounce, isDevEnv } from "../../utils"; import Trans from "../Trans"; -import type { MermaidToExcalidrawLibProps } from "./common"; + +import { TTDDialogInput } from "./TTDDialogInput"; +import { TTDDialogOutput } from "./TTDDialogOutput"; +import { TTDDialogPanel } from "./TTDDialogPanel"; +import { TTDDialogPanels } from "./TTDDialogPanels"; +import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; import { convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common"; -import { TTDDialogPanels } from "./TTDDialogPanels"; -import { TTDDialogPanel } from "./TTDDialogPanel"; -import { TTDDialogInput } from "./TTDDialogInput"; -import { TTDDialogOutput } from "./TTDDialogOutput"; -import { EditorLocalStorage } from "../../data/EditorLocalStorage"; -import { EDITOR_LS_KEYS } from "../../constants"; -import { debounce, isDevEnv } from "../../utils"; -import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; + +import "./MermaidToExcalidraw.scss"; + +import type { BinaryFiles } from "../../types"; +import type { MermaidToExcalidrawLibProps } from "./common"; +import type { NonDeletedExcalidrawElement } from "../../element/types"; const MERMAID_EXAMPLE = "flowchart TD\n A[Christmas] -->|Get money| B(Go shopping)\n B --> C{Let me think}\n C -->|One| D[Laptop]\n C -->|Two| E[iPhone]\n C -->|Three| F[Car]"; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx index c77dfbf68..3b9b868f7 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialog.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialog.tsx @@ -1,35 +1,39 @@ -import { Dialog } from "../Dialog"; +import { isFiniteNumber } from "@excalidraw/math"; +import { useEffect, useRef, useState } from "react"; + +import { trackEvent } from "../../analytics"; +import { useUIAppState } from "../../context/ui-appState"; +import { atom, useAtom } from "../../editor-jotai"; +import { t } from "../../i18n"; import { useApp, useExcalidrawSetAppState } from "../App"; +import { Dialog } from "../Dialog"; +import { InlineIcon } from "../InlineIcon"; +import { withInternalFallback } from "../hoc/withInternalFallback"; +import { ArrowRightIcon } from "../icons"; + import MermaidToExcalidraw from "./MermaidToExcalidraw"; import TTDDialogTabs from "./TTDDialogTabs"; -import type { ChangeEventHandler } from "react"; -import { useEffect, useRef, useState } from "react"; -import { useUIAppState } from "../../context/ui-appState"; -import { withInternalFallback } from "../hoc/withInternalFallback"; import { TTDDialogTabTriggers } from "./TTDDialogTabTriggers"; import { TTDDialogTabTrigger } from "./TTDDialogTabTrigger"; import { TTDDialogTab } from "./TTDDialogTab"; -import { t } from "../../i18n"; import { TTDDialogInput } from "./TTDDialogInput"; import { TTDDialogOutput } from "./TTDDialogOutput"; import { TTDDialogPanel } from "./TTDDialogPanel"; import { TTDDialogPanels } from "./TTDDialogPanels"; -import type { MermaidToExcalidrawLibProps } from "./common"; + import { convertMermaidToExcalidraw, insertToEditor, saveMermaidDataToStorage, } from "./common"; -import type { NonDeletedExcalidrawElement } from "../../element/types"; -import type { BinaryFiles } from "../../types"; -import { ArrowRightIcon } from "../icons"; +import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; import "./TTDDialog.scss"; -import { atom, useAtom } from "../../editor-jotai"; -import { trackEvent } from "../../analytics"; -import { InlineIcon } from "../InlineIcon"; -import { TTDDialogSubmitShortcut } from "./TTDDialogSubmitShortcut"; -import { isFiniteNumber } from "@excalidraw/math"; + +import type { ChangeEventHandler } from "react"; +import type { MermaidToExcalidrawLibProps } from "./common"; +import type { NonDeletedExcalidrawElement } from "../../element/types"; +import type { BinaryFiles } from "../../types"; const MIN_PROMPT_LENGTH = 3; const MAX_PROMPT_LENGTH = 1000; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx index e11d0dc3f..8e349643e 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogInput.tsx @@ -1,8 +1,10 @@ -import type { ChangeEventHandler } from "react"; import { useEffect, useRef } from "react"; + import { EVENT } from "../../constants"; import { KEYS } from "../../keys"; +import type { ChangeEventHandler } from "react"; + interface TTDDialogInputProps { input: string; placeholder: string; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx index 0a78e4969..82aede8ae 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogPanel.tsx @@ -1,8 +1,10 @@ -import type { ReactNode } from "react"; -import { Button } from "../Button"; import clsx from "clsx"; + +import { Button } from "../Button"; import Spinner from "../Spinner"; +import type { ReactNode } from "react"; + interface TTDDialogPanelProps { label: string; children: ReactNode; diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx index 439f92844..1c9075e7d 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogTabs.tsx @@ -1,8 +1,10 @@ import * as RadixTabs from "@radix-ui/react-tabs"; -import type { ReactNode } from "react"; import { useRef } from "react"; -import { useExcalidrawSetAppState } from "../App"; + import { isMemberOf } from "../../utils"; +import { useExcalidrawSetAppState } from "../App"; + +import type { ReactNode } from "react"; const TTDDialogTabs = ( props: { diff --git a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx index a73f31a68..833b659fe 100644 --- a/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx +++ b/packages/excalidraw/components/TTDDialog/TTDDialogTrigger.tsx @@ -1,11 +1,12 @@ -import type { JSX } from "react"; -import type { ReactNode } from "react"; -import { useTunnels } from "../../context/tunnels"; -import DropdownMenu from "../dropdownMenu/DropdownMenu"; -import { useExcalidrawSetAppState } from "../App"; -import { brainIcon } from "../icons"; -import { t } from "../../i18n"; import { trackEvent } from "../../analytics"; +import { useTunnels } from "../../context/tunnels"; +import { t } from "../../i18n"; +import { useExcalidrawSetAppState } from "../App"; +import DropdownMenu from "../dropdownMenu/DropdownMenu"; +import { brainIcon } from "../icons"; + +import type { ReactNode } from "react"; +import type { JSX } from "react"; export const TTDDialogTrigger = ({ children, diff --git a/packages/excalidraw/components/TTDDialog/common.ts b/packages/excalidraw/components/TTDDialog/common.ts index 4191126a4..89c342c65 100644 --- a/packages/excalidraw/components/TTDDialog/common.ts +++ b/packages/excalidraw/components/TTDDialog/common.ts @@ -1,12 +1,14 @@ import type { MermaidConfig } from "@excalidraw/mermaid-to-excalidraw"; import type { MermaidToExcalidrawResult } from "@excalidraw/mermaid-to-excalidraw/dist/interfaces"; + import { DEFAULT_EXPORT_PADDING, EDITOR_LS_KEYS } from "../../constants"; +import { EditorLocalStorage } from "../../data/EditorLocalStorage"; +import { canvasToBlob } from "../../data/blob"; +import { t } from "../../i18n"; import { convertToExcalidrawElements, exportToCanvas } from "../../index"; + import type { NonDeletedExcalidrawElement } from "../../element/types"; import type { AppClassProperties, BinaryFiles } from "../../types"; -import { canvasToBlob } from "../../data/blob"; -import { EditorLocalStorage } from "../../data/EditorLocalStorage"; -import { t } from "../../i18n"; const resetPreview = ({ canvasRef, diff --git a/packages/excalidraw/components/TextField.tsx b/packages/excalidraw/components/TextField.tsx index c5bdc8260..d6bc315b1 100644 --- a/packages/excalidraw/components/TextField.tsx +++ b/packages/excalidraw/components/TextField.tsx @@ -1,4 +1,4 @@ -import type { KeyboardEvent } from "react"; +import clsx from "clsx"; import { forwardRef, useRef, @@ -6,12 +6,14 @@ import { useLayoutEffect, useState, } from "react"; -import clsx from "clsx"; -import "./TextField.scss"; import { Button } from "./Button"; import { eyeIcon, eyeClosedIcon } from "./icons"; +import "./TextField.scss"; + +import type { KeyboardEvent } from "react"; + type TextFieldProps = { onChange?: (value: string) => void; onClick?: () => void; diff --git a/packages/excalidraw/components/Toast.tsx b/packages/excalidraw/components/Toast.tsx index d99c9f648..a7167c00f 100644 --- a/packages/excalidraw/components/Toast.tsx +++ b/packages/excalidraw/components/Toast.tsx @@ -1,9 +1,12 @@ -import type { CSSProperties } from "react"; import { useCallback, useEffect, useRef } from "react"; + import { CloseIcon } from "./icons"; -import "./Toast.scss"; import { ToolButton } from "./ToolButton"; +import "./Toast.scss"; + +import type { CSSProperties } from "react"; + const DEFAULT_TOAST_TIMEOUT = 5000; export const Toast = ({ diff --git a/packages/excalidraw/components/ToolButton.tsx b/packages/excalidraw/components/ToolButton.tsx index 09b0b6cf8..fb76731b0 100644 --- a/packages/excalidraw/components/ToolButton.tsx +++ b/packages/excalidraw/components/ToolButton.tsx @@ -1,13 +1,16 @@ +import clsx from "clsx"; +import React, { useEffect, useRef, useState } from "react"; + +import { AbortError } from "../errors"; +import { isPromiseLike } from "../utils"; + import "./ToolIcon.scss"; -import type { CSSProperties } from "react"; -import React, { useEffect, useRef, useState } from "react"; -import clsx from "clsx"; -import { useExcalidrawContainer } from "./App"; -import { AbortError } from "../errors"; import Spinner from "./Spinner"; +import { useExcalidrawContainer } from "./App"; + import type { PointerType } from "../element/types"; -import { isPromiseLike } from "../utils"; +import type { CSSProperties } from "react"; export type ToolButtonSize = "small" | "medium"; diff --git a/packages/excalidraw/components/Tooltip.tsx b/packages/excalidraw/components/Tooltip.tsx index 38c04ef23..9c7c7ea0c 100644 --- a/packages/excalidraw/components/Tooltip.tsx +++ b/packages/excalidraw/components/Tooltip.tsx @@ -1,7 +1,7 @@ -import "./Tooltip.scss"; - import React, { useEffect } from "react"; +import "./Tooltip.scss"; + export const getTooltipDiv = () => { const existingDiv = document.querySelector( ".excalidraw-tooltip", diff --git a/packages/excalidraw/components/Trans.test.tsx b/packages/excalidraw/components/Trans.test.tsx index c331796bd..077fcb88c 100644 --- a/packages/excalidraw/components/Trans.test.tsx +++ b/packages/excalidraw/components/Trans.test.tsx @@ -1,10 +1,11 @@ import { render } from "@testing-library/react"; +import { EditorJotaiProvider } from "../editor-jotai"; import fallbackLangData from "../locales/en.json"; import Trans from "./Trans"; + import type { TranslationKeys } from "../i18n"; -import { EditorJotaiProvider } from "../editor-jotai"; describe("Test ", () => { it("should translate the the strings correctly", () => { diff --git a/packages/excalidraw/components/Trans.tsx b/packages/excalidraw/components/Trans.tsx index 0cb0f78cb..7a6215c89 100644 --- a/packages/excalidraw/components/Trans.tsx +++ b/packages/excalidraw/components/Trans.tsx @@ -1,8 +1,9 @@ import React from "react"; -import type { TranslationKeys } from "../i18n"; import { useI18n } from "../i18n"; +import type { TranslationKeys } from "../i18n"; + // Used for splitting i18nKey into tokens in Trans component // Example: // "Please click {{location}} to continue.".split(SPLIT_REGEX).filter(Boolean) diff --git a/packages/excalidraw/components/UserList.tsx b/packages/excalidraw/components/UserList.tsx index 9fbfc1aed..6c74411a1 100644 --- a/packages/excalidraw/components/UserList.tsx +++ b/packages/excalidraw/components/UserList.tsx @@ -1,20 +1,22 @@ -import "./UserList.scss"; - -import React, { useLayoutEffect } from "react"; -import clsx from "clsx"; -import type { Collaborator, SocketId } from "../types"; -import { Tooltip } from "./Tooltip"; -import { useExcalidrawActionManager } from "./App"; -import type { ActionManager } from "../actions/manager"; - import * as Popover from "@radix-ui/react-popover"; -import { Island } from "./Island"; -import { QuickSearch } from "./QuickSearch"; +import clsx from "clsx"; +import React, { useLayoutEffect } from "react"; + +import { supportsResizeObserver } from "../constants"; import { t } from "../i18n"; import { isShallowEqual } from "../utils"; -import { supportsResizeObserver } from "../constants"; -import type { MarkRequired } from "../utility-types"; + +import { useExcalidrawActionManager } from "./App"; +import { Island } from "./Island"; +import { QuickSearch } from "./QuickSearch"; import { ScrollableList } from "./ScrollableList"; +import { Tooltip } from "./Tooltip"; + +import "./UserList.scss"; + +import type { ActionManager } from "../actions/manager"; +import type { Collaborator, SocketId } from "../types"; +import type { MarkRequired } from "../utility-types"; export type GoToCollaboratorComponentProps = { socketId: SocketId; diff --git a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx index 03ae0f6b6..8388e5e6c 100644 --- a/packages/excalidraw/components/canvases/InteractiveCanvas.tsx +++ b/packages/excalidraw/components/canvases/InteractiveCanvas.tsx @@ -1,20 +1,22 @@ import React, { useEffect, useRef } from "react"; -import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils"; + import { CURSOR_TYPE } from "../../constants"; import { t } from "../../i18n"; -import type { DOMAttributes } from "react"; -import type { AppState, Device, InteractiveCanvasAppState } from "../../types"; +import { isRenderThrottlingEnabled } from "../../reactUtils"; +import { renderInteractiveScene } from "../../renderer/interactiveScene"; +import { isShallowEqual, sceneCoordsToViewportCoords } from "../../utils"; + +import type { + NonDeletedExcalidrawElement, + NonDeletedSceneElementsMap, +} from "../../element/types"; import type { InteractiveCanvasRenderConfig, RenderableElementsMap, RenderInteractiveSceneCallback, } from "../../scene/types"; -import type { - NonDeletedExcalidrawElement, - NonDeletedSceneElementsMap, -} from "../../element/types"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; -import { renderInteractiveScene } from "../../renderer/interactiveScene"; +import type { AppState, Device, InteractiveCanvasAppState } from "../../types"; +import type { DOMAttributes } from "react"; type InteractiveCanvasProps = { containerRef: React.RefObject; diff --git a/packages/excalidraw/components/canvases/NewElementCanvas.tsx b/packages/excalidraw/components/canvases/NewElementCanvas.tsx index 181567110..524d6af34 100644 --- a/packages/excalidraw/components/canvases/NewElementCanvas.tsx +++ b/packages/excalidraw/components/canvases/NewElementCanvas.tsx @@ -1,13 +1,15 @@ import { useEffect, useRef } from "react"; + +import { isRenderThrottlingEnabled } from "../../reactUtils"; +import { renderNewElementScene } from "../../renderer/renderNewElementScene"; + import type { NonDeletedSceneElementsMap } from "../../element/types"; -import type { AppState } from "../../types"; import type { RenderableElementsMap, StaticCanvasRenderConfig, } from "../../scene/types"; +import type { AppState } from "../../types"; import type { RoughCanvas } from "roughjs/bin/canvas"; -import { renderNewElementScene } from "../../renderer/renderNewElementScene"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; interface NewElementCanvasProps { appState: AppState; diff --git a/packages/excalidraw/components/canvases/StaticCanvas.tsx b/packages/excalidraw/components/canvases/StaticCanvas.tsx index 9185bdd5c..6e2df9537 100644 --- a/packages/excalidraw/components/canvases/StaticCanvas.tsx +++ b/packages/excalidraw/components/canvases/StaticCanvas.tsx @@ -1,17 +1,19 @@ import React, { useEffect, useRef } from "react"; -import type { RoughCanvas } from "roughjs/bin/canvas"; + +import { isRenderThrottlingEnabled } from "../../reactUtils"; import { renderStaticScene } from "../../renderer/staticScene"; import { isShallowEqual } from "../../utils"; -import type { AppState, StaticCanvasAppState } from "../../types"; -import type { - RenderableElementsMap, - StaticCanvasRenderConfig, -} from "../../scene/types"; + import type { NonDeletedExcalidrawElement, NonDeletedSceneElementsMap, } from "../../element/types"; -import { isRenderThrottlingEnabled } from "../../reactUtils"; +import type { + RenderableElementsMap, + StaticCanvasRenderConfig, +} from "../../scene/types"; +import type { AppState, StaticCanvasAppState } from "../../types"; +import type { RoughCanvas } from "roughjs/bin/canvas"; type StaticCanvasProps = { canvas: HTMLCanvasElement; diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx index 0c8deec87..d4c0b7a8d 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenu.test.tsx @@ -1,4 +1,5 @@ import React from "react"; + import { Excalidraw } from "../../index"; import { KEYS } from "../../keys"; import { Keyboard } from "../../tests/helpers/ui"; diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx index 8f4ce435b..e1412e20b 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenu.tsx @@ -1,11 +1,12 @@ import React from "react"; -import DropdownMenuTrigger from "./DropdownMenuTrigger"; -import DropdownMenuItem from "./DropdownMenuItem"; -import MenuSeparator from "./DropdownMenuSeparator"; -import DropdownMenuGroup from "./DropdownMenuGroup"; + import DropdownMenuContent from "./DropdownMenuContent"; -import DropdownMenuItemLink from "./DropdownMenuItemLink"; +import DropdownMenuGroup from "./DropdownMenuGroup"; +import DropdownMenuItem from "./DropdownMenuItem"; import DropdownMenuItemCustom from "./DropdownMenuItemCustom"; +import DropdownMenuItemLink from "./DropdownMenuItemLink"; +import MenuSeparator from "./DropdownMenuSeparator"; +import DropdownMenuTrigger from "./DropdownMenuTrigger"; import { getMenuContentComponent, getMenuTriggerComponent, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx index a203124d6..24a0a4d27 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuContent.tsx @@ -1,13 +1,15 @@ -import { Island } from "../Island"; -import { useDevice } from "../App"; import clsx from "clsx"; -import Stack from "../Stack"; import React, { useEffect, useRef } from "react"; -import { DropdownMenuContentPropsContext } from "./common"; -import { useOutsideClick } from "../../hooks/useOutsideClick"; -import { KEYS } from "../../keys"; + import { EVENT } from "../../constants"; +import { useOutsideClick } from "../../hooks/useOutsideClick"; import { useStable } from "../../hooks/useStable"; +import { KEYS } from "../../keys"; +import { useDevice } from "../App"; +import { Island } from "../Island"; +import Stack from "../Stack"; + +import { DropdownMenuContentPropsContext } from "./common"; const MenuContent = ({ children, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx index 1ff53f8af..fc19bd1bf 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItem.tsx @@ -1,13 +1,16 @@ -import type { JSX } from "react"; import React, { useEffect, useRef } from "react"; + +import { THEME } from "../../constants"; +import { useExcalidrawAppState } from "../App"; + +import MenuItemContent from "./DropdownMenuItemContent"; import { getDropdownMenuItemClassName, useHandleDropdownMenuItemClick, } from "./common"; -import MenuItemContent from "./DropdownMenuItemContent"; -import { useExcalidrawAppState } from "../App"; -import { THEME } from "../../constants"; + import type { ValueOf } from "../../utility-types"; +import type { JSX } from "react"; const DropdownMenuItem = ({ icon, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx index 000b8c344..b2f9e7e0a 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemContent.tsx @@ -1,6 +1,7 @@ -import type { JSX } from "react"; import { useDevice } from "../App"; +import type { JSX } from "react"; + const MenuItemContent = ({ textStyle, icon, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx index 2dbee7584..1457f5ae7 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuItemLink.tsx @@ -1,11 +1,13 @@ -import MenuItemContent from "./DropdownMenuItemContent"; -import type { JSX } from "react"; import React from "react"; + +import MenuItemContent from "./DropdownMenuItemContent"; import { getDropdownMenuItemClassName, useHandleDropdownMenuItemClick, } from "./common"; +import type { JSX } from "react"; + const DropdownMenuItemLink = ({ icon, shortcut, diff --git a/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx b/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx index e7369ba57..a7301fb44 100644 --- a/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx +++ b/packages/excalidraw/components/dropdownMenu/DropdownMenuTrigger.tsx @@ -1,4 +1,5 @@ import clsx from "clsx"; + import { useDevice } from "../App"; const MenuTrigger = ({ diff --git a/packages/excalidraw/components/dropdownMenu/common.ts b/packages/excalidraw/components/dropdownMenu/common.ts index a2a46fc93..312b78aae 100644 --- a/packages/excalidraw/components/dropdownMenu/common.ts +++ b/packages/excalidraw/components/dropdownMenu/common.ts @@ -1,4 +1,5 @@ import React, { useContext } from "react"; + import { EVENT } from "../../constants"; import { composeEventHandlers } from "../../utils"; diff --git a/packages/excalidraw/components/footer/Footer.tsx b/packages/excalidraw/components/footer/Footer.tsx index ccbe9eaee..427628e7c 100644 --- a/packages/excalidraw/components/footer/Footer.tsx +++ b/packages/excalidraw/components/footer/Footer.tsx @@ -1,6 +1,7 @@ import clsx from "clsx"; + import { actionShortcuts } from "../../actions"; -import type { ActionManager } from "../../actions/manager"; +import { useTunnels } from "../../context/tunnels"; import { ExitZenModeAction, FinalizeAction, @@ -8,10 +9,11 @@ import { ZoomActions, } from "../Actions"; import { useDevice } from "../App"; -import { useTunnels } from "../../context/tunnels"; import { HelpButton } from "../HelpButton"; import { Section } from "../Section"; import Stack from "../Stack"; + +import type { ActionManager } from "../../actions/manager"; import type { UIAppState } from "../../types"; const Footer = ({ diff --git a/packages/excalidraw/components/footer/FooterCenter.tsx b/packages/excalidraw/components/footer/FooterCenter.tsx index 55a0fb998..6a44581de 100644 --- a/packages/excalidraw/components/footer/FooterCenter.tsx +++ b/packages/excalidraw/components/footer/FooterCenter.tsx @@ -1,8 +1,10 @@ import clsx from "clsx"; + import { useTunnels } from "../../context/tunnels"; -import "./FooterCenter.scss"; import { useUIAppState } from "../../context/ui-appState"; +import "./FooterCenter.scss"; + const FooterCenter = ({ children }: { children?: React.ReactNode }) => { const { FooterCenterTunnel } = useTunnels(); const appState = useUIAppState(); diff --git a/packages/excalidraw/components/hoc/withInternalFallback.test.tsx b/packages/excalidraw/components/hoc/withInternalFallback.test.tsx index 554313377..1f30a64c4 100644 --- a/packages/excalidraw/components/hoc/withInternalFallback.test.tsx +++ b/packages/excalidraw/components/hoc/withInternalFallback.test.tsx @@ -1,6 +1,7 @@ import React from "react"; -import { render, queryAllByTestId } from "../../tests/test-utils"; + import { Excalidraw, MainMenu } from "../../index"; +import { render, queryAllByTestId } from "../../tests/test-utils"; describe("Test internal component fallback rendering", () => { it("should render only one menu per excalidraw instance (custom menu first scenario)", async () => { diff --git a/packages/excalidraw/components/hoc/withInternalFallback.tsx b/packages/excalidraw/components/hoc/withInternalFallback.tsx index 5906b30f5..298f58dd9 100644 --- a/packages/excalidraw/components/hoc/withInternalFallback.tsx +++ b/packages/excalidraw/components/hoc/withInternalFallback.tsx @@ -1,4 +1,5 @@ import React, { useLayoutEffect, useRef } from "react"; + import { useTunnels } from "../../context/tunnels"; import { atom } from "../../editor-jotai"; diff --git a/packages/excalidraw/components/hyperlink/Hyperlink.tsx b/packages/excalidraw/components/hyperlink/Hyperlink.tsx index 4d3dce640..88983aeab 100644 --- a/packages/excalidraw/components/hyperlink/Hyperlink.tsx +++ b/packages/excalidraw/components/hyperlink/Hyperlink.tsx @@ -1,20 +1,5 @@ -import type { AppState, ExcalidrawProps, UIAppState } from "../../types"; -import { - sceneCoordsToViewportCoords, - viewportCoordsToSceneCoords, - wrapEvent, -} from "../../utils"; -import { getEmbedLink, embeddableURLValidator } from "../../element/embeddable"; -import { mutateElement } from "../../element/mutateElement"; -import type { - ElementsMap, - ExcalidrawEmbeddableElement, - NonDeletedExcalidrawElement, -} from "../../element/types"; - -import { ToolButton } from "../ToolButton"; -import { FreedrawIcon, TrashIcon, elementLinkIcon } from "../icons"; -import { t } from "../../i18n"; +import { pointFrom, type GlobalPoint } from "@excalidraw/math"; +import clsx from "clsx"; import { useCallback, useEffect, @@ -22,23 +7,40 @@ import { useRef, useState, } from "react"; -import clsx from "clsx"; -import { KEYS } from "../../keys"; -import { EVENT, HYPERLINK_TOOLTIP_DELAY } from "../../constants"; -import { getElementAbsoluteCoords } from "../../element/bounds"; -import { getTooltipDiv, updateTooltipPosition } from "../../components/Tooltip"; -import { getSelectedElements } from "../../scene"; -import { hitElementBoundingBox } from "../../element/collision"; -import { isLocalLink, normalizeLink } from "../../data/url"; + import { trackEvent } from "../../analytics"; -import { useAppProps, useDevice, useExcalidrawAppState } from "../App"; -import { isEmbeddableElement } from "../../element/typeChecks"; -import { getLinkHandleFromCoords } from "./helpers"; -import { pointFrom, type GlobalPoint } from "@excalidraw/math"; +import { getTooltipDiv, updateTooltipPosition } from "../../components/Tooltip"; +import { EVENT, HYPERLINK_TOOLTIP_DELAY } from "../../constants"; +import { isLocalLink, normalizeLink } from "../../data/url"; +import { getElementAbsoluteCoords } from "../../element/bounds"; +import { hitElementBoundingBox } from "../../element/collision"; import { isElementLink } from "../../element/elementLink"; +import { getEmbedLink, embeddableURLValidator } from "../../element/embeddable"; +import { mutateElement } from "../../element/mutateElement"; +import { t } from "../../i18n"; +import { + sceneCoordsToViewportCoords, + viewportCoordsToSceneCoords, + wrapEvent, +} from "../../utils"; +import { useAppProps, useDevice, useExcalidrawAppState } from "../App"; +import { ToolButton } from "../ToolButton"; +import { FreedrawIcon, TrashIcon, elementLinkIcon } from "../icons"; +import { KEYS } from "../../keys"; +import { getSelectedElements } from "../../scene"; +import { isEmbeddableElement } from "../../element/typeChecks"; + +import { getLinkHandleFromCoords } from "./helpers"; import "./Hyperlink.scss"; +import type { + ElementsMap, + ExcalidrawEmbeddableElement, + NonDeletedExcalidrawElement, +} from "../../element/types"; +import type { AppState, ExcalidrawProps, UIAppState } from "../../types"; + const POPUP_WIDTH = 380; const POPUP_HEIGHT = 42; const POPUP_PADDING = 5; diff --git a/packages/excalidraw/components/hyperlink/helpers.ts b/packages/excalidraw/components/hyperlink/helpers.ts index 75c5dad9c..3d39e2ebe 100644 --- a/packages/excalidraw/components/hyperlink/helpers.ts +++ b/packages/excalidraw/components/hyperlink/helpers.ts @@ -1,14 +1,17 @@ -import type { GlobalPoint, Radians } from "@excalidraw/math"; import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { GlobalPoint, Radians } from "@excalidraw/math"; + import { MIME_TYPES } from "../../constants"; -import type { Bounds } from "../../element/bounds"; import { getElementAbsoluteCoords } from "../../element/bounds"; import { hitElementBoundingBox } from "../../element/collision"; +import { DEFAULT_LINK_SIZE } from "../../renderer/renderElement"; + +import type { Bounds } from "../../element/bounds"; import type { ElementsMap, NonDeletedExcalidrawElement, } from "../../element/types"; -import { DEFAULT_LINK_SIZE } from "../../renderer/renderElement"; import type { AppState, UIAppState } from "../../types"; export const EXTERNAL_LINK_IMG = document.createElement("img"); diff --git a/packages/excalidraw/components/icons.tsx b/packages/excalidraw/components/icons.tsx index 073d7a9f7..03e6ca2bb 100644 --- a/packages/excalidraw/components/icons.tsx +++ b/packages/excalidraw/components/icons.tsx @@ -6,13 +6,14 @@ // Note: when adding new icons, review https://developer.mozilla.org/en-US/docs/Mozilla/Developer_guide/RTL_Guidelines // to determine whether or not the icons should be mirrored in right-to-left languages. +import clsx from "clsx"; +import oc from "open-color"; import React from "react"; -import oc from "open-color"; -import clsx from "clsx"; -import type { Theme } from "../element/types"; import { THEME } from "../constants"; +import type { Theme } from "../element/types"; + export const iconFillColor = (theme: Theme) => "var(--icon-fill-color)"; const handlerColor = (theme: Theme) => diff --git a/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx b/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx index a22bc523a..1aa187167 100644 --- a/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx +++ b/packages/excalidraw/components/live-collaboration/LiveCollaborationTrigger.tsx @@ -1,12 +1,12 @@ -import { t } from "../../i18n"; -import { share } from "../icons"; -import { Button } from "../Button"; - import clsx from "clsx"; -import "./LiveCollaborationTrigger.scss"; +import { t } from "../../i18n"; +import { Button } from "../Button"; +import { share } from "../icons"; import { useUIAppState } from "../../context/ui-appState"; +import "./LiveCollaborationTrigger.scss"; + const LiveCollaborationTrigger = ({ isCollaborating, onSelect, diff --git a/packages/excalidraw/components/main-menu/DefaultItems.tsx b/packages/excalidraw/components/main-menu/DefaultItems.tsx index 632ea4ffa..c2307d521 100644 --- a/packages/excalidraw/components/main-menu/DefaultItems.tsx +++ b/packages/excalidraw/components/main-menu/DefaultItems.tsx @@ -1,11 +1,32 @@ +import clsx from "clsx"; + +import { + actionClearCanvas, + actionLoadScene, + actionSaveToActiveFile, + actionShortcuts, + actionToggleSearchMenu, + actionToggleTheme, +} from "../../actions"; import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { trackEvent } from "../../analytics"; +import { THEME } from "../../constants"; +import { useUIAppState } from "../../context/ui-appState"; +import { useSetAtom } from "../../editor-jotai"; import { useI18n } from "../../i18n"; +import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; import { useExcalidrawSetAppState, useExcalidrawActionManager, useExcalidrawElements, useAppProps, } from "../App"; +import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState"; +import Trans from "../Trans"; +import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem"; +import DropdownMenuItemContentRadio from "../dropdownMenu/DropdownMenuItemContentRadio"; +import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink"; +import { GithubIcon, DiscordIcon, XBrandIcon } from "../icons"; import { boltIcon, DeviceDesktopIcon, @@ -20,29 +41,11 @@ import { TrashIcon, usersIcon, } from "../icons"; -import { GithubIcon, DiscordIcon, XBrandIcon } from "../icons"; -import DropdownMenuItem from "../dropdownMenu/DropdownMenuItem"; -import DropdownMenuItemLink from "../dropdownMenu/DropdownMenuItemLink"; -import { - actionClearCanvas, - actionLoadScene, - actionSaveToActiveFile, - actionShortcuts, - actionToggleSearchMenu, - actionToggleTheme, -} from "../../actions"; -import clsx from "clsx"; -import { activeConfirmDialogAtom } from "../ActiveConfirmDialog"; -import { useSetAtom } from "../../editor-jotai"; -import { useUIAppState } from "../../context/ui-appState"; -import { openConfirmModal } from "../OverwriteConfirm/OverwriteConfirmState"; -import Trans from "../Trans"; -import DropdownMenuItemContentRadio from "../dropdownMenu/DropdownMenuItemContentRadio"; -import { THEME } from "../../constants"; -import type { Theme } from "../../element/types"; -import { trackEvent } from "../../analytics"; + import "./DefaultItems.scss"; +import type { Theme } from "../../element/types"; + export const LoadScene = () => { const { t } = useI18n(); const actionManager = useExcalidrawActionManager(); diff --git a/packages/excalidraw/components/main-menu/MainMenu.tsx b/packages/excalidraw/components/main-menu/MainMenu.tsx index 07afd3c1d..54f60a364 100644 --- a/packages/excalidraw/components/main-menu/MainMenu.tsx +++ b/packages/excalidraw/components/main-menu/MainMenu.tsx @@ -1,16 +1,16 @@ import React from "react"; -import { useDevice, useExcalidrawSetAppState } from "../App"; -import DropdownMenu from "../dropdownMenu/DropdownMenu"; -import * as DefaultItems from "./DefaultItems"; - -import { UserList } from "../UserList"; -import { t } from "../../i18n"; -import { HamburgerMenuIcon } from "../icons"; -import { withInternalFallback } from "../hoc/withInternalFallback"; -import { composeEventHandlers } from "../../utils"; import { useTunnels } from "../../context/tunnels"; import { useUIAppState } from "../../context/ui-appState"; +import { t } from "../../i18n"; +import { composeEventHandlers } from "../../utils"; +import { useDevice, useExcalidrawSetAppState } from "../App"; +import { UserList } from "../UserList"; +import DropdownMenu from "../dropdownMenu/DropdownMenu"; +import { withInternalFallback } from "../hoc/withInternalFallback"; +import { HamburgerMenuIcon } from "../icons"; + +import * as DefaultItems from "./DefaultItems"; const MainMenu = Object.assign( withInternalFallback( diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx index 4faa41bf7..bd9b9e55b 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Center.tsx @@ -1,12 +1,13 @@ -import type { JSX } from "react"; import { actionLoadScene, actionShortcuts } from "../../actions"; import { getShortcutFromShortcutName } from "../../actions/shortcuts"; +import { useTunnels } from "../../context/tunnels"; +import { useUIAppState } from "../../context/ui-appState"; import { t, useI18n } from "../../i18n"; import { useDevice, useExcalidrawActionManager } from "../App"; -import { useTunnels } from "../../context/tunnels"; -import { HelpIcon, LoadIcon, usersIcon } from "../icons"; -import { useUIAppState } from "../../context/ui-appState"; import { ExcalidrawLogo } from "../ExcalidrawLogo"; +import { HelpIcon, LoadIcon, usersIcon } from "../icons"; + +import type { JSX } from "react"; const WelcomeScreenMenuItemContent = ({ icon, diff --git a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx index 896f4014e..e47a5a1d3 100644 --- a/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx +++ b/packages/excalidraw/components/welcome-screen/WelcomeScreen.Hints.tsx @@ -1,5 +1,5 @@ -import { t } from "../../i18n"; import { useTunnels } from "../../context/tunnels"; +import { t } from "../../i18n"; import { WelcomeScreenHelpArrow, WelcomeScreenMenuArrow, diff --git a/packages/excalidraw/constants.ts b/packages/excalidraw/constants.ts index 616ced1a7..88cddd5c5 100644 --- a/packages/excalidraw/constants.ts +++ b/packages/excalidraw/constants.ts @@ -1,7 +1,8 @@ -import type { AppProps, AppState } from "./types"; -import type { ExcalidrawElement, FontFamilyValues } from "./element/types"; import { COLOR_PALETTE } from "./colors"; +import type { ExcalidrawElement, FontFamilyValues } from "./element/types"; +import type { AppProps, AppState } from "./types"; + export const isDarwin = /Mac|iPod|iPhone|iPad/.test(navigator.platform); export const isWindows = /^Win/.test(navigator.platform); export const isAndroid = /\b(android)\b/i.test(navigator.userAgent); diff --git a/packages/excalidraw/context/tunnels.ts b/packages/excalidraw/context/tunnels.ts index 73b85ba6a..370a0f2bb 100644 --- a/packages/excalidraw/context/tunnels.ts +++ b/packages/excalidraw/context/tunnels.ts @@ -1,6 +1,6 @@ +import { createIsolation } from "jotai-scope"; import React from "react"; import tunnel from "tunnel-rat"; -import { createIsolation } from "jotai-scope"; export type Tunnel = ReturnType; diff --git a/packages/excalidraw/context/ui-appState.ts b/packages/excalidraw/context/ui-appState.ts index f94ce28c3..174b6e89c 100644 --- a/packages/excalidraw/context/ui-appState.ts +++ b/packages/excalidraw/context/ui-appState.ts @@ -1,4 +1,5 @@ import React from "react"; + import type { UIAppState } from "../types"; export const UIAppStateContext = React.createContext(null!); diff --git a/packages/excalidraw/cursor.ts b/packages/excalidraw/cursor.ts index 759b7a4ae..1aa6e52d2 100644 --- a/packages/excalidraw/cursor.ts +++ b/packages/excalidraw/cursor.ts @@ -1,7 +1,9 @@ -import { CURSOR_TYPE, MIME_TYPES, THEME } from "./constants"; import OpenColor from "open-color"; -import type { AppState, DataURL } from "./types"; + import { isHandToolActive, isEraserActive } from "./appState"; +import { CURSOR_TYPE, MIME_TYPES, THEME } from "./constants"; + +import type { AppState, DataURL } from "./types"; const laserPointerCursorSVG_tag = ``; const laserPointerCursorBackgroundSVG = ``; diff --git a/packages/excalidraw/data/blob.ts b/packages/excalidraw/data/blob.ts index 2293f860c..54505068f 100644 --- a/packages/excalidraw/data/blob.ts +++ b/packages/excalidraw/data/blob.ts @@ -1,19 +1,22 @@ import { nanoid } from "nanoid"; + import { cleanAppStateForExport } from "../appState"; import { IMAGE_MIME_TYPES, MIME_TYPES } from "../constants"; import { clearElementsForExport } from "../element"; -import type { ExcalidrawElement, FileId } from "../element/types"; import { CanvasError, ImageSceneDataError } from "../errors"; import { calculateScrollCenter } from "../scene"; import { decodeSvgBase64Payload } from "../scene/export"; -import type { AppState, DataURL, LibraryItem } from "../types"; -import type { ValueOf } from "../utility-types"; import { bytesToHexString, isPromiseLike } from "../utils"; + import { base64ToString, stringToBase64, toByteString } from "./encode"; -import type { FileSystemHandle } from "./filesystem"; import { nativeFileSystemSupported } from "./filesystem"; import { isValidExcalidrawData, isValidLibrary } from "./json"; import { restore, restoreLibraryItems } from "./restore"; + +import type { FileSystemHandle } from "./filesystem"; +import type { ExcalidrawElement, FileId } from "../element/types"; +import type { AppState, DataURL, LibraryItem } from "../types"; +import type { ValueOf } from "../utility-types"; import type { ImportedLibraryData } from "./types"; const parseFileContents = async (blob: Blob | File): Promise => { diff --git a/packages/excalidraw/data/encode.ts b/packages/excalidraw/data/encode.ts index 15dfdb2c0..31d7a5bc1 100644 --- a/packages/excalidraw/data/encode.ts +++ b/packages/excalidraw/data/encode.ts @@ -1,4 +1,5 @@ import { deflate, inflate } from "pako"; + import { encryptData, decryptData } from "./encryption"; // ----------------------------------------------------------------------------- diff --git a/packages/excalidraw/data/encryption.ts b/packages/excalidraw/data/encryption.ts index 33e689977..a796d05b4 100644 --- a/packages/excalidraw/data/encryption.ts +++ b/packages/excalidraw/data/encryption.ts @@ -1,4 +1,5 @@ import { ENCRYPTION_KEY_BITS } from "../constants"; + import { blobToArrayBuffer } from "./blob"; export const IV_LENGTH_BYTES = 12; diff --git a/packages/excalidraw/data/filesystem.ts b/packages/excalidraw/data/filesystem.ts index 186d58734..0bdab68fd 100644 --- a/packages/excalidraw/data/filesystem.ts +++ b/packages/excalidraw/data/filesystem.ts @@ -1,13 +1,15 @@ -import type { FileSystemHandle } from "browser-fs-access"; import { fileOpen as _fileOpen, fileSave as _fileSave, supported as nativeFileSystemSupported, } from "browser-fs-access"; + import { EVENT, MIME_TYPES } from "../constants"; import { AbortError } from "../errors"; import { debounce } from "../utils"; +import type { FileSystemHandle } from "browser-fs-access"; + type FILE_EXTENSION = Exclude; const INPUT_CHANGE_INTERVAL_MS = 500; diff --git a/packages/excalidraw/data/image.ts b/packages/excalidraw/data/image.ts index 0359a9c32..e54f7bab5 100644 --- a/packages/excalidraw/data/image.ts +++ b/packages/excalidraw/data/image.ts @@ -1,9 +1,11 @@ -import decodePng from "png-chunks-extract"; import tEXt from "png-chunk-text"; import encodePng from "png-chunks-encode"; -import { encode, decode } from "./encode"; +import decodePng from "png-chunks-extract"; + import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; + import { blobToArrayBuffer } from "./blob"; +import { encode, decode } from "./encode"; // ----------------------------------------------------------------------------- // PNG diff --git a/packages/excalidraw/data/index.ts b/packages/excalidraw/data/index.ts index 04cdcaf95..013ac5b75 100644 --- a/packages/excalidraw/data/index.ts +++ b/packages/excalidraw/data/index.ts @@ -11,22 +11,24 @@ import { } from "../constants"; import { getNonDeletedElements } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; +import { getElementsOverlappingFrame } from "../frame"; +import { t } from "../i18n"; +import { getSelectedElements, isSomeElementSelected } from "../scene"; +import { exportToCanvas, exportToSvg } from "../scene/export"; +import { cloneJSON } from "../utils"; + +import { canvasToBlob } from "./blob"; +import { fileSave } from "./filesystem"; +import { serializeAsJSON } from "./json"; + +import type { FileSystemHandle } from "./filesystem"; import type { ExcalidrawElement, ExcalidrawFrameLikeElement, NonDeletedExcalidrawElement, } from "../element/types"; -import { getElementsOverlappingFrame } from "../frame"; -import { t } from "../i18n"; -import { getSelectedElements, isSomeElementSelected } from "../scene"; -import { exportToCanvas, exportToSvg } from "../scene/export"; import type { ExportType } from "../scene/types"; import type { AppState, BinaryFiles } from "../types"; -import { cloneJSON } from "../utils"; -import { canvasToBlob } from "./blob"; -import type { FileSystemHandle } from "./filesystem"; -import { fileSave } from "./filesystem"; -import { serializeAsJSON } from "./json"; export { loadFromBlob } from "./blob"; export { loadFromJSON, saveAsJSON } from "./json"; diff --git a/packages/excalidraw/data/json.ts b/packages/excalidraw/data/json.ts index 1270fd1b4..c1cdd4f92 100644 --- a/packages/excalidraw/data/json.ts +++ b/packages/excalidraw/data/json.ts @@ -1,4 +1,3 @@ -import { fileOpen, fileSave } from "./filesystem"; import { cleanAppStateForExport, clearAppStateForDatabase } from "../appState"; import { DEFAULT_FILENAME, @@ -8,10 +7,12 @@ import { VERSIONS, } from "../constants"; import { clearElementsForDatabase, clearElementsForExport } from "../element"; + +import { isImageFileHandle, loadFromBlob, normalizeFile } from "./blob"; +import { fileOpen, fileSave } from "./filesystem"; + import type { ExcalidrawElement } from "../element/types"; import type { AppState, BinaryFiles, LibraryItems } from "../types"; -import { isImageFileHandle, loadFromBlob, normalizeFile } from "./blob"; - import type { ExportedDataState, ImportedDataState, diff --git a/packages/excalidraw/data/library.ts b/packages/excalidraw/data/library.ts index 1c23edcf0..76424f54a 100644 --- a/packages/excalidraw/data/library.ts +++ b/packages/excalidraw/data/library.ts @@ -1,19 +1,5 @@ -import { loadLibraryFromBlob } from "./blob"; -import type { - LibraryItems, - LibraryItem, - ExcalidrawImperativeAPI, - LibraryItemsSource, - LibraryItems_anyVersion, -} from "../types"; -import { restoreLibraryItems } from "./restore"; -import type App from "../components/App"; -import { atom, editorJotaiStore } from "../editor-jotai"; -import type { ExcalidrawElement } from "../element/types"; -import { getCommonBoundingBox } from "../element/bounds"; -import { AbortError } from "../errors"; -import { t } from "../i18n"; import { useEffect, useRef } from "react"; + import { URL_HASH_KEYS, URL_QUERY_KEYS, @@ -22,7 +8,14 @@ import { DEFAULT_SIDEBAR, LIBRARY_SIDEBAR_TAB, } from "../constants"; +import { atom, editorJotaiStore } from "../editor-jotai"; +import { hashElementsVersion, hashString } from "../element"; +import { getCommonBoundingBox } from "../element/bounds"; +import { Emitter } from "../emitter"; +import { AbortError } from "../errors"; import { libraryItemSvgsCache } from "../hooks/useLibraryItemSvg"; +import { t } from "../i18n"; +import { Queue } from "../queue"; import { arrayToMap, cloneJSON, @@ -30,12 +23,22 @@ import { promiseTry, resolvablePromise, } from "../utils"; -import type { MaybePromise } from "../utility-types"; -import { Emitter } from "../emitter"; -import { Queue } from "../queue"; -import { hashElementsVersion, hashString } from "../element"; + +import { loadLibraryFromBlob } from "./blob"; +import { restoreLibraryItems } from "./restore"; import { toValidURL } from "./url"; +import type App from "../components/App"; +import type { ExcalidrawElement } from "../element/types"; +import type { + LibraryItems, + LibraryItem, + ExcalidrawImperativeAPI, + LibraryItemsSource, + LibraryItems_anyVersion, +} from "../types"; +import type { MaybePromise } from "../utility-types"; + /** * format: hostname or hostname/pathname * diff --git a/packages/excalidraw/data/reconcile.ts b/packages/excalidraw/data/reconcile.ts index fa4cff8d1..ef644c3aa 100644 --- a/packages/excalidraw/data/reconcile.ts +++ b/packages/excalidraw/data/reconcile.ts @@ -1,14 +1,16 @@ import throttle from "lodash.throttle"; + import { ENV } from "../constants"; -import type { OrderedExcalidrawElement } from "../element/types"; import { orderByFractionalIndex, syncInvalidIndices, validateFractionalIndices, } from "../fractionalIndex"; +import { arrayToMap } from "../utils"; + +import type { OrderedExcalidrawElement } from "../element/types"; import type { AppState } from "../types"; import type { MakeBrand } from "../utility-types"; -import { arrayToMap } from "../utils"; export type ReconciledExcalidrawElement = OrderedExcalidrawElement & MakeBrand<"ReconciledElement">; diff --git a/packages/excalidraw/data/resave.ts b/packages/excalidraw/data/resave.ts index 624918425..2c448429a 100644 --- a/packages/excalidraw/data/resave.ts +++ b/packages/excalidraw/data/resave.ts @@ -1,7 +1,9 @@ +import { getFileHandleType, isImageFileHandleType } from "./blob"; + +import { exportCanvas, prepareElementsForExport } from "."; + import type { ExcalidrawElement } from "../element/types"; import type { AppState, BinaryFiles } from "../types"; -import { exportCanvas, prepareElementsForExport } from "."; -import { getFileHandleType, isImageFileHandleType } from "./blob"; export const resaveAsImageWithScene = async ( elements: readonly ExcalidrawElement[], diff --git a/packages/excalidraw/data/restore.ts b/packages/excalidraw/data/restore.ts index c4e45b025..df1a64621 100644 --- a/packages/excalidraw/data/restore.ts +++ b/packages/excalidraw/data/restore.ts @@ -1,3 +1,56 @@ +import { isFiniteNumber, pointFrom } from "@excalidraw/math"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + +import { getDefaultAppState } from "../appState"; +import { + DEFAULT_FONT_FAMILY, + DEFAULT_TEXT_ALIGN, + DEFAULT_VERTICAL_ALIGN, + FONT_FAMILY, + ROUNDNESS, + DEFAULT_SIDEBAR, + DEFAULT_ELEMENT_PROPS, + DEFAULT_GRID_SIZE, + DEFAULT_GRID_STEP, +} from "../constants"; +import { + getNonDeletedElements, + getNormalizedDimensions, + isInvisiblySmallElement, + refreshTextDimensions, +} from "../element"; +import { normalizeFixedPoint } from "../element/binding"; +import { + updateElbowArrowPoints, + validateElbowPoints, +} from "../element/elbowArrow"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { bumpVersion } from "../element/mutateElement"; +import { getContainerElement } from "../element/textElement"; +import { detectLineHeight } from "../element/textMeasurements"; +import { + isArrowElement, + isElbowArrow, + isFixedPointBinding, + isLinearElement, + isTextElement, + isUsingAdaptiveRadius, +} from "../element/typeChecks"; +import { getLineHeight } from "../fonts"; +import { syncInvalidIndices } from "../fractionalIndex"; +import { randomId } from "../random"; +import { + getNormalizedGridSize, + getNormalizedGridStep, + getNormalizedZoom, +} from "../scene"; +import { getUpdatedTimestamp, updateActiveTool } from "../utils"; +import { arrayToMap } from "../utils"; +import { getSizeFromPoints } from "../points"; + +import { normalizeLink } from "./url"; + import type { ExcalidrawArrowElement, ExcalidrawElbowArrowElement, @@ -14,57 +67,8 @@ import type { StrokeRoundness, } from "../element/types"; import type { AppState, BinaryFiles, LibraryItem } from "../types"; -import type { ImportedDataState, LegacyAppState } from "./types"; -import { - getNonDeletedElements, - getNormalizedDimensions, - isInvisiblySmallElement, - refreshTextDimensions, -} from "../element"; -import { - isArrowElement, - isElbowArrow, - isFixedPointBinding, - isLinearElement, - isTextElement, - isUsingAdaptiveRadius, -} from "../element/typeChecks"; -import { randomId } from "../random"; -import { - DEFAULT_FONT_FAMILY, - DEFAULT_TEXT_ALIGN, - DEFAULT_VERTICAL_ALIGN, - FONT_FAMILY, - ROUNDNESS, - DEFAULT_SIDEBAR, - DEFAULT_ELEMENT_PROPS, - DEFAULT_GRID_SIZE, - DEFAULT_GRID_STEP, -} from "../constants"; -import { getDefaultAppState } from "../appState"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { bumpVersion } from "../element/mutateElement"; -import { getUpdatedTimestamp, updateActiveTool } from "../utils"; -import { arrayToMap } from "../utils"; import type { MarkOptional, Mutable } from "../utility-types"; -import { getContainerElement } from "../element/textElement"; -import { normalizeLink } from "./url"; -import { syncInvalidIndices } from "../fractionalIndex"; -import { getSizeFromPoints } from "../points"; -import { getLineHeight } from "../fonts"; -import { normalizeFixedPoint } from "../element/binding"; -import { - getNormalizedGridSize, - getNormalizedGridStep, - getNormalizedZoom, -} from "../scene"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { isFiniteNumber, pointFrom } from "@excalidraw/math"; -import { detectLineHeight } from "../element/textMeasurements"; -import { - updateElbowArrowPoints, - validateElbowPoints, -} from "../element/elbowArrow"; +import type { ImportedDataState, LegacyAppState } from "./types"; type RestoredAppState = Omit< AppState, diff --git a/packages/excalidraw/data/transform.test.ts b/packages/excalidraw/data/transform.test.ts index a36af0c35..94f7b6c82 100644 --- a/packages/excalidraw/data/transform.test.ts +++ b/packages/excalidraw/data/transform.test.ts @@ -1,8 +1,10 @@ -import { vi } from "vitest"; -import type { ExcalidrawElementSkeleton } from "./transform"; -import { convertToExcalidrawElements } from "./transform"; -import type { ExcalidrawArrowElement } from "../element/types"; import { pointFrom } from "@excalidraw/math"; +import { vi } from "vitest"; + +import { convertToExcalidrawElements } from "./transform"; + +import type { ExcalidrawElementSkeleton } from "./transform"; +import type { ExcalidrawArrowElement } from "../element/types"; const opts = { regenerateIds: false }; diff --git a/packages/excalidraw/data/transform.ts b/packages/excalidraw/data/transform.ts index 023740cf1..704b63cb5 100644 --- a/packages/excalidraw/data/transform.ts +++ b/packages/excalidraw/data/transform.ts @@ -1,3 +1,5 @@ +import { pointFrom, type LocalPoint } from "@excalidraw/math"; + import { DEFAULT_FONT_FAMILY, DEFAULT_FONT_SIZE, @@ -11,7 +13,6 @@ import { redrawTextBoundingBox, } from "../element"; import { bindLinearElement } from "../element/binding"; -import type { ElementConstructorOpts } from "../element/newElement"; import { newArrowElement, newFrameElement, @@ -19,6 +20,22 @@ import { newMagicFrameElement, newTextElement, } from "../element/newElement"; +import { measureText, normalizeText } from "../element/textMeasurements"; +import { isArrowElement } from "../element/typeChecks"; +import { getLineHeight } from "../fonts"; +import { syncInvalidIndices } from "../fractionalIndex"; +import { getSizeFromPoints } from "../points"; +import { randomId } from "../random"; +import { + arrayToMap, + assertNever, + cloneJSON, + getFontString, + isDevEnv, + toBrandedType, +} from "../utils"; + +import type { ElementConstructorOpts } from "../element/newElement"; import type { ElementsMap, ExcalidrawArrowElement, @@ -40,21 +57,6 @@ import type { VerticalAlign, } from "../element/types"; import type { MarkOptional } from "../utility-types"; -import { - arrayToMap, - assertNever, - cloneJSON, - getFontString, - isDevEnv, - toBrandedType, -} from "../utils"; -import { getSizeFromPoints } from "../points"; -import { randomId } from "../random"; -import { syncInvalidIndices } from "../fractionalIndex"; -import { getLineHeight } from "../fonts"; -import { isArrowElement } from "../element/typeChecks"; -import { pointFrom, type LocalPoint } from "@excalidraw/math"; -import { measureText, normalizeText } from "../element/textMeasurements"; export type ValidLinearElement = { type: "arrow" | "line"; diff --git a/packages/excalidraw/data/types.ts b/packages/excalidraw/data/types.ts index f5f5535a5..de3436137 100644 --- a/packages/excalidraw/data/types.ts +++ b/packages/excalidraw/data/types.ts @@ -1,3 +1,5 @@ +import type { cleanAppStateForExport } from "../appState"; +import type { VERSIONS } from "../constants"; import type { ExcalidrawElement } from "../element/types"; import type { AppState, @@ -5,8 +7,6 @@ import type { LibraryItems, LibraryItems_anyVersion, } from "../types"; -import type { cleanAppStateForExport } from "../appState"; -import type { VERSIONS } from "../constants"; export interface ExportedDataState { type: string; diff --git a/packages/excalidraw/data/url.ts b/packages/excalidraw/data/url.ts index 2ab553bb8..a758d233e 100644 --- a/packages/excalidraw/data/url.ts +++ b/packages/excalidraw/data/url.ts @@ -1,4 +1,5 @@ import { sanitizeUrl } from "@braintree/sanitize-url"; + import { escapeDoubleQuotes } from "../utils"; export const normalizeLink = (link: string) => { diff --git a/packages/excalidraw/distribute.ts b/packages/excalidraw/distribute.ts index 368b2f24d..767d3802c 100644 --- a/packages/excalidraw/distribute.ts +++ b/packages/excalidraw/distribute.ts @@ -1,6 +1,7 @@ +import { getCommonBoundingBox } from "./element/bounds"; import { newElementWith } from "./element/mutateElement"; import { getMaximumGroups } from "./groups"; -import { getCommonBoundingBox } from "./element/bounds"; + import type { ElementsMap, ExcalidrawElement } from "./element/types"; export interface Distribution { diff --git a/packages/excalidraw/element/ElementCanvasButtons.tsx b/packages/excalidraw/element/ElementCanvasButtons.tsx index 1bcad97b4..e67e8d5bc 100644 --- a/packages/excalidraw/element/ElementCanvasButtons.tsx +++ b/packages/excalidraw/element/ElementCanvasButtons.tsx @@ -1,11 +1,14 @@ -import type { AppState } from "../types"; -import { sceneCoordsToViewportCoords } from "../utils"; -import type { ElementsMap, NonDeletedExcalidrawElement } from "./types"; -import { getElementAbsoluteCoords } from "."; import { useExcalidrawAppState } from "../components/App"; +import { sceneCoordsToViewportCoords } from "../utils"; import "./ElementCanvasButtons.scss"; +import { getElementAbsoluteCoords } from "."; + +import type { AppState } from "../types"; + +import type { ElementsMap, NonDeletedExcalidrawElement } from "./types"; + const CONTAINER_PADDING = 5; const getContainerCoords = ( diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index e716b860f..fa472d211 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -1,63 +1,3 @@ -import type { - ExcalidrawBindableElement, - ExcalidrawElement, - NonDeleted, - ExcalidrawLinearElement, - PointBinding, - NonDeletedExcalidrawElement, - ElementsMap, - NonDeletedSceneElementsMap, - ExcalidrawTextElement, - ExcalidrawArrowElement, - OrderedExcalidrawElement, - ExcalidrawElbowArrowElement, - FixedPoint, - SceneElementsMap, - FixedPointBinding, -} from "./types"; - -import type { Bounds } from "./bounds"; -import { - getCenterForBounds, - getElementBounds, - doBoundsIntersect, -} from "./bounds"; -import type { AppState } from "../types"; -import { isPointOnShape } from "@excalidraw/utils/collision"; -import { - isArrowElement, - isBindableElement, - isBindingElement, - isBoundToContainer, - isElbowArrow, - isFixedPointBinding, - isFrameLikeElement, - isLinearElement, - isRectanguloidElement, - isTextElement, -} from "./typeChecks"; -import type { ElementUpdate } from "./mutateElement"; -import { mutateElement } from "./mutateElement"; -import type Scene from "../scene/Scene"; -import { LinearElementEditor } from "./linearElementEditor"; -import { - arrayToMap, - isBindingFallthroughEnabled, - tupleToCoors, -} from "../utils"; -import { KEYS } from "../keys"; -import { getBoundTextElement, handleBindTextResize } from "./textElement"; -import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; -import { - compareHeading, - HEADING_DOWN, - HEADING_RIGHT, - HEADING_UP, - headingForPointFromElement, - vectorToHeading, - type Heading, -} from "./heading"; -import type { LocalPoint, Radians } from "@excalidraw/math"; import { lineSegment, pointFrom, @@ -76,8 +16,71 @@ import { round, PRECISION, } from "@excalidraw/math"; +import { isPointOnShape } from "@excalidraw/utils/collision"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + +import { KEYS } from "../keys"; +import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; +import { + arrayToMap, + isBindingFallthroughEnabled, + tupleToCoors, +} from "../utils"; + +import { + getCenterForBounds, + getElementBounds, + doBoundsIntersect, +} from "./bounds"; import { intersectElementWithLineSegment } from "./collision"; import { distanceToBindableElement } from "./distance"; +import { + compareHeading, + HEADING_DOWN, + HEADING_RIGHT, + HEADING_UP, + headingForPointFromElement, + vectorToHeading, + type Heading, +} from "./heading"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { getBoundTextElement, handleBindTextResize } from "./textElement"; +import { + isArrowElement, + isBindableElement, + isBindingElement, + isBoundToContainer, + isElbowArrow, + isFixedPointBinding, + isFrameLikeElement, + isLinearElement, + isRectanguloidElement, + isTextElement, +} from "./typeChecks"; + +import type { Bounds } from "./bounds"; +import type { ElementUpdate } from "./mutateElement"; +import type { + ExcalidrawBindableElement, + ExcalidrawElement, + NonDeleted, + ExcalidrawLinearElement, + PointBinding, + NonDeletedExcalidrawElement, + ElementsMap, + NonDeletedSceneElementsMap, + ExcalidrawTextElement, + ExcalidrawArrowElement, + OrderedExcalidrawElement, + ExcalidrawElbowArrowElement, + FixedPoint, + SceneElementsMap, + FixedPointBinding, +} from "./types"; +import type Scene from "../scene/Scene"; +import type { AppState } from "../types"; export type SuggestedBinding = | NonDeleted diff --git a/packages/excalidraw/element/bounds.test.ts b/packages/excalidraw/element/bounds.test.ts index 9d91d0925..936ebf797 100644 --- a/packages/excalidraw/element/bounds.test.ts +++ b/packages/excalidraw/element/bounds.test.ts @@ -1,8 +1,12 @@ -import type { LocalPoint } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; + +import type { LocalPoint } from "@excalidraw/math"; + import { ROUNDNESS } from "../constants"; import { arrayToMap } from "../utils"; + import { getElementAbsoluteCoords, getElementBounds } from "./bounds"; + import type { ExcalidrawElement, ExcalidrawLinearElement } from "./types"; const _ce = ({ diff --git a/packages/excalidraw/element/bounds.ts b/packages/excalidraw/element/bounds.ts index 06f977023..9d8fd22d3 100644 --- a/packages/excalidraw/element/bounds.ts +++ b/packages/excalidraw/element/bounds.ts @@ -1,3 +1,39 @@ +import { + degreesToRadians, + lineSegment, + pointFrom, + pointDistance, + pointFromArray, + pointRotateRads, +} from "@excalidraw/math"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; +import rough from "roughjs/bin/rough"; + +import type { + Degrees, + GlobalPoint, + LineSegment, + LocalPoint, + Radians, +} from "@excalidraw/math"; + +import { rescalePoints } from "../points"; +import { generateRoughOptions } from "../scene/Shape"; +import { ShapeCache } from "../scene/ShapeCache"; +import { arrayToMap, invariant } from "../utils"; + +import { LinearElementEditor } from "./linearElementEditor"; +import { getBoundTextElement, getContainerElement } from "./textElement"; +import { + isArrowElement, + isBoundToContainer, + isFreeDrawElement, + isLinearElement, + isTextElement, +} from "./typeChecks"; + +import type { AppState } from "../types"; +import type { Mutable } from "../utility-types"; import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -7,40 +43,8 @@ import type { ExcalidrawTextElementWithContainer, ElementsMap, } from "./types"; -import rough from "roughjs/bin/rough"; -import type { Point as RoughPoint } from "roughjs/bin/geometry"; import type { Drawable, Op } from "roughjs/bin/core"; -import type { AppState } from "../types"; -import { generateRoughOptions } from "../scene/Shape"; -import { - isArrowElement, - isBoundToContainer, - isFreeDrawElement, - isLinearElement, - isTextElement, -} from "./typeChecks"; -import { rescalePoints } from "../points"; -import { getBoundTextElement, getContainerElement } from "./textElement"; -import { LinearElementEditor } from "./linearElementEditor"; -import { ShapeCache } from "../scene/ShapeCache"; -import { arrayToMap, invariant } from "../utils"; -import type { - Degrees, - GlobalPoint, - LineSegment, - LocalPoint, - Radians, -} from "@excalidraw/math"; -import { - degreesToRadians, - lineSegment, - pointFrom, - pointDistance, - pointFromArray, - pointRotateRads, -} from "@excalidraw/math"; -import type { Mutable } from "../utility-types"; -import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; +import type { Point as RoughPoint } from "roughjs/bin/geometry"; export type RectangleBox = { x: number; diff --git a/packages/excalidraw/element/collision.ts b/packages/excalidraw/element/collision.ts index b0a2ce9a5..a86cbd62f 100644 --- a/packages/excalidraw/element/collision.ts +++ b/packages/excalidraw/element/collision.ts @@ -1,31 +1,3 @@ -import type { - ElementsMap, - ExcalidrawDiamondElement, - ExcalidrawElement, - ExcalidrawEllipseElement, - ExcalidrawRectangleElement, - ExcalidrawRectanguloidElement, -} from "./types"; -import { getElementBounds } from "./bounds"; -import type { FrameNameBounds } from "../types"; -import type { GeometricShape } from "@excalidraw/utils/geometry/shape"; -import { getPolygonShape } from "@excalidraw/utils/geometry/shape"; -import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; -import { isTransparent } from "../utils"; -import { - hasBoundTextElement, - isIframeLikeElement, - isImageElement, - isTextElement, -} from "./typeChecks"; -import { getBoundTextShape, isPathALoop } from "../shapes"; -import type { - GlobalPoint, - LineSegment, - LocalPoint, - Polygon, - Radians, -} from "@excalidraw/math"; import { curveIntersectLineSegment, isPointWithinBounds, @@ -40,11 +12,43 @@ import { ellipse, ellipseLineIntersectionPoints, } from "@excalidraw/math/ellipse"; +import { isPointInShape, isPointOnShape } from "@excalidraw/utils/collision"; +import { getPolygonShape } from "@excalidraw/utils/geometry/shape"; + +import type { + GlobalPoint, + LineSegment, + LocalPoint, + Polygon, + Radians, +} from "@excalidraw/math"; +import type { GeometricShape } from "@excalidraw/utils/geometry/shape"; + +import { getBoundTextShape, isPathALoop } from "../shapes"; +import { isTransparent } from "../utils"; + +import { getElementBounds } from "./bounds"; +import { + hasBoundTextElement, + isIframeLikeElement, + isImageElement, + isTextElement, +} from "./typeChecks"; import { deconstructDiamondElement, deconstructRectanguloidElement, } from "./utils"; +import type { + ElementsMap, + ExcalidrawDiamondElement, + ExcalidrawElement, + ExcalidrawEllipseElement, + ExcalidrawRectangleElement, + ExcalidrawRectanguloidElement, +} from "./types"; +import type { FrameNameBounds } from "../types"; + export const shouldTestInside = (element: ExcalidrawElement) => { if (element.type === "arrow") { return false; diff --git a/packages/excalidraw/element/cropElement.ts b/packages/excalidraw/element/cropElement.ts index b10980209..dd75f9360 100644 --- a/packages/excalidraw/element/cropElement.ts +++ b/packages/excalidraw/element/cropElement.ts @@ -1,4 +1,3 @@ -import { type Point } from "points-on-curve"; import { type Radians, pointFrom, @@ -13,6 +12,13 @@ import { clamp, isCloseTo, } from "@excalidraw/math"; +import { type Point } from "points-on-curve"; + +import { + getElementAbsoluteCoords, + getResizedElementAbsoluteCoords, +} from "./bounds"; + import type { TransformHandleType } from "./transformHandles"; import type { ElementsMap, @@ -21,10 +27,6 @@ import type { ImageCrop, NonDeleted, } from "./types"; -import { - getElementAbsoluteCoords, - getResizedElementAbsoluteCoords, -} from "./bounds"; export const MINIMAL_CROP_SIZE = 10; diff --git a/packages/excalidraw/element/distance.ts b/packages/excalidraw/element/distance.ts index 0010ab953..038233555 100644 --- a/packages/excalidraw/element/distance.ts +++ b/packages/excalidraw/element/distance.ts @@ -1,4 +1,3 @@ -import type { GlobalPoint, Radians } from "@excalidraw/math"; import { curvePointDistance, distanceToLineSegment, @@ -6,16 +5,20 @@ import { pointRotateRads, } from "@excalidraw/math"; import { ellipse, ellipseDistanceFromPoint } from "@excalidraw/math/ellipse"; + +import type { GlobalPoint, Radians } from "@excalidraw/math"; + +import { + deconstructDiamondElement, + deconstructRectanguloidElement, +} from "./utils"; + import type { ExcalidrawBindableElement, ExcalidrawDiamondElement, ExcalidrawEllipseElement, ExcalidrawRectanguloidElement, } from "./types"; -import { - deconstructDiamondElement, - deconstructRectanguloidElement, -} from "./utils"; export const distanceToBindableElement = ( element: ExcalidrawBindableElement, diff --git a/packages/excalidraw/element/dragElements.ts b/packages/excalidraw/element/dragElements.ts index bb8fd237e..4cc408b21 100644 --- a/packages/excalidraw/element/dragElements.ts +++ b/packages/excalidraw/element/dragElements.ts @@ -1,17 +1,13 @@ +import { TEXT_AUTOWRAP_THRESHOLD } from "../constants"; +import { getGridPoint } from "../snapping"; +import { getFontString } from "../utils"; + import { updateBoundElements } from "./binding"; -import type { Bounds } from "./bounds"; import { getCommonBounds } from "./bounds"; import { mutateElement } from "./mutateElement"; import { getPerfectElementSize } from "./sizeHelpers"; -import type { NonDeletedExcalidrawElement } from "./types"; -import type { - AppState, - NormalizedZoomValue, - NullableGridSize, - PointerDownState, -} from "../types"; import { getBoundTextElement } from "./textElement"; -import type Scene from "../scene/Scene"; +import { getMinTextElementWidth } from "./textMeasurements"; import { isArrowElement, isElbowArrow, @@ -19,10 +15,16 @@ import { isImageElement, isTextElement, } from "./typeChecks"; -import { getFontString } from "../utils"; -import { TEXT_AUTOWRAP_THRESHOLD } from "../constants"; -import { getGridPoint } from "../snapping"; -import { getMinTextElementWidth } from "./textMeasurements"; + +import type { Bounds } from "./bounds"; +import type { NonDeletedExcalidrawElement } from "./types"; +import type Scene from "../scene/Scene"; +import type { + AppState, + NormalizedZoomValue, + NullableGridSize, + PointerDownState, +} from "../types"; export const dragSelectedElements = ( pointerDownState: PointerDownState, diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index c00eae989..91e280d30 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -1,4 +1,13 @@ +import { pointFrom } from "@excalidraw/math"; import React from "react"; + +import type { LocalPoint } from "@excalidraw/math"; + +import "../../utils/test-utils"; +import { actionSelectAll } from "../actions"; +import { actionDuplicateSelection } from "../actions/actionDuplicateSelection"; +import { ARROW_TYPE } from "../constants"; +import { Excalidraw, mutateElement } from "../index"; import Scene from "../scene/Scene"; import { API } from "../tests/helpers/api"; import { Pointer, UI } from "../tests/helpers/ui"; @@ -9,19 +18,14 @@ import { queryByTestId, render, } from "../tests/test-utils"; + import { bindLinearElement } from "./binding"; -import { Excalidraw, mutateElement } from "../index"; + import type { ExcalidrawArrowElement, ExcalidrawBindableElement, ExcalidrawElbowArrowElement, } from "./types"; -import { ARROW_TYPE } from "../constants"; -import "../../utils/test-utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; -import { actionDuplicateSelection } from "../actions/actionDuplicateSelection"; -import { actionSelectAll } from "../actions"; const { h } = window; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index ce8c3d5a6..5b8dc3813 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -12,11 +12,12 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + import BinaryHeap from "../binaryheap"; import { getSizeFromPoints } from "../points"; import { aabbForElement, pointInsideBounds } from "../shapes"; import { invariant, isAnyTrue, tupleToCoors } from "../utils"; -import type { AppState } from "../types"; + import { bindPointToSnapToElementOutline, FIXED_BINDING_DISTANCE, @@ -25,8 +26,7 @@ import { snapToMid, getHoveredElementForBinding, } from "./binding"; -import type { Bounds } from "./bounds"; -import type { Heading } from "./heading"; +import { distanceToBindableElement } from "./distance"; import { compareHeading, flipHeading, @@ -46,6 +46,9 @@ import { type NonDeletedSceneElementsMap, type SceneElementsMap, } from "./types"; + +import type { Bounds } from "./bounds"; +import type { Heading } from "./heading"; import type { Arrowhead, ElementsMap, @@ -54,7 +57,7 @@ import type { FixedSegment, NonDeletedExcalidrawElement, } from "./types"; -import { distanceToBindableElement } from "./distance"; +import type { AppState } from "../types"; type GridAddress = [number, number] & { _brand: "gridaddress" }; diff --git a/packages/excalidraw/element/elementLink.ts b/packages/excalidraw/element/elementLink.ts index 991f9caec..79b689c93 100644 --- a/packages/excalidraw/element/elementLink.ts +++ b/packages/excalidraw/element/elementLink.ts @@ -5,6 +5,7 @@ import { ELEMENT_LINK_KEY } from "../constants"; import { normalizeLink } from "../data/url"; import { elementsAreInSameGroup } from "../groups"; + import type { AppProps, AppState } from "../types"; import type { ExcalidrawElement } from "./types"; diff --git a/packages/excalidraw/element/embeddable.ts b/packages/excalidraw/element/embeddable.ts index 8265a0b13..1dc1968a0 100644 --- a/packages/excalidraw/element/embeddable.ts +++ b/packages/excalidraw/element/embeddable.ts @@ -1,18 +1,20 @@ import { register } from "../actions/register"; import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants"; -import type { ExcalidrawProps } from "../types"; -import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils"; import { setCursorForShape } from "../cursor"; +import { CaptureUpdateAction } from "../store"; +import { escapeDoubleQuotes, getFontString, updateActiveTool } from "../utils"; + import { newTextElement } from "./newElement"; import { wrapText } from "./textWrapping"; import { isIframeElement } from "./typeChecks"; + +import type { ExcalidrawProps } from "../types"; +import type { MarkRequired } from "../utility-types"; import type { ExcalidrawElement, ExcalidrawIframeLikeElement, IframeData, } from "./types"; -import type { MarkRequired } from "../utility-types"; -import { CaptureUpdateAction } from "../store"; type IframeDataWithSandbox = MarkRequired; diff --git a/packages/excalidraw/element/flowchart.test.tsx b/packages/excalidraw/element/flowchart.test.tsx index d47c850b7..bc026e7d7 100644 --- a/packages/excalidraw/element/flowchart.test.tsx +++ b/packages/excalidraw/element/flowchart.test.tsx @@ -1,9 +1,9 @@ -import { render, unmountComponent } from "../tests/test-utils"; -import { reseed } from "../random"; -import { UI, Keyboard, Pointer } from "../tests/helpers/ui"; import { Excalidraw } from "../index"; -import { API } from "../tests/helpers/api"; import { KEYS } from "../keys"; +import { reseed } from "../random"; +import { API } from "../tests/helpers/api"; +import { UI, Keyboard, Pointer } from "../tests/helpers/ui"; +import { render, unmountComponent } from "../tests/test-utils"; unmountComponent(); diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index 09f006dd0..9880f27af 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -1,3 +1,12 @@ +import { pointFrom, type LocalPoint } from "@excalidraw/math"; + +import { elementOverlapsWithFrame, elementsAreInFrameBounds } from "../frame"; +import { KEYS } from "../keys"; +import { aabbForElement } from "../shapes"; +import { invariant, toBrandedType } from "../utils"; + +import { bindLinearElement } from "./binding"; +import { updateElbowArrowPoints } from "./elbowArrow"; import { HEADING_DOWN, HEADING_LEFT, @@ -7,9 +16,15 @@ import { headingForPointFromElement, type Heading, } from "./heading"; -import { bindLinearElement } from "./binding"; import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; import { newArrowElement, newElement } from "./newElement"; +import { + isBindableElement, + isElbowArrow, + isFrameElement, + isFlowchartNodeElement, +} from "./typeChecks"; import { type ElementsMap, type ExcalidrawBindableElement, @@ -19,20 +34,8 @@ import { type Ordered, type OrderedExcalidrawElement, } from "./types"; -import { KEYS } from "../keys"; + import type { AppState, PendingExcalidrawElements } from "../types"; -import { mutateElement } from "./mutateElement"; -import { elementOverlapsWithFrame, elementsAreInFrameBounds } from "../frame"; -import { - isBindableElement, - isElbowArrow, - isFrameElement, - isFlowchartNodeElement, -} from "./typeChecks"; -import { invariant, toBrandedType } from "../utils"; -import { pointFrom, type LocalPoint } from "@excalidraw/math"; -import { aabbForElement } from "../shapes"; -import { updateElbowArrowPoints } from "./elbowArrow"; type LinkDirection = "up" | "right" | "down" | "left"; diff --git a/packages/excalidraw/element/heading.ts b/packages/excalidraw/element/heading.ts index 94e86339d..ddebeca53 100644 --- a/packages/excalidraw/element/heading.ts +++ b/packages/excalidraw/element/heading.ts @@ -1,10 +1,3 @@ -import type { - LocalPoint, - GlobalPoint, - Triangle, - Vector, - Radians, -} from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -13,7 +6,17 @@ import { triangleIncludesPoint, vectorFromPoint, } from "@excalidraw/math"; + +import type { + LocalPoint, + GlobalPoint, + Triangle, + Vector, + Radians, +} from "@excalidraw/math"; + import { getCenterForBounds, type Bounds } from "./bounds"; + import type { ExcalidrawBindableElement } from "./types"; export const HEADING_RIGHT = [1, 0] as Heading; diff --git a/packages/excalidraw/element/image.ts b/packages/excalidraw/element/image.ts index 32644b64d..0d5f9fb5a 100644 --- a/packages/excalidraw/element/image.ts +++ b/packages/excalidraw/element/image.ts @@ -3,8 +3,10 @@ // ----------------------------------------------------------------------------- import { MIME_TYPES, SVG_NS } from "../constants"; -import type { AppClassProperties, DataURL, BinaryFiles } from "../types"; + import { isInitializedImageElement } from "./typeChecks"; + +import type { AppClassProperties, DataURL, BinaryFiles } from "../types"; import type { ExcalidrawElement, FileId, diff --git a/packages/excalidraw/element/index.ts b/packages/excalidraw/element/index.ts index a9b747681..abe84e031 100644 --- a/packages/excalidraw/element/index.ts +++ b/packages/excalidraw/element/index.ts @@ -1,10 +1,11 @@ +import { isInvisiblySmallElement } from "./sizeHelpers"; +import { isLinearElementType } from "./typeChecks"; + import type { ExcalidrawElement, NonDeletedExcalidrawElement, NonDeleted, } from "./types"; -import { isInvisiblySmallElement } from "./sizeHelpers"; -import { isLinearElementType } from "./typeChecks"; export { newElement, diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index b616268a6..f9b23f048 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -1,3 +1,48 @@ +import { + pointCenter, + pointFrom, + pointRotateRads, + pointsEqual, + type GlobalPoint, + type LocalPoint, + pointDistance, + vectorFromPoint, +} from "@excalidraw/math"; +import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; + +import type { Radians } from "@excalidraw/math"; + +import { DRAGGING_THRESHOLD } from "../constants"; +import { KEYS, shouldRotateWithDiscreteAngle } from "../keys"; +import { ShapeCache } from "../scene/ShapeCache"; +import { + getBezierCurveLength, + getBezierXY, + getControlPointsForBezierCurve, + isPathALoop, + mapIntervalToBezierT, +} from "../shapes"; +import { getGridPoint } from "../snapping"; +import { invariant, tupleToCoors } from "../utils"; + +import { + bindOrUnbindLinearElement, + getHoveredElementForBinding, + isBindingEnabled, +} from "./binding"; +import { getElementPointsCoords, getMinMaxXYFromCurvePathOps } from "./bounds"; +import { headingIsHorizontal, vectorToHeading } from "./heading"; +import { mutateElement } from "./mutateElement"; +import { getBoundTextElement, handleBindTextResize } from "./textElement"; +import { + isBindingElement, + isElbowArrow, + isFixedPointBinding, +} from "./typeChecks"; + +import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; + +import type { Bounds } from "./bounds"; import type { NonDeleted, ExcalidrawLinearElement, @@ -12,9 +57,8 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import { getElementAbsoluteCoords, getLockedLinearCursorAlignSize } from "."; -import type { Bounds } from "./bounds"; -import { getElementPointsCoords, getMinMaxXYFromCurvePathOps } from "./bounds"; +import type Scene from "../scene/Scene"; +import type { Store } from "../store"; import type { AppState, PointerCoords, @@ -23,47 +67,7 @@ import type { NullableGridSize, Zoom, } from "../types"; -import { mutateElement } from "./mutateElement"; - -import { - bindOrUnbindLinearElement, - getHoveredElementForBinding, - isBindingEnabled, -} from "./binding"; -import { invariant, tupleToCoors } from "../utils"; -import { - isBindingElement, - isElbowArrow, - isFixedPointBinding, -} from "./typeChecks"; -import { KEYS, shouldRotateWithDiscreteAngle } from "../keys"; -import { getBoundTextElement, handleBindTextResize } from "./textElement"; -import { DRAGGING_THRESHOLD } from "../constants"; import type { Mutable } from "../utility-types"; -import { ShapeCache } from "../scene/ShapeCache"; -import type { Store } from "../store"; -import type Scene from "../scene/Scene"; -import type { Radians } from "@excalidraw/math"; -import { - pointCenter, - pointFrom, - pointRotateRads, - pointsEqual, - type GlobalPoint, - type LocalPoint, - pointDistance, - vectorFromPoint, -} from "@excalidraw/math"; -import { - getBezierCurveLength, - getBezierXY, - getControlPointsForBezierCurve, - isPathALoop, - mapIntervalToBezierT, -} from "../shapes"; -import { getGridPoint } from "../snapping"; -import { headingIsHorizontal, vectorToHeading } from "./heading"; -import { getCurvePathOps } from "@excalidraw/utils/geometry/shape"; const editorMidPointsCache: { version: number | null; diff --git a/packages/excalidraw/element/mutateElement.ts b/packages/excalidraw/element/mutateElement.ts index cfff5c826..fc96ec312 100644 --- a/packages/excalidraw/element/mutateElement.ts +++ b/packages/excalidraw/element/mutateElement.ts @@ -1,13 +1,16 @@ -import type { ExcalidrawElement, NonDeletedSceneElementsMap } from "./types"; -import Scene from "../scene/Scene"; +import type { Radians } from "@excalidraw/math"; + import { getSizeFromPoints } from "../points"; import { randomInteger } from "../random"; -import { getUpdatedTimestamp, toBrandedType } from "../utils"; -import type { Mutable } from "../utility-types"; +import Scene from "../scene/Scene"; import { ShapeCache } from "../scene/ShapeCache"; -import { isElbowArrow } from "./typeChecks"; +import { getUpdatedTimestamp, toBrandedType } from "../utils"; + import { updateElbowArrowPoints } from "./elbowArrow"; -import type { Radians } from "@excalidraw/math"; +import { isElbowArrow } from "./typeChecks"; + +import type { ExcalidrawElement, NonDeletedSceneElementsMap } from "./types"; +import type { Mutable } from "../utility-types"; export type ElementUpdate = Omit< Partial, diff --git a/packages/excalidraw/element/newElement.test.ts b/packages/excalidraw/element/newElement.test.ts index 9c9006b6c..418ede1be 100644 --- a/packages/excalidraw/element/newElement.test.ts +++ b/packages/excalidraw/element/newElement.test.ts @@ -1,12 +1,16 @@ -import { duplicateElement, duplicateElements } from "./newElement"; -import { mutateElement } from "./mutateElement"; -import { API } from "../tests/helpers/api"; -import { FONT_FAMILY, ROUNDNESS } from "../constants"; -import { isPrimitive } from "../utils"; -import type { ExcalidrawLinearElement } from "./types"; -import type { LocalPoint } from "@excalidraw/math"; import { pointFrom } from "@excalidraw/math"; +import type { LocalPoint } from "@excalidraw/math"; + +import { FONT_FAMILY, ROUNDNESS } from "../constants"; +import { API } from "../tests/helpers/api"; +import { isPrimitive } from "../utils"; + +import { mutateElement } from "./mutateElement"; +import { duplicateElement, duplicateElements } from "./newElement"; + +import type { ExcalidrawLinearElement } from "./types"; + const assertCloneObjects = (source: any, clone: any) => { for (const key in clone) { if (clone.hasOwnProperty(key) && !isPrimitive(clone[key])) { diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 7d1f14910..d11c4c20f 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -1,3 +1,32 @@ +import type { Radians } from "@excalidraw/math"; + +import { + DEFAULT_ELEMENT_PROPS, + DEFAULT_FONT_FAMILY, + DEFAULT_FONT_SIZE, + DEFAULT_TEXT_ALIGN, + DEFAULT_VERTICAL_ALIGN, + ORIG_ID, + VERTICAL_ALIGN, +} from "../constants"; +import { getLineHeight } from "../fonts"; +import { getNewGroupIdsForDuplication } from "../groups"; +import { randomInteger, randomId } from "../random"; +import { + arrayToMap, + getFontString, + getUpdatedTimestamp, + isTestEnv, +} from "../utils"; + +import { getResizedElementAbsoluteCoords } from "./bounds"; +import { bumpVersion, newElementWith } from "./mutateElement"; +import { getBoundTextMaxWidth } from "./textElement"; +import { normalizeText, measureText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; + +import { getElementAbsoluteCoords } from "."; + import type { ExcalidrawElement, ExcalidrawImageElement, @@ -21,33 +50,8 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import { - arrayToMap, - getFontString, - getUpdatedTimestamp, - isTestEnv, -} from "../utils"; -import { randomInteger, randomId } from "../random"; -import { bumpVersion, newElementWith } from "./mutateElement"; -import { getNewGroupIdsForDuplication } from "../groups"; import type { AppState } from "../types"; -import { getElementAbsoluteCoords } from "."; -import { getResizedElementAbsoluteCoords } from "./bounds"; -import { getBoundTextMaxWidth } from "./textElement"; -import { wrapText } from "./textWrapping"; -import { - DEFAULT_ELEMENT_PROPS, - DEFAULT_FONT_FAMILY, - DEFAULT_FONT_SIZE, - DEFAULT_TEXT_ALIGN, - DEFAULT_VERTICAL_ALIGN, - ORIG_ID, - VERTICAL_ALIGN, -} from "../constants"; import type { MarkOptional, Merge, Mutable } from "../utility-types"; -import { getLineHeight } from "../fonts"; -import type { Radians } from "@excalidraw/math"; -import { normalizeText, measureText } from "./textMeasurements"; export type ElementConstructorOpts = MarkOptional< Omit, diff --git a/packages/excalidraw/element/resizeElements.ts b/packages/excalidraw/element/resizeElements.ts index b86ba0279..cd51b8bd5 100644 --- a/packages/excalidraw/element/resizeElements.ts +++ b/packages/excalidraw/element/resizeElements.ts @@ -1,5 +1,60 @@ +import { + pointCenter, + normalizeRadians, + pointFrom, + pointFromPair, + pointRotateRads, + type Radians, + type LocalPoint, +} from "@excalidraw/math"; + +import type { GlobalPoint } from "@excalidraw/math"; + import { MIN_FONT_SIZE, SHIFT_LOCKING_ANGLE } from "../constants"; +import { isInGroup } from "../groups"; import { rescalePoints } from "../points"; +import { getFontString } from "../utils"; + +import { getArrowLocalFixedPoints, updateBoundElements } from "./binding"; +import { + getElementAbsoluteCoords, + getCommonBounds, + getResizedElementAbsoluteCoords, + getCommonBoundingBox, + getElementBounds, +} from "./bounds"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { + getBoundTextElement, + getBoundTextElementId, + getContainerElement, + handleBindTextResize, + getBoundTextMaxWidth, +} from "./textElement"; +import { + getMinTextElementWidth, + measureText, + getApproxMinLineWidth, + getApproxMinLineHeight, +} from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { + isArrowElement, + isBoundToContainer, + isElbowArrow, + isFrameLikeElement, + isFreeDrawElement, + isImageElement, + isLinearElement, + isTextElement, +} from "./typeChecks"; + +import type { BoundingBox } from "./bounds"; +import type { + MaybeTransformHandleType, + TransformHandleDirection, +} from "./transformHandles"; import type { ExcalidrawLinearElement, ExcalidrawTextElement, @@ -12,60 +67,9 @@ import type { SceneElementsMap, ExcalidrawElbowArrowElement, } from "./types"; -import type { Mutable } from "../utility-types"; -import { - getElementAbsoluteCoords, - getCommonBounds, - getResizedElementAbsoluteCoords, - getCommonBoundingBox, - getElementBounds, -} from "./bounds"; -import type { BoundingBox } from "./bounds"; -import { - isArrowElement, - isBoundToContainer, - isElbowArrow, - isFrameLikeElement, - isFreeDrawElement, - isImageElement, - isLinearElement, - isTextElement, -} from "./typeChecks"; -import { mutateElement } from "./mutateElement"; -import { getFontString } from "../utils"; -import { getArrowLocalFixedPoints, updateBoundElements } from "./binding"; -import type { - MaybeTransformHandleType, - TransformHandleDirection, -} from "./transformHandles"; -import type { PointerDownState } from "../types"; import type Scene from "../scene/Scene"; -import { - getBoundTextElement, - getBoundTextElementId, - getContainerElement, - handleBindTextResize, - getBoundTextMaxWidth, -} from "./textElement"; -import { wrapText } from "./textWrapping"; -import { LinearElementEditor } from "./linearElementEditor"; -import { isInGroup } from "../groups"; -import type { GlobalPoint } from "@excalidraw/math"; -import { - pointCenter, - normalizeRadians, - pointFrom, - pointFromPair, - pointRotateRads, - type Radians, - type LocalPoint, -} from "@excalidraw/math"; -import { - getMinTextElementWidth, - measureText, - getApproxMinLineWidth, - getApproxMinLineHeight, -} from "./textMeasurements"; +import type { PointerDownState } from "../types"; +import type { Mutable } from "../utility-types"; // Returns true when transform (resizing/rotation) happened export const transformElements = ( diff --git a/packages/excalidraw/element/resizeTest.ts b/packages/excalidraw/element/resizeTest.ts index 375ff980b..1eb36d0b2 100644 --- a/packages/excalidraw/element/resizeTest.ts +++ b/packages/excalidraw/element/resizeTest.ts @@ -1,27 +1,3 @@ -import type { - ExcalidrawElement, - PointerType, - NonDeletedExcalidrawElement, - ElementsMap, -} from "./types"; - -import type { - TransformHandleType, - TransformHandle, - MaybeTransformHandleType, -} from "./transformHandles"; -import { - getTransformHandlesFromCoords, - getTransformHandles, - getOmitSidesForDevice, - canResizeFromSides, -} from "./transformHandles"; -import type { AppState, Device, Zoom } from "../types"; -import type { Bounds } from "./bounds"; -import { getElementAbsoluteCoords } from "./bounds"; -import { SIDE_RESIZING_THRESHOLD } from "../constants"; -import { isImageElement, isLinearElement } from "./typeChecks"; -import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; import { pointFrom, pointOnLineSegment, @@ -29,6 +5,33 @@ import { type Radians, } from "@excalidraw/math"; +import type { GlobalPoint, LineSegment, LocalPoint } from "@excalidraw/math"; + +import { SIDE_RESIZING_THRESHOLD } from "../constants"; + +import { getElementAbsoluteCoords } from "./bounds"; +import { + getTransformHandlesFromCoords, + getTransformHandles, + getOmitSidesForDevice, + canResizeFromSides, +} from "./transformHandles"; +import { isImageElement, isLinearElement } from "./typeChecks"; + +import type { AppState, Device, Zoom } from "../types"; +import type { Bounds } from "./bounds"; +import type { + TransformHandleType, + TransformHandle, + MaybeTransformHandleType, +} from "./transformHandles"; +import type { + ExcalidrawElement, + PointerType, + NonDeletedExcalidrawElement, + ElementsMap, +} from "./types"; + const isInsideTransformHandle = ( transformHandle: TransformHandle, x: number, diff --git a/packages/excalidraw/element/showSelectedShapeActions.ts b/packages/excalidraw/element/showSelectedShapeActions.ts index bbf313d01..44c2e75c3 100644 --- a/packages/excalidraw/element/showSelectedShapeActions.ts +++ b/packages/excalidraw/element/showSelectedShapeActions.ts @@ -1,6 +1,7 @@ -import type { NonDeletedExcalidrawElement } from "./types"; import { getSelectedElements } from "../scene"; + import type { UIAppState } from "../types"; +import type { NonDeletedExcalidrawElement } from "./types"; export const showSelectedShapeActions = ( appState: UIAppState, diff --git a/packages/excalidraw/element/sizeHelpers.test.ts b/packages/excalidraw/element/sizeHelpers.test.ts index 8e63dd9da..c882e1f3c 100644 --- a/packages/excalidraw/element/sizeHelpers.test.ts +++ b/packages/excalidraw/element/sizeHelpers.test.ts @@ -1,7 +1,9 @@ import { vi } from "vitest"; -import { getPerfectElementSize } from "./sizeHelpers"; + import * as constants from "../constants"; +import { getPerfectElementSize } from "./sizeHelpers"; + const EPSILON_DIGITS = 3; // Needed so that we can mock the value of constants which is done in // below tests. In Jest this wasn't needed as global override was possible diff --git a/packages/excalidraw/element/sizeHelpers.ts b/packages/excalidraw/element/sizeHelpers.ts index f633789a9..33b13e188 100644 --- a/packages/excalidraw/element/sizeHelpers.ts +++ b/packages/excalidraw/element/sizeHelpers.ts @@ -1,10 +1,12 @@ -import type { ElementsMap, ExcalidrawElement } from "./types"; +import { SHIFT_LOCKING_ANGLE } from "../constants"; +import { viewportCoordsToSceneCoords } from "../utils"; + +import { getCommonBounds, getElementBounds } from "./bounds"; import { mutateElement } from "./mutateElement"; import { isFreeDrawElement, isLinearElement } from "./typeChecks"; -import { SHIFT_LOCKING_ANGLE } from "../constants"; + +import type { ElementsMap, ExcalidrawElement } from "./types"; import type { AppState, Offsets, Zoom } from "../types"; -import { getCommonBounds, getElementBounds } from "./bounds"; -import { viewportCoordsToSceneCoords } from "../utils"; // TODO: remove invisible elements consistently actions, so that invisible elements are not recorded by the store, exported, broadcasted or persisted // - perhaps could be as part of a standalone 'cleanup' action, in addition to 'finalize' diff --git a/packages/excalidraw/element/sortElements.test.ts b/packages/excalidraw/element/sortElements.test.ts index a7b78e8ea..5f7c4b2e6 100644 --- a/packages/excalidraw/element/sortElements.test.ts +++ b/packages/excalidraw/element/sortElements.test.ts @@ -1,6 +1,8 @@ import { API } from "../tests/helpers/api"; + import { mutateElement } from "./mutateElement"; import { normalizeElementOrder } from "./sortElements"; + import type { ExcalidrawElement } from "./types"; const assertOrder = ( diff --git a/packages/excalidraw/element/sortElements.ts b/packages/excalidraw/element/sortElements.ts index 3078a6827..d395adf2f 100644 --- a/packages/excalidraw/element/sortElements.ts +++ b/packages/excalidraw/element/sortElements.ts @@ -1,4 +1,5 @@ import { arrayToMapWithIndex } from "../utils"; + import type { ExcalidrawElement } from "./types"; const normalizeGroupElementOrder = (elements: readonly ExcalidrawElement[]) => { diff --git a/packages/excalidraw/element/textElement.test.ts b/packages/excalidraw/element/textElement.test.ts index 2c23c2b06..41531a738 100644 --- a/packages/excalidraw/element/textElement.test.ts +++ b/packages/excalidraw/element/textElement.test.ts @@ -1,6 +1,7 @@ import { FONT_FAMILY } from "../constants"; import { getLineHeight } from "../fonts"; import { API } from "../tests/helpers/api"; + import { computeContainerDimensionForBoundText, getContainerCoords, @@ -8,6 +9,7 @@ import { getBoundTextMaxHeight, } from "./textElement"; import { detectLineHeight, getLineHeightInPx } from "./textMeasurements"; + import type { ExcalidrawTextElementWithContainer } from "./types"; describe("Test measureText", () => { diff --git a/packages/excalidraw/element/textElement.ts b/packages/excalidraw/element/textElement.ts index de948d9ce..9893ba5d6 100644 --- a/packages/excalidraw/element/textElement.ts +++ b/packages/excalidraw/element/textElement.ts @@ -1,4 +1,26 @@ +import { + ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, + ARROW_LABEL_WIDTH_FRACTION, + BOUND_TEXT_PADDING, + DEFAULT_FONT_SIZE, + TEXT_ALIGN, + VERTICAL_ALIGN, +} from "../constants"; import { getFontString, arrayToMap } from "../utils"; + +import { + resetOriginalContainerCache, + updateOriginalContainerCache, +} from "./containerCache"; +import { LinearElementEditor } from "./linearElementEditor"; +import { mutateElement } from "./mutateElement"; +import { measureText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { isBoundToContainer, isArrowElement } from "./typeChecks"; + +import { isTextElement } from "."; + +import type { MaybeTransformHandleType } from "./transformHandles"; import type { ElementsMap, ExcalidrawElement, @@ -8,27 +30,8 @@ import type { ExcalidrawTextElementWithContainer, NonDeletedExcalidrawElement, } from "./types"; -import { mutateElement } from "./mutateElement"; -import { - ARROW_LABEL_FONT_SIZE_TO_MIN_WIDTH_RATIO, - ARROW_LABEL_WIDTH_FRACTION, - BOUND_TEXT_PADDING, - DEFAULT_FONT_SIZE, - TEXT_ALIGN, - VERTICAL_ALIGN, -} from "../constants"; -import type { MaybeTransformHandleType } from "./transformHandles"; -import { isTextElement } from "."; -import { wrapText } from "./textWrapping"; -import { isBoundToContainer, isArrowElement } from "./typeChecks"; -import { LinearElementEditor } from "./linearElementEditor"; import type { AppState } from "../types"; -import { - resetOriginalContainerCache, - updateOriginalContainerCache, -} from "./containerCache"; import type { ExtractSetType } from "../utility-types"; -import { measureText } from "./textMeasurements"; export const redrawTextBoundingBox = ( textElement: ExcalidrawTextElement, diff --git a/packages/excalidraw/element/textMeasurements.ts b/packages/excalidraw/element/textMeasurements.ts index f2a132a3a..840896cfc 100644 --- a/packages/excalidraw/element/textMeasurements.ts +++ b/packages/excalidraw/element/textMeasurements.ts @@ -4,6 +4,7 @@ import { DEFAULT_FONT_FAMILY, } from "../constants"; import { getFontString, isTestEnv, normalizeEOL } from "../utils"; + import type { FontString, ExcalidrawTextElement } from "./types"; export const measureText = ( diff --git a/packages/excalidraw/element/textWrapping.test.ts b/packages/excalidraw/element/textWrapping.test.ts index 6c7bcb819..357736a2e 100644 --- a/packages/excalidraw/element/textWrapping.test.ts +++ b/packages/excalidraw/element/textWrapping.test.ts @@ -1,4 +1,5 @@ import { wrapText, parseTokens } from "./textWrapping"; + import type { FontString } from "./types"; describe("Test wrapText", () => { diff --git a/packages/excalidraw/element/textWrapping.ts b/packages/excalidraw/element/textWrapping.ts index 1913f6ed3..5df7051c0 100644 --- a/packages/excalidraw/element/textWrapping.ts +++ b/packages/excalidraw/element/textWrapping.ts @@ -1,5 +1,7 @@ import { ENV } from "../constants"; + import { charWidth, getLineWidth } from "./textMeasurements"; + import type { FontString } from "./types"; let cachedCjkRegex: RegExp | undefined; diff --git a/packages/excalidraw/element/textWysiwyg.test.tsx b/packages/excalidraw/element/textWysiwyg.test.tsx index 0842e30fd..11c700e33 100644 --- a/packages/excalidraw/element/textWysiwyg.test.tsx +++ b/packages/excalidraw/element/textWysiwyg.test.tsx @@ -1,29 +1,31 @@ +import { pointFrom } from "@excalidraw/math"; +import { queryByText } from "@testing-library/react"; import React from "react"; + +import { FONT_FAMILY, TEXT_ALIGN, VERTICAL_ALIGN } from "../constants"; import { Excalidraw } from "../index"; +import { CODES, KEYS } from "../keys"; +import { API } from "../tests/helpers/api"; +import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; +import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; import { GlobalTestState, render, screen, unmountComponent, } from "../tests/test-utils"; -import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; -import { CODES, KEYS } from "../keys"; import { fireEvent, mockBoundingClientRect, restoreOriginalGetBoundingClientRect, } from "../tests/test-utils"; -import { queryByText } from "@testing-library/react"; -import { FONT_FAMILY, TEXT_ALIGN, VERTICAL_ALIGN } from "../constants"; +import { getOriginalContainerHeightFromCache } from "./containerCache"; + import type { ExcalidrawTextElement, ExcalidrawTextElementWithContainer, } from "./types"; -import { API } from "../tests/helpers/api"; -import { getOriginalContainerHeightFromCache } from "./containerCache"; -import { getTextEditor, updateTextEditor } from "../tests/queries/dom"; -import { pointFrom } from "@excalidraw/math"; unmountComponent(); diff --git a/packages/excalidraw/element/textWysiwyg.tsx b/packages/excalidraw/element/textWysiwyg.tsx index a7570862d..1d0c19de3 100644 --- a/packages/excalidraw/element/textWysiwyg.tsx +++ b/packages/excalidraw/element/textWysiwyg.tsx @@ -1,24 +1,28 @@ +import { + actionResetZoom, + actionZoomIn, + actionZoomOut, +} from "../actions/actionCanvas"; +import { + actionDecreaseFontSize, + actionIncreaseFontSize, +} from "../actions/actionProperties"; +import { parseClipboard } from "../clipboard"; +import { CLASSES, POINTER_BUTTON } from "../constants"; import { CODES, KEYS } from "../keys"; +import Scene from "../scene/Scene"; import { isWritableElement, getFontString, getFontFamilyString, isTestEnv, } from "../utils"; -import Scene from "../scene/Scene"; + import { - isArrowElement, - isBoundToContainer, - isTextElement, -} from "./typeChecks"; -import { CLASSES, POINTER_BUTTON } from "../constants"; -import type { - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElementWithContainer, - ExcalidrawTextElement, -} from "./types"; -import type { AppState } from "../types"; + originalContainerCache, + updateOriginalContainerCache, +} from "./containerCache"; +import { LinearElementEditor } from "./linearElementEditor"; import { bumpVersion, mutateElement } from "./mutateElement"; import { getBoundTextElementId, @@ -31,25 +35,23 @@ import { computeBoundTextPosition, getBoundTextElement, } from "./textElement"; -import { wrapText } from "./textWrapping"; -import { - actionDecreaseFontSize, - actionIncreaseFontSize, -} from "../actions/actionProperties"; -import { - actionResetZoom, - actionZoomIn, - actionZoomOut, -} from "../actions/actionCanvas"; -import type App from "../components/App"; -import { LinearElementEditor } from "./linearElementEditor"; -import { parseClipboard } from "../clipboard"; -import { - originalContainerCache, - updateOriginalContainerCache, -} from "./containerCache"; import { getTextWidth } from "./textMeasurements"; import { normalizeText } from "./textMeasurements"; +import { wrapText } from "./textWrapping"; +import { + isArrowElement, + isBoundToContainer, + isTextElement, +} from "./typeChecks"; + +import type { + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElementWithContainer, + ExcalidrawTextElement, +} from "./types"; +import type App from "../components/App"; +import type { AppState } from "../types"; const getTransform = ( width: number, diff --git a/packages/excalidraw/element/transformHandles.ts b/packages/excalidraw/element/transformHandles.ts index d34eb3279..ab5691df8 100644 --- a/packages/excalidraw/element/transformHandles.ts +++ b/packages/excalidraw/element/transformHandles.ts @@ -1,26 +1,29 @@ -import type { - ElementsMap, - ExcalidrawElement, - NonDeletedExcalidrawElement, - PointerType, -} from "./types"; +import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Radians } from "@excalidraw/math"; + +import { + DEFAULT_TRANSFORM_HANDLE_SPACING, + isAndroid, + isIOS, +} from "../constants"; -import type { Bounds } from "./bounds"; import { getElementAbsoluteCoords } from "./bounds"; -import type { Device, InteractiveCanvasAppState, Zoom } from "../types"; import { isElbowArrow, isFrameLikeElement, isImageElement, isLinearElement, } from "./typeChecks"; -import { - DEFAULT_TRANSFORM_HANDLE_SPACING, - isAndroid, - isIOS, -} from "../constants"; -import type { Radians } from "@excalidraw/math"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { Device, InteractiveCanvasAppState, Zoom } from "../types"; +import type { Bounds } from "./bounds"; +import type { + ElementsMap, + ExcalidrawElement, + NonDeletedExcalidrawElement, + PointerType, +} from "./types"; export type TransformHandleDirection = | "n" diff --git a/packages/excalidraw/element/typeChecks.test.ts b/packages/excalidraw/element/typeChecks.test.ts index 60eb9e273..44e4dd755 100644 --- a/packages/excalidraw/element/typeChecks.test.ts +++ b/packages/excalidraw/element/typeChecks.test.ts @@ -1,4 +1,5 @@ import { API } from "../tests/helpers/api"; + import { hasBoundTextElement } from "./typeChecks"; describe("Test TypeChecks", () => { diff --git a/packages/excalidraw/element/typeChecks.ts b/packages/excalidraw/element/typeChecks.ts index 6bb4269f8..77ac38f9d 100644 --- a/packages/excalidraw/element/typeChecks.ts +++ b/packages/excalidraw/element/typeChecks.ts @@ -1,7 +1,8 @@ import { ROUNDNESS } from "../constants"; +import { assertNever } from "../utils"; + import type { ElementOrToolType } from "../types"; import type { MarkNonNullable } from "../utility-types"; -import { assertNever } from "../utils"; import type { Bounds } from "./bounds"; import type { ExcalidrawElement, diff --git a/packages/excalidraw/element/types.ts b/packages/excalidraw/element/types.ts index 596586743..49ad800af 100644 --- a/packages/excalidraw/element/types.ts +++ b/packages/excalidraw/element/types.ts @@ -1,4 +1,5 @@ import type { LocalPoint, Radians } from "@excalidraw/math"; + import type { FONT_FAMILY, ROUNDNESS, diff --git a/packages/excalidraw/element/utils.ts b/packages/excalidraw/element/utils.ts index d85cd78c6..8992850dc 100644 --- a/packages/excalidraw/element/utils.ts +++ b/packages/excalidraw/element/utils.ts @@ -1,5 +1,3 @@ -import { getDiamondPoints } from "."; -import type { Curve, LineSegment } from "@excalidraw/math"; import { curve, lineSegment, @@ -11,7 +9,13 @@ import { vectorScale, type GlobalPoint, } from "@excalidraw/math"; + +import type { Curve, LineSegment } from "@excalidraw/math"; + import { getCornerRadius } from "../shapes"; + +import { getDiamondPoints } from "."; + import type { ExcalidrawDiamondElement, ExcalidrawRectanguloidElement, diff --git a/packages/excalidraw/fonts/Cascadia/index.ts b/packages/excalidraw/fonts/Cascadia/index.ts index ecd111644..aad91ff0c 100644 --- a/packages/excalidraw/fonts/Cascadia/index.ts +++ b/packages/excalidraw/fonts/Cascadia/index.ts @@ -1,7 +1,7 @@ -import CascadiaCodeRegular from "./CascadiaCode-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import CascadiaCodeRegular from "./CascadiaCode-Regular.woff2"; + export const CascadiaFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: CascadiaCodeRegular, diff --git a/packages/excalidraw/fonts/ComicShanns/index.ts b/packages/excalidraw/fonts/ComicShanns/index.ts index bf78650b4..20d23c28e 100644 --- a/packages/excalidraw/fonts/ComicShanns/index.ts +++ b/packages/excalidraw/fonts/ComicShanns/index.ts @@ -1,13 +1,13 @@ // The following file content was generated with https://chinese-font.netlify.app/online-split, // but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API. -import _0 from "./ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2"; -import _1 from "./ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2"; -import _2 from "./ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2"; -import _3 from "./ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import _0 from "./ComicShanns-Regular-279a7b317d12eb88de06167bd672b4b4.woff2"; +import _3 from "./ComicShanns-Regular-6e066e8de2ac57ea9283adb9c24d7f0c.woff2"; +import _2 from "./ComicShanns-Regular-dc6a8806fa96795d7b3be5026f989a17.woff2"; +import _1 from "./ComicShanns-Regular-fcb0fc02dcbee4c9846b3e2508668039.woff2"; + /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Thu, 17 Oct 2024 09:57:51 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fonts/Emoji/index.ts b/packages/excalidraw/fonts/Emoji/index.ts index 491c7b8c9..323d075cb 100644 --- a/packages/excalidraw/fonts/Emoji/index.ts +++ b/packages/excalidraw/fonts/Emoji/index.ts @@ -1,5 +1,4 @@ import { LOCAL_FONT_PROTOCOL } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; export const EmojiFontFaces: ExcalidrawFontFaceDescriptor[] = [ diff --git a/packages/excalidraw/fonts/ExcalidrawFontFace.ts b/packages/excalidraw/fonts/ExcalidrawFontFace.ts index 9d8b9f78a..615fef20f 100644 --- a/packages/excalidraw/fonts/ExcalidrawFontFace.ts +++ b/packages/excalidraw/fonts/ExcalidrawFontFace.ts @@ -1,6 +1,7 @@ -import { promiseTry } from "../utils"; -import { LOCAL_FONT_PROTOCOL } from "./FontMetadata"; import { subsetWoff2GlyphsByCodepoints } from "../subset/subset-main"; +import { promiseTry } from "../utils"; + +import { LOCAL_FONT_PROTOCOL } from "./FontMetadata"; type DataURL = string; diff --git a/packages/excalidraw/fonts/Excalifont/index.ts b/packages/excalidraw/fonts/Excalifont/index.ts index 7e11af6c6..bcd384be5 100644 --- a/packages/excalidraw/fonts/Excalifont/index.ts +++ b/packages/excalidraw/fonts/Excalifont/index.ts @@ -1,13 +1,13 @@ -import _0 from "./Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2"; -import _1 from "./Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2"; -import _2 from "./Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2"; -import _3 from "./Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2"; -import _4 from "./Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2"; -import _5 from "./Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2"; -import _6 from "./Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import _5 from "./Excalifont-Regular-349fac6ca4700ffec595a7150a0d1e1d.woff2"; +import _4 from "./Excalifont-Regular-3f2c5db56cc93c5a6873b1361d730c16.woff2"; +import _3 from "./Excalifont-Regular-41b173a47b57366892116a575a43e2b6.woff2"; +import _6 from "./Excalifont-Regular-623ccf21b21ef6b3a0d87738f77eb071.woff2"; +import _0 from "./Excalifont-Regular-a88b72a24fb54c9f94e3b5fdaa7481c9.woff2"; +import _2 from "./Excalifont-Regular-b9dcf9d2e50a1eaf42fc664b50a3fd0d.woff2"; +import _1 from "./Excalifont-Regular-be310b9bcd4f1a43f571c46df7809174.woff2"; + /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Mon, 14 Oct 2024 18:59:19 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fonts/FontMetadata.ts b/packages/excalidraw/fonts/FontMetadata.ts index e93380e81..e8b46205b 100644 --- a/packages/excalidraw/fonts/FontMetadata.ts +++ b/packages/excalidraw/fonts/FontMetadata.ts @@ -1,4 +1,3 @@ -import type { JSX } from "react"; import { FreedrawIcon, FontFamilyNormalIcon, @@ -7,6 +6,8 @@ import { } from "../components/icons"; import { FONT_FAMILY, FONT_FAMILY_FALLBACKS } from "../constants"; +import type { JSX } from "react"; + /** * Encapsulates font metrics with additional font metadata. * */ diff --git a/packages/excalidraw/fonts/Fonts.ts b/packages/excalidraw/fonts/Fonts.ts index 4b8ba7828..c1b94bdef 100644 --- a/packages/excalidraw/fonts/Fonts.ts +++ b/packages/excalidraw/fonts/Fonts.ts @@ -7,15 +7,17 @@ import { } from "../constants"; import { isTextElement } from "../element"; import { getContainerElement } from "../element/textElement"; +import { charWidth } from "../element/textMeasurements"; import { containsCJK } from "../element/textWrapping"; import { ShapeCache } from "../scene/ShapeCache"; import { getFontString, PromisePool, promiseTry } from "../utils"; -import { ExcalidrawFontFace } from "./ExcalidrawFontFace"; import { CascadiaFontFaces } from "./Cascadia"; import { ComicShannsFontFaces } from "./ComicShanns"; import { EmojiFontFaces } from "./Emoji"; +import { ExcalidrawFontFace } from "./ExcalidrawFontFace"; import { ExcalifontFontFaces } from "./Excalifont"; +import { FONT_METADATA, type FontMetadata } from "./FontMetadata"; import { HelveticaFontFaces } from "./Helvetica"; import { LiberationFontFaces } from "./Liberation"; import { LilitaFontFaces } from "./Lilita"; @@ -23,7 +25,6 @@ import { NunitoFontFaces } from "./Nunito"; import { VirgilFontFaces } from "./Virgil"; import { XiaolaiFontFaces } from "./Xiaolai"; -import { FONT_METADATA, type FontMetadata } from "./FontMetadata"; import type { ExcalidrawElement, ExcalidrawTextElement, @@ -31,7 +32,6 @@ import type { } from "../element/types"; import type Scene from "../scene/Scene"; import type { ValueOf } from "../utility-types"; -import { charWidth } from "../element/textMeasurements"; export class Fonts { // it's ok to track fonts across multiple instances only once, so let's use diff --git a/packages/excalidraw/fonts/Helvetica/index.ts b/packages/excalidraw/fonts/Helvetica/index.ts index a0e7ecb61..f13d15118 100644 --- a/packages/excalidraw/fonts/Helvetica/index.ts +++ b/packages/excalidraw/fonts/Helvetica/index.ts @@ -1,5 +1,4 @@ import { LOCAL_FONT_PROTOCOL } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; export const HelveticaFontFaces: ExcalidrawFontFaceDescriptor[] = [ diff --git a/packages/excalidraw/fonts/Liberation/index.ts b/packages/excalidraw/fonts/Liberation/index.ts index 5bc964815..86b3e72ec 100644 --- a/packages/excalidraw/fonts/Liberation/index.ts +++ b/packages/excalidraw/fonts/Liberation/index.ts @@ -1,7 +1,7 @@ -import LiberationSansRegular from "./LiberationSans-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import LiberationSansRegular from "./LiberationSans-Regular.woff2"; + export const LiberationFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: LiberationSansRegular, diff --git a/packages/excalidraw/fonts/Lilita/index.ts b/packages/excalidraw/fonts/Lilita/index.ts index d5ea82e58..37a5d6a5e 100644 --- a/packages/excalidraw/fonts/Lilita/index.ts +++ b/packages/excalidraw/fonts/Lilita/index.ts @@ -1,10 +1,9 @@ -import LilitaLatin from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2"; -import LilitaLatinExt from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2"; - import { GOOGLE_FONTS_RANGES } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import LilitaLatinExt from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYE98RXi4EwSsbg.woff2"; +import LilitaLatin from "./Lilita-Regular-i7dPIFZ9Zz-WBtRtedDbYEF8RXi4EwQ.woff2"; + export const LilitaFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: LilitaLatinExt, diff --git a/packages/excalidraw/fonts/Nunito/index.ts b/packages/excalidraw/fonts/Nunito/index.ts index 4db432d07..3b092b0d6 100644 --- a/packages/excalidraw/fonts/Nunito/index.ts +++ b/packages/excalidraw/fonts/Nunito/index.ts @@ -1,13 +1,12 @@ -import Latin from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2"; -import LatinExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2"; -import Cyrilic from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2"; -import CyrilicExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2"; -import Vietnamese from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2"; - import { GOOGLE_FONTS_RANGES } from "../FontMetadata"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import Cyrilic from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTA3j6zbXWjgevT5.woff2"; +import Latin from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTQ3j6zbXWjgeg.woff2"; +import CyrilicExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTk3j6zbXWjgevT5.woff2"; +import LatinExt from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTo3j6zbXWjgevT5.woff2"; +import Vietnamese from "./Nunito-Regular-XRXI3I6Li01BKofiOc5wtlZ2di8HDIkhdTs3j6zbXWjgevT5.woff2"; + export const NunitoFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: CyrilicExt, diff --git a/packages/excalidraw/fonts/Virgil/index.ts b/packages/excalidraw/fonts/Virgil/index.ts index fdd5ffcfc..b9ce7ee78 100644 --- a/packages/excalidraw/fonts/Virgil/index.ts +++ b/packages/excalidraw/fonts/Virgil/index.ts @@ -1,7 +1,7 @@ -import Virgil from "./Virgil-Regular.woff2"; - import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; +import Virgil from "./Virgil-Regular.woff2"; + export const VirgilFontFaces: ExcalidrawFontFaceDescriptor[] = [ { uri: Virgil, diff --git a/packages/excalidraw/fonts/Xiaolai/index.ts b/packages/excalidraw/fonts/Xiaolai/index.ts index 17fd71831..67476b912 100644 --- a/packages/excalidraw/fonts/Xiaolai/index.ts +++ b/packages/excalidraw/fonts/Xiaolai/index.ts @@ -1,23 +1,31 @@ // The following file content was generated with https://chinese-font.netlify.app/online-split, // but has been manully rewritten from `@font-face` rules into TS while leveraging FontFace API. +import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; + +import _80 from "./Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2"; +import _16 from "./Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2"; +import _13 from "./Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2"; +import _166 from "./Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2"; +import _71 from "./Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2"; +import _161 from "./Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2"; +import _183 from "./Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2"; import _0 from "./Xiaolai-Regular-09850c4077f3fffe707905872e0e2460.woff2"; -import _1 from "./Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2"; +import _14 from "./Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2"; +import _10 from "./Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2"; import _2 from "./Xiaolai-Regular-60a3089806700d379f11827ee9843b6b.woff2"; +import _1 from "./Xiaolai-Regular-7eb9fffd1aa890d07d0f88cc82e6cfe4.woff2"; import _3 from "./Xiaolai-Regular-6fe5c5973cc06f74b2387a631ea36b88.woff2"; +import _6 from "./Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2"; import _4 from "./Xiaolai-Regular-b96d9226ce77ec94ceca043d712182e6.woff2"; import _5 from "./Xiaolai-Regular-6ae5b42180ad70b971c91e7eefb8eba2.woff2"; -import _6 from "./Xiaolai-Regular-a4c34be6d42152e64b0df90bc4607f64.woff2"; import _7 from "./Xiaolai-Regular-c69f61a4ab18d0488c8d1fc12e7028e8.woff2"; +import _30 from "./Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2"; import _8 from "./Xiaolai-Regular-e3fcf5180fd466c8915c4e8069491054.woff2"; import _9 from "./Xiaolai-Regular-c1f94158256bb1f3bf665b053d895af9.woff2"; -import _10 from "./Xiaolai-Regular-544fc28abe2c5c30e62383fd4dac255f.woff2"; import _11 from "./Xiaolai-Regular-7197d6fda6cba7c3874c53d6381ca239.woff2"; import _12 from "./Xiaolai-Regular-70c2eb8d64e71a42a834eb857ea9df51.woff2"; -import _13 from "./Xiaolai-Regular-069e77aac84590e2e991d0a0176d34f2.woff2"; -import _14 from "./Xiaolai-Regular-41521fade99856108931b4768b1b2648.woff2"; import _15 from "./Xiaolai-Regular-a004ddfcb26e67bd6e678c8ed19e25ce.woff2"; -import _16 from "./Xiaolai-Regular-04b718e5623574919c8b0dea5f301444.woff2"; import _17 from "./Xiaolai-Regular-7e4bde7e9c7f84cd34d8a845e384c746.woff2"; import _18 from "./Xiaolai-Regular-23686f7f29da6e8008c36dd3a80c83d6.woff2"; import _19 from "./Xiaolai-Regular-69c09cc5fa3e55c74fc4821f76909cc3.woff2"; @@ -31,7 +39,6 @@ import _26 from "./Xiaolai-Regular-7e929f262f30c8ee78bf398150b1a7cd.woff2"; import _27 from "./Xiaolai-Regular-73e309718fd16cea44b4d54a33581811.woff2"; import _28 from "./Xiaolai-Regular-9eb5a99df4e76ac3363453ac9ca288b1.woff2"; import _29 from "./Xiaolai-Regular-3e63ed8162808a9e425ed80a8bc79114.woff2"; -import _30 from "./Xiaolai-Regular-cb17fc3db95f6d139afc9d31a8e93293.woff2"; import _31 from "./Xiaolai-Regular-c8b71798409ccc126ee264a00aadcf21.woff2"; import _32 from "./Xiaolai-Regular-11c345711937f0ba4b8f7b6b919c8440.woff2"; import _33 from "./Xiaolai-Regular-e480d9c614742d05f0e78f274f1e69e6.woff2"; @@ -40,15 +47,17 @@ import _35 from "./Xiaolai-Regular-2cf96d082d35ea3d8106851223ad0d16.woff2"; import _36 from "./Xiaolai-Regular-2d43040e86ff03ba677f6f9c04cd0805.woff2"; import _37 from "./Xiaolai-Regular-2a26d20a23b00898ce82f09d2ee47c3f.woff2"; import _38 from "./Xiaolai-Regular-a365e82ed54697a52f27adcea1315fe8.woff2"; +import _41 from "./Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2"; +import _105 from "./Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2"; +import _82 from "./Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2"; +import _45 from "./Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2"; +import _47 from "./Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2"; import _39 from "./Xiaolai-Regular-f5d079153c99a25b9be5b8583c4cc8a7.woff2"; import _40 from "./Xiaolai-Regular-10a7ae9a371830a80c3d844acf1c02d7.woff2"; -import _41 from "./Xiaolai-Regular-e4bca6cfa53e499cae0a6be4894a90e9.woff2"; import _42 from "./Xiaolai-Regular-60a41c7e1c68f22424e6d22df544bc82.woff2"; import _43 from "./Xiaolai-Regular-7ab2bed91166a9dca83a5ebfbe2a7f38.woff2"; import _44 from "./Xiaolai-Regular-670ba603758d94268e8606f240a42e12.woff2"; -import _45 from "./Xiaolai-Regular-e656f091b9dc4709722c9f4b84d3c797.woff2"; import _46 from "./Xiaolai-Regular-15dc6d811c9cd078f9086a740d5a1038.woff2"; -import _47 from "./Xiaolai-Regular-f0f13b5c60e0af5553bd359f5513be1b.woff2"; import _48 from "./Xiaolai-Regular-8c2f33cee3993174f7e87c28e4bf42ee.woff2"; import _49 from "./Xiaolai-Regular-761d05e3cd968cf574166867998ef06a.woff2"; import _50 from "./Xiaolai-Regular-642b26e2e5f5fb780b51b593dbc8c851.woff2"; @@ -72,7 +81,6 @@ import _67 from "./Xiaolai-Regular-0b5d723fdc4e249c140f0909e87d03b4.woff2"; import _68 from "./Xiaolai-Regular-cdbce89e82cc1ab53a2decbf5819278f.woff2"; import _69 from "./Xiaolai-Regular-739bc1a567439c7cffcd1614644593d2.woff2"; import _70 from "./Xiaolai-Regular-72252d73220fa3cd856677888cee1635.woff2"; -import _71 from "./Xiaolai-Regular-08e0dc436ad0ad61ba5558db0674d762.woff2"; import _72 from "./Xiaolai-Regular-cf6ff4e0f491ca0cf3038187a997b9b4.woff2"; import _73 from "./Xiaolai-Regular-9cfb2a77a4e45025105ad29a1748b90d.woff2"; import _74 from "./Xiaolai-Regular-450da755d5bcb70906e1295e559b9602.woff2"; @@ -81,9 +89,7 @@ import _76 from "./Xiaolai-Regular-1ee544f0f1dac422545c505baa788992.woff2"; import _77 from "./Xiaolai-Regular-4806e761d750087c2d734fc64596eaff.woff2"; import _78 from "./Xiaolai-Regular-33432927cd87d40cfe393c7482bf221f.woff2"; import _79 from "./Xiaolai-Regular-be549ab72f0719d606a5c01e2c0219b6.woff2"; -import _80 from "./Xiaolai-Regular-019d66dcad46dc156b162d267f981c20.woff2"; import _81 from "./Xiaolai-Regular-b5c1596551c256e0e9cf02028595b092.woff2"; -import _82 from "./Xiaolai-Regular-e5f453bb04da18eed01675eeebd88bf8.woff2"; import _83 from "./Xiaolai-Regular-cf2cc71752631e579e35b0e423bf2638.woff2"; import _84 from "./Xiaolai-Regular-6f3256af8454371776bc46670d33cc65.woff2"; import _85 from "./Xiaolai-Regular-23f228f3999c01983860012330e4be08.woff2"; @@ -106,7 +112,6 @@ import _101 from "./Xiaolai-Regular-4a0fdb40036e87b40aa08dd30584cb85.woff2"; import _102 from "./Xiaolai-Regular-0f626226ba1272e832aea87bafd9720e.woff2"; import _103 from "./Xiaolai-Regular-938d90c10ff8c20386af7f242c05d6b0.woff2"; import _104 from "./Xiaolai-Regular-b6d128682ee29e471486354d486a1b90.woff2"; -import _105 from "./Xiaolai-Regular-e51ef413167c6e14e0c0fdcc585f2fc9.woff2"; import _106 from "./Xiaolai-Regular-9d81066dd2b337c938df6e90380a00dc.woff2"; import _107 from "./Xiaolai-Regular-20e7bf72fa05de9adf7dbcc7bf51dde6.woff2"; import _108 from "./Xiaolai-Regular-4095eb84ef3874e2600247bee0b04026.woff2"; @@ -162,15 +167,14 @@ import _157 from "./Xiaolai-Regular-774d4f764a1299da5d28ec2f2ffe0d69.woff2"; import _158 from "./Xiaolai-Regular-7718fe60986d8b42b1be9c5ace5ccf25.woff2"; import _159 from "./Xiaolai-Regular-aa5c9ca6cf4fba00433b7aa3fa10671a.woff2"; import _160 from "./Xiaolai-Regular-4f50e5136e136527280bc902c5817561.woff2"; -import _161 from "./Xiaolai-Regular-093b9ef39a46ceae95a1df18a0a3a326.woff2"; import _162 from "./Xiaolai-Regular-a0ca5df4258213d7fc9fce80f65ce760.woff2"; import _163 from "./Xiaolai-Regular-d2666cbed13462c5dc36fa2f15c202ca.woff2"; import _164 from "./Xiaolai-Regular-1e6fd68f1f3902ce48ce8c69df385622.woff2"; import _165 from "./Xiaolai-Regular-87599f94b6cc129d505b375798d0d751.woff2"; -import _166 from "./Xiaolai-Regular-06c77b8c66e51ed6c63ccb502dd8b8af.woff2"; import _167 from "./Xiaolai-Regular-13ae07ed2e272d26d59bc0691cd7117a.woff2"; import _168 from "./Xiaolai-Regular-353f33792a8f60dc69323ddf635a269e.woff2"; import _169 from "./Xiaolai-Regular-0facdf1ea213ba40261022f5d5ed4493.woff2"; +import _202 from "./Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2"; import _170 from "./Xiaolai-Regular-f8ee5d36068a42b51d0e4a1116cfcec1.woff2"; import _171 from "./Xiaolai-Regular-79d494361ae093b69e74ee9dbe65bfd4.woff2"; import _172 from "./Xiaolai-Regular-74e2263a91439c25b91d5132ce9f4d62.woff2"; @@ -184,7 +188,6 @@ import _179 from "./Xiaolai-Regular-8e9f97f01034820170065b2921b4fb5e.woff2"; import _180 from "./Xiaolai-Regular-13d2887ec8ee73c43acdabc52a05af7b.woff2"; import _181 from "./Xiaolai-Regular-72536a3d71b694a0d53dd90ddceae41e.woff2"; import _182 from "./Xiaolai-Regular-603aefd23e350ba7eb124273e3c9bcf1.woff2"; -import _183 from "./Xiaolai-Regular-095c169f3314805276f603a362766abd.woff2"; import _184 from "./Xiaolai-Regular-9544732d2e62d1a429674f8ee41b5d3a.woff2"; import _185 from "./Xiaolai-Regular-d3716376641d615e2995605b29bca7b6.woff2"; import _186 from "./Xiaolai-Regular-5a1ce3117cfe90c48e8fb4a9a00f694d.woff2"; @@ -203,7 +206,6 @@ import _198 from "./Xiaolai-Regular-24476a126f129212beb33f66853ea151.woff2"; import _199 from "./Xiaolai-Regular-1b611157cd46bb184d4fa4dae2d6a2b8.woff2"; import _200 from "./Xiaolai-Regular-56a32a7689abd0326e57c10c6c069bb4.woff2"; import _201 from "./Xiaolai-Regular-3cc70dbb64df5b21f1326cc24dee2195.woff2"; -import _202 from "./Xiaolai-Regular-f6032fc06eb20480f096199713f70885.woff2"; import _203 from "./Xiaolai-Regular-e2ead7ea7da0437f085f42ffc05f8d13.woff2"; import _204 from "./Xiaolai-Regular-97f7f48ce90c9429bf32ae51469db74d.woff2"; import _205 from "./Xiaolai-Regular-24a21c1e4449222e8d1898d69ff3a404.woff2"; @@ -211,8 +213,6 @@ import _206 from "./Xiaolai-Regular-726303e0774b4e678bff8c2deb6ca603.woff2"; import _207 from "./Xiaolai-Regular-5a7fac4b8b23a6e4e5ba0c9bf1756c91.woff2"; import _208 from "./Xiaolai-Regular-2b7441d46298788ac94e610ffcc709b6.woff2"; -import { type ExcalidrawFontFaceDescriptor } from "../Fonts"; - /* Generated By cn-font-split@5.2.2 https://www.npmjs.com/package/cn-font-split CreateTime: Tue, 08 Oct 2024 18:34:44 GMT; Origin File Name Table: diff --git a/packages/excalidraw/fractionalIndex.ts b/packages/excalidraw/fractionalIndex.ts index dfb8a4672..8a1459ddd 100644 --- a/packages/excalidraw/fractionalIndex.ts +++ b/packages/excalidraw/fractionalIndex.ts @@ -1,14 +1,16 @@ import { generateNKeysBetween } from "fractional-indexing"; + import { mutateElement } from "./element/mutateElement"; +import { getBoundTextElement } from "./element/textElement"; +import { hasBoundTextElement } from "./element/typeChecks"; +import { InvalidFractionalIndexError } from "./errors"; +import { arrayToMap } from "./utils"; + import type { ExcalidrawElement, FractionalIndex, OrderedExcalidrawElement, } from "./element/types"; -import { InvalidFractionalIndexError } from "./errors"; -import { hasBoundTextElement } from "./element/typeChecks"; -import { getBoundTextElement } from "./element/textElement"; -import { arrayToMap } from "./utils"; /** * Envisioned relation between array order and fractional indices: diff --git a/packages/excalidraw/frame.test.tsx b/packages/excalidraw/frame.test.tsx index 6a5045b2c..fce420c02 100644 --- a/packages/excalidraw/frame.test.tsx +++ b/packages/excalidraw/frame.test.tsx @@ -1,9 +1,11 @@ -import type { ExcalidrawElement } from "./element/types"; -import { convertToExcalidrawElements, Excalidraw } from "./index"; import { API } from "./tests/helpers/api"; import { Keyboard, Pointer } from "./tests/helpers/ui"; import { getCloneByOrigId, render } from "./tests/test-utils"; +import { convertToExcalidrawElements, Excalidraw } from "./index"; + +import type { ExcalidrawElement } from "./element/types"; + const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/frame.ts b/packages/excalidraw/frame.ts index 4659a34a0..758bc273e 100644 --- a/packages/excalidraw/frame.ts +++ b/packages/excalidraw/frame.ts @@ -1,8 +1,25 @@ +import { isPointWithinBounds, pointFrom } from "@excalidraw/math"; +import { + doLineSegmentsIntersect, + elementsOverlappingBBox, +} from "@excalidraw/utils"; + import { getCommonBounds, getElementAbsoluteCoords, isTextElement, } from "./element"; +import { getElementLineSegments } from "./element/bounds"; +import { mutateElement } from "./element/mutateElement"; +import { + getBoundTextElement, + getContainerElement, +} from "./element/textElement"; +import { isFrameElement, isFrameLikeElement } from "./element/typeChecks"; +import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; +import { getElementsWithinSelection, getSelectedElements } from "./scene"; +import { arrayToMap } from "./utils"; + import type { ElementsMap, ElementsMapOrArray, @@ -11,28 +28,13 @@ import type { NonDeleted, NonDeletedExcalidrawElement, } from "./element/types"; -import { - getBoundTextElement, - getContainerElement, -} from "./element/textElement"; -import { arrayToMap } from "./utils"; -import { mutateElement } from "./element/mutateElement"; +import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; import type { AppClassProperties, AppState, StaticCanvasAppState, } from "./types"; -import { getElementsWithinSelection, getSelectedElements } from "./scene"; -import { getElementsInGroup, selectGroupsFromGivenElements } from "./groups"; -import type { ExcalidrawElementsIncludingDeleted } from "./scene/Scene"; -import { getElementLineSegments } from "./element/bounds"; -import { - doLineSegmentsIntersect, - elementsOverlappingBBox, -} from "@excalidraw/utils"; -import { isFrameElement, isFrameLikeElement } from "./element/typeChecks"; import type { ReadonlySetLike } from "./utility-types"; -import { isPointWithinBounds, pointFrom } from "@excalidraw/math"; // --------------------------- Frame State ------------------------------------ export const bindElementsToFramesAfterDuplication = ( diff --git a/packages/excalidraw/groups.ts b/packages/excalidraw/groups.ts index 5a4e606f7..cedc4af0f 100644 --- a/packages/excalidraw/groups.ts +++ b/packages/excalidraw/groups.ts @@ -1,3 +1,7 @@ +import { getBoundTextElement } from "./element/textElement"; +import { getSelectedElements } from "./scene"; +import { makeNextSelectedElementIds } from "./scene/selection"; + import type { GroupId, ExcalidrawElement, @@ -11,9 +15,6 @@ import type { AppState, InteractiveCanvasAppState, } from "./types"; -import { getSelectedElements } from "./scene"; -import { getBoundTextElement } from "./element/textElement"; -import { makeNextSelectedElementIds } from "./scene/selection"; import type { Mutable } from "./utility-types"; export const selectGroup = ( diff --git a/packages/excalidraw/history.ts b/packages/excalidraw/history.ts index daed2a394..48ea012bd 100644 --- a/packages/excalidraw/history.ts +++ b/packages/excalidraw/history.ts @@ -1,6 +1,7 @@ +import { Emitter } from "./emitter"; + import type { AppStateChange, ElementsChange } from "./change"; import type { SceneElementsMap } from "./element/types"; -import { Emitter } from "./emitter"; import type { Snapshot } from "./store"; import type { AppState } from "./types"; diff --git a/packages/excalidraw/hooks/useCreatePortalContainer.ts b/packages/excalidraw/hooks/useCreatePortalContainer.ts index e8f5e3db6..b557d7e2f 100644 --- a/packages/excalidraw/hooks/useCreatePortalContainer.ts +++ b/packages/excalidraw/hooks/useCreatePortalContainer.ts @@ -1,4 +1,5 @@ import { useState, useLayoutEffect } from "react"; + import { useDevice, useExcalidrawContainer } from "../components/App"; import { THEME } from "../constants"; import { useUIAppState } from "../context/ui-appState"; diff --git a/packages/excalidraw/hooks/useEmitter.ts b/packages/excalidraw/hooks/useEmitter.ts index 27b94bc91..eebbaaf30 100644 --- a/packages/excalidraw/hooks/useEmitter.ts +++ b/packages/excalidraw/hooks/useEmitter.ts @@ -1,4 +1,5 @@ import { useEffect, useState } from "react"; + import type { Emitter } from "../emitter"; export const useEmitter = ( diff --git a/packages/excalidraw/hooks/useLibraryItemSvg.ts b/packages/excalidraw/hooks/useLibraryItemSvg.ts index 72b648d11..a79aab5c5 100644 --- a/packages/excalidraw/hooks/useLibraryItemSvg.ts +++ b/packages/excalidraw/hooks/useLibraryItemSvg.ts @@ -1,7 +1,9 @@ +import { exportToSvg } from "@excalidraw/utils/export"; import { useEffect, useState } from "react"; + import { COLOR_PALETTE } from "../colors"; import { atom, useAtom } from "../editor-jotai"; -import { exportToSvg } from "@excalidraw/utils/export"; + import type { LibraryItem } from "../types"; export type SvgCache = Map; diff --git a/packages/excalidraw/hooks/useOutsideClick.ts b/packages/excalidraw/hooks/useOutsideClick.ts index da9a54d08..7ec2113c2 100644 --- a/packages/excalidraw/hooks/useOutsideClick.ts +++ b/packages/excalidraw/hooks/useOutsideClick.ts @@ -1,4 +1,5 @@ import { useEffect } from "react"; + import { EVENT } from "../constants"; export function useOutsideClick( diff --git a/packages/excalidraw/hooks/useScrollPosition.ts b/packages/excalidraw/hooks/useScrollPosition.ts index 0be2eab95..1fb1408b5 100644 --- a/packages/excalidraw/hooks/useScrollPosition.ts +++ b/packages/excalidraw/hooks/useScrollPosition.ts @@ -1,6 +1,7 @@ -import { useEffect } from "react"; -import { atom, useAtom } from "../editor-jotai"; import throttle from "lodash.throttle"; +import { useEffect } from "react"; + +import { atom, useAtom } from "../editor-jotai"; const scrollPositionAtom = atom(0); diff --git a/packages/excalidraw/i18n.ts b/packages/excalidraw/i18n.ts index e1da5fc44..47bae5979 100644 --- a/packages/excalidraw/i18n.ts +++ b/packages/excalidraw/i18n.ts @@ -1,6 +1,7 @@ +import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai"; import fallbackLangData from "./locales/en.json"; import percentages from "./locales/percentages.json"; -import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai"; + import type { NestedKeyOf } from "./utility-types"; const COMPLETION_THRESHOLD = 85; diff --git a/packages/excalidraw/index-node.ts b/packages/excalidraw/index-node.ts index e966b1d52..3b9499149 100644 --- a/packages/excalidraw/index-node.ts +++ b/packages/excalidraw/index-node.ts @@ -1,5 +1,7 @@ -import { exportToCanvas } from "./scene/export"; import { getDefaultAppState } from "./appState"; +import { exportToCanvas } from "./scene/export"; + +const fs = require("fs"); const { registerFont, createCanvas } = require("canvas"); @@ -74,7 +76,6 @@ const canvas = exportToCanvas( createCanvas, ); -const fs = require("fs"); const out = fs.createWriteStream("test.png"); const stream = (canvas as any).createPNGStream(); stream.pipe(out); diff --git a/packages/excalidraw/index.tsx b/packages/excalidraw/index.tsx index b4b8574bd..f9f25b530 100644 --- a/packages/excalidraw/index.tsx +++ b/packages/excalidraw/index.tsx @@ -1,21 +1,22 @@ import React, { useEffect } from "react"; -import { InitializeApp } from "./components/InitializeApp"; + import App from "./components/App"; -import { isShallowEqual } from "./utils"; +import { InitializeApp } from "./components/InitializeApp"; +import Footer from "./components/footer/FooterCenter"; +import LiveCollaborationTrigger from "./components/live-collaboration/LiveCollaborationTrigger"; +import MainMenu from "./components/main-menu/MainMenu"; +import WelcomeScreen from "./components/welcome-screen/WelcomeScreen"; +import { DEFAULT_UI_OPTIONS } from "./constants"; +import { defaultLang } from "./i18n"; +import { EditorJotaiProvider, editorJotaiStore } from "./editor-jotai"; import polyfill from "./polyfill"; +import { isShallowEqual } from "./utils"; import "./css/app.scss"; import "./css/styles.scss"; import "./fonts/fonts.css"; import type { AppProps, ExcalidrawProps } from "./types"; -import { defaultLang } from "./i18n"; -import { DEFAULT_UI_OPTIONS } from "./constants"; -import { EditorJotaiProvider, editorJotaiStore } from "./editor-jotai"; -import Footer from "./components/footer/FooterCenter"; -import MainMenu from "./components/main-menu/MainMenu"; -import WelcomeScreen from "./components/welcome-screen/WelcomeScreen"; -import LiveCollaborationTrigger from "./components/live-collaboration/LiveCollaborationTrigger"; polyfill(); diff --git a/packages/excalidraw/keys.ts b/packages/excalidraw/keys.ts index 2088f89d6..948e7f568 100644 --- a/packages/excalidraw/keys.ts +++ b/packages/excalidraw/keys.ts @@ -1,4 +1,5 @@ import { isDarwin } from "./constants"; + import type { ValueOf } from "./utility-types"; export const CODES = { diff --git a/packages/excalidraw/laser-trails.ts b/packages/excalidraw/laser-trails.ts index b7733baed..06e6b573a 100644 --- a/packages/excalidraw/laser-trails.ts +++ b/packages/excalidraw/laser-trails.ts @@ -1,12 +1,14 @@ import type { LaserPointerOptions } from "@excalidraw/laser-pointer"; -import type { Trail } from "./animated-trail"; + import { AnimatedTrail } from "./animated-trail"; +import { getClientColor } from "./clients"; +import { DEFAULT_LASER_COLOR } from "./constants"; +import { easeOut } from "./utils"; + +import type { Trail } from "./animated-trail"; import type { AnimationFrameHandler } from "./animation-frame-handler"; import type App from "./components/App"; import type { SocketId } from "./types"; -import { easeOut } from "./utils"; -import { getClientColor } from "./clients"; -import { DEFAULT_LASER_COLOR } from "./constants"; export class LaserTrails implements Trail { public localTrail: AnimatedTrail; diff --git a/packages/excalidraw/queue.ts b/packages/excalidraw/queue.ts index 9cac2c5e9..b7369e5e0 100644 --- a/packages/excalidraw/queue.ts +++ b/packages/excalidraw/queue.ts @@ -1,6 +1,7 @@ +import { promiseTry, resolvablePromise } from "./utils"; + import type { MaybePromise } from "./utility-types"; import type { ResolvablePromise } from "./utils"; -import { promiseTry, resolvablePromise } from "./utils"; type Job = (...args: TArgs) => MaybePromise; diff --git a/packages/excalidraw/random.ts b/packages/excalidraw/random.ts index 851bc28ec..4a4424a76 100644 --- a/packages/excalidraw/random.ts +++ b/packages/excalidraw/random.ts @@ -1,5 +1,6 @@ -import { Random } from "roughjs/bin/math"; import { nanoid } from "nanoid"; +import { Random } from "roughjs/bin/math"; + import { isTestEnv } from "./utils"; let random = new Random(Date.now()); diff --git a/packages/excalidraw/reactUtils.ts b/packages/excalidraw/reactUtils.ts index 535302d42..5bc466395 100644 --- a/packages/excalidraw/reactUtils.ts +++ b/packages/excalidraw/reactUtils.ts @@ -2,8 +2,9 @@ * @param func handler taking at most single parameter (event). */ -import { unstable_batchedUpdates } from "react-dom"; import { version as ReactVersion } from "react"; +import { unstable_batchedUpdates } from "react-dom"; + import { throttleRAF } from "./utils"; export const withBatchedUpdates = < diff --git a/packages/excalidraw/renderer/helpers.ts b/packages/excalidraw/renderer/helpers.ts index 90f40099f..05097f95b 100644 --- a/packages/excalidraw/renderer/helpers.ts +++ b/packages/excalidraw/renderer/helpers.ts @@ -1,8 +1,7 @@ -import type { StaticCanvasAppState, AppState } from "../types"; +import { THEME, THEME_FILTER } from "../constants"; import type { StaticCanvasRenderConfig } from "../scene/types"; - -import { THEME, THEME_FILTER } from "../constants"; +import type { StaticCanvasAppState, AppState } from "../types"; export const fillCircle = ( context: CanvasRenderingContext2D, diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 9aa832770..257decd62 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -1,48 +1,23 @@ +import { + pointFrom, + type GlobalPoint, + type LocalPoint, + type Radians, +} from "@excalidraw/math"; +import oc from "open-color"; + +import { getClientColor, renderRemoteCursors } from "../clients"; +import { + DEFAULT_TRANSFORM_HANDLE_SPACING, + FRAME_STYLE, + THEME, +} from "../constants"; import { getElementAbsoluteCoords, getTransformHandlesFromCoords, getTransformHandles, getCommonBounds, } from "../element"; - -import { roundRect } from "../renderer/roundRect"; - -import { - getScrollBars, - SCROLLBAR_COLOR, - SCROLLBAR_WIDTH, -} from "../scene/scrollbars"; - -import { renderSelectionElement } from "../renderer/renderElement"; -import { getClientColor, renderRemoteCursors } from "../clients"; -import { - isSelectedViaGroup, - getSelectedGroupIds, - getElementsInGroup, - selectGroupsFromGivenElements, -} from "../groups"; -import type { - TransformHandles, - TransformHandleType, -} from "../element/transformHandles"; -import { - getOmitSidesForDevice, - shouldShowBoundingBox, -} from "../element/transformHandles"; -import { arrayToMap, invariant, throttleRAF } from "../utils"; -import { - DEFAULT_TRANSFORM_HANDLE_SPACING, - FRAME_STYLE, - THEME, -} from "../constants"; -import { type InteractiveCanvasAppState } from "../types"; - -import { renderSnaps } from "../renderer/renderSnaps"; - -import type { - SuggestedBinding, - SuggestedPointBinding, -} from "../element/binding"; import { BINDING_HIGHLIGHT_OFFSET, BINDING_HIGHLIGHT_THICKNESS, @@ -50,11 +25,9 @@ import { } from "../element/binding"; import { LinearElementEditor } from "../element/linearElementEditor"; import { - bootstrapCanvas, - fillCircle, - getNormalizedCanvasDimensions, -} from "./helpers"; -import oc from "open-color"; + getOmitSidesForDevice, + shouldShowBoundingBox, +} from "../element/transformHandles"; import { isElbowArrow, isFrameLikeElement, @@ -62,6 +35,38 @@ import { isLinearElement, isTextElement, } from "../element/typeChecks"; +import { + isSelectedViaGroup, + getSelectedGroupIds, + getElementsInGroup, + selectGroupsFromGivenElements, +} from "../groups"; +import { renderSelectionElement } from "../renderer/renderElement"; +import { renderSnaps } from "../renderer/renderSnaps"; +import { roundRect } from "../renderer/roundRect"; +import { + getScrollBars, + SCROLLBAR_COLOR, + SCROLLBAR_WIDTH, +} from "../scene/scrollbars"; +import { getCornerRadius } from "../shapes"; +import { type InteractiveCanvasAppState } from "../types"; +import { arrayToMap, invariant, throttleRAF } from "../utils"; + +import { + bootstrapCanvas, + fillCircle, + getNormalizedCanvasDimensions, +} from "./helpers"; + +import type { + SuggestedBinding, + SuggestedPointBinding, +} from "../element/binding"; +import type { + TransformHandles, + TransformHandleType, +} from "../element/transformHandles"; import type { ElementsMap, ExcalidrawBindableElement, @@ -78,13 +83,6 @@ import type { InteractiveSceneRenderConfig, RenderableElementsMap, } from "../scene/types"; -import { - pointFrom, - type GlobalPoint, - type LocalPoint, - type Radians, -} from "@excalidraw/math"; -import { getCornerRadius } from "../shapes"; const renderElbowArrowMidPointHighlight = ( context: CanvasRenderingContext2D, diff --git a/packages/excalidraw/renderer/renderElement.ts b/packages/excalidraw/renderer/renderElement.ts index d93469c2d..9209c46d6 100644 --- a/packages/excalidraw/renderer/renderElement.ts +++ b/packages/excalidraw/renderer/renderElement.ts @@ -1,3 +1,43 @@ +import { isRightAngleRads } from "@excalidraw/math"; +import { getStroke } from "perfect-freehand"; +import rough from "roughjs/bin/rough"; + +import { getDefaultAppState } from "../appState"; +import { + BOUND_TEXT_PADDING, + DEFAULT_REDUCED_GLOBAL_ALPHA, + ELEMENT_READY_TO_ERASE_OPACITY, + FRAME_STYLE, + MIME_TYPES, + THEME, +} from "../constants"; +import { getElementAbsoluteCoords } from "../element/bounds"; +import { getUncroppedImageElement } from "../element/cropElement"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { + getBoundTextElement, + getContainerCoords, + getContainerElement, + getBoundTextMaxHeight, + getBoundTextMaxWidth, +} from "../element/textElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; +import { + isTextElement, + isLinearElement, + isFreeDrawElement, + isInitializedImageElement, + isArrowElement, + hasBoundTextElement, + isMagicFrameElement, + isImageElement, +} from "../element/typeChecks"; +import { getVerticalOffset } from "../fonts"; +import { getContainingFrame } from "../frame"; +import { ShapeCache } from "../scene/ShapeCache"; +import { getCornerRadius } from "../shapes"; +import { distance, getFontString, isRTL } from "../utils"; + import type { ExcalidrawElement, ExcalidrawTextElement, @@ -9,26 +49,11 @@ import type { NonDeletedSceneElementsMap, ElementsMap, } from "../element/types"; -import { - isTextElement, - isLinearElement, - isFreeDrawElement, - isInitializedImageElement, - isArrowElement, - hasBoundTextElement, - isMagicFrameElement, - isImageElement, -} from "../element/typeChecks"; -import { getElementAbsoluteCoords } from "../element/bounds"; -import type { RoughCanvas } from "roughjs/bin/canvas"; - import type { StaticCanvasRenderConfig, RenderableElementsMap, InteractiveCanvasRenderConfig, } from "../scene/types"; -import { distance, getFontString, isRTL } from "../utils"; -import rough from "roughjs/bin/rough"; import type { AppState, StaticCanvasAppState, @@ -37,33 +62,8 @@ import type { ElementsPendingErasure, PendingExcalidrawElements, } from "../types"; -import { getDefaultAppState } from "../appState"; -import { - BOUND_TEXT_PADDING, - DEFAULT_REDUCED_GLOBAL_ALPHA, - ELEMENT_READY_TO_ERASE_OPACITY, - FRAME_STYLE, - MIME_TYPES, - THEME, -} from "../constants"; import type { StrokeOptions } from "perfect-freehand"; -import { getStroke } from "perfect-freehand"; -import { - getBoundTextElement, - getContainerCoords, - getContainerElement, - getBoundTextMaxHeight, - getBoundTextMaxWidth, -} from "../element/textElement"; -import { LinearElementEditor } from "../element/linearElementEditor"; - -import { getContainingFrame } from "../frame"; -import { ShapeCache } from "../scene/ShapeCache"; -import { getVerticalOffset } from "../fonts"; -import { isRightAngleRads } from "@excalidraw/math"; -import { getCornerRadius } from "../shapes"; -import { getUncroppedImageElement } from "../element/cropElement"; -import { getLineHeightInPx } from "../element/textMeasurements"; +import type { RoughCanvas } from "roughjs/bin/canvas"; // using a stronger invert (100% vs our regular 93%) and saturate // as a temp hack to make images in dark theme look closer to original diff --git a/packages/excalidraw/renderer/renderNewElementScene.ts b/packages/excalidraw/renderer/renderNewElementScene.ts index caa7f581c..f80408366 100644 --- a/packages/excalidraw/renderer/renderNewElementScene.ts +++ b/packages/excalidraw/renderer/renderNewElementScene.ts @@ -1,8 +1,10 @@ -import type { NewElementSceneRenderConfig } from "../scene/types"; import { throttleRAF } from "../utils"; + import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; import { renderElement } from "./renderElement"; +import type { NewElementSceneRenderConfig } from "../scene/types"; + const _renderNewElementScene = ({ canvas, rc, diff --git a/packages/excalidraw/renderer/renderSnaps.ts b/packages/excalidraw/renderer/renderSnaps.ts index 878e8e523..8c26675ac 100644 --- a/packages/excalidraw/renderer/renderSnaps.ts +++ b/packages/excalidraw/renderer/renderSnaps.ts @@ -1,5 +1,7 @@ import { pointFrom, type GlobalPoint, type LocalPoint } from "@excalidraw/math"; + import { THEME } from "../constants"; + import type { PointSnapLine, PointerSnapLine } from "../snapping"; import type { InteractiveCanvasAppState } from "../types"; diff --git a/packages/excalidraw/renderer/staticScene.ts b/packages/excalidraw/renderer/staticScene.ts index 90ed8af43..62aeed5b9 100644 --- a/packages/excalidraw/renderer/staticScene.ts +++ b/packages/excalidraw/renderer/staticScene.ts @@ -1,19 +1,28 @@ +import { + EXTERNAL_LINK_IMG, + ELEMENT_LINK_IMG, + getLinkHandleFromCoords, +} from "../components/hyperlink/helpers"; import { FRAME_STYLE } from "../constants"; import { getElementAbsoluteCoords } from "../element"; - -import { - elementOverlapsWithFrame, - getTargetFrame, - shouldApplyFrameClip, -} from "../frame"; +import { isElementLink } from "../element/elementLink"; +import { createPlaceholderEmbeddableLabel } from "../element/embeddable"; +import { getBoundTextElement } from "../element/textElement"; import { isEmbeddableElement, isIframeLikeElement, isTextElement, } from "../element/typeChecks"; +import { + elementOverlapsWithFrame, + getTargetFrame, + shouldApplyFrameClip, +} from "../frame"; import { renderElement } from "../renderer/renderElement"; -import { createPlaceholderEmbeddableLabel } from "../element/embeddable"; -import type { StaticCanvasAppState, Zoom } from "../types"; +import { throttleRAF } from "../utils"; + +import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; + import type { ElementsMap, ExcalidrawFrameLikeElement, @@ -23,15 +32,7 @@ import type { StaticCanvasRenderConfig, StaticSceneRenderConfig, } from "../scene/types"; -import { - EXTERNAL_LINK_IMG, - ELEMENT_LINK_IMG, - getLinkHandleFromCoords, -} from "../components/hyperlink/helpers"; -import { bootstrapCanvas, getNormalizedCanvasDimensions } from "./helpers"; -import { throttleRAF } from "../utils"; -import { getBoundTextElement } from "../element/textElement"; -import { isElementLink } from "../element/elementLink"; +import type { StaticCanvasAppState, Zoom } from "../types"; const GridLineColor = { Bold: "#dddddd", diff --git a/packages/excalidraw/renderer/staticSvgScene.ts b/packages/excalidraw/renderer/staticSvgScene.ts index b14faf7f4..23a6890df 100644 --- a/packages/excalidraw/renderer/staticSvgScene.ts +++ b/packages/excalidraw/renderer/staticSvgScene.ts @@ -1,5 +1,3 @@ -import type { Drawable } from "roughjs/bin/core"; -import type { RoughSVG } from "roughjs/bin/svg"; import { FRAME_STYLE, MAX_DECIMALS_FOR_SVG_EXPORT, @@ -8,6 +6,7 @@ import { } from "../constants"; import { normalizeLink, toValidURL } from "../data/url"; import { getElementAbsoluteCoords, hashString } from "../element"; +import { getUncroppedWidthAndHeight } from "../element/cropElement"; import { createPlaceholderEmbeddableLabel, getEmbedLink, @@ -17,27 +16,30 @@ import { getBoundTextElement, getContainerElement, } from "../element/textElement"; +import { getLineHeightInPx } from "../element/textMeasurements"; import { isArrowElement, isIframeLikeElement, isInitializedImageElement, isTextElement, } from "../element/typeChecks"; +import { getVerticalOffset } from "../fonts"; +import { getContainingFrame } from "../frame"; +import { ShapeCache } from "../scene/ShapeCache"; +import { getCornerRadius, isPathALoop } from "../shapes"; +import { getFontFamilyString, isRTL, isTestEnv } from "../utils"; + +import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement"; + import type { ExcalidrawElement, ExcalidrawTextElementWithContainer, NonDeletedExcalidrawElement, } from "../element/types"; -import { getContainingFrame } from "../frame"; -import { ShapeCache } from "../scene/ShapeCache"; import type { RenderableElementsMap, SVGRenderConfig } from "../scene/types"; import type { AppState, BinaryFiles } from "../types"; -import { getFontFamilyString, isRTL, isTestEnv } from "../utils"; -import { getFreeDrawSvgPath, IMAGE_INVERT_FILTER } from "./renderElement"; -import { getVerticalOffset } from "../fonts"; -import { getCornerRadius, isPathALoop } from "../shapes"; -import { getUncroppedWidthAndHeight } from "../element/cropElement"; -import { getLineHeightInPx } from "../element/textMeasurements"; +import type { Drawable } from "roughjs/bin/core"; +import type { RoughSVG } from "roughjs/bin/svg"; const roughSVGDrawWithPrecision = ( rsvg: RoughSVG, diff --git a/packages/excalidraw/scene/Renderer.ts b/packages/excalidraw/scene/Renderer.ts index 8048d20c1..19a6c0b10 100644 --- a/packages/excalidraw/scene/Renderer.ts +++ b/packages/excalidraw/scene/Renderer.ts @@ -1,17 +1,17 @@ import { isElementInViewport } from "../element/sizeHelpers"; import { isImageElement } from "../element/typeChecks"; +import { renderInteractiveSceneThrottled } from "../renderer/interactiveScene"; +import { renderStaticSceneThrottled } from "../renderer/staticScene"; +import { memoize, toBrandedType } from "../utils"; + +import type Scene from "./Scene"; +import type { RenderableElementsMap } from "./types"; import type { ExcalidrawElement, NonDeletedElementsMap, NonDeletedExcalidrawElement, } from "../element/types"; -import { renderInteractiveSceneThrottled } from "../renderer/interactiveScene"; -import { renderStaticSceneThrottled } from "../renderer/staticScene"; - import type { AppState } from "../types"; -import { memoize, toBrandedType } from "../utils"; -import type Scene from "./Scene"; -import type { RenderableElementsMap } from "./types"; export class Renderer { private scene: Scene; diff --git a/packages/excalidraw/scene/Scene.ts b/packages/excalidraw/scene/Scene.ts index 99bb9e1e4..0eab8b80e 100644 --- a/packages/excalidraw/scene/Scene.ts +++ b/packages/excalidraw/scene/Scene.ts @@ -1,4 +1,21 @@ import throttle from "lodash.throttle"; + +import { ENV } from "../constants"; +import { isNonDeletedElement } from "../element"; +import { isFrameLikeElement } from "../element/typeChecks"; +import { + syncInvalidIndices, + syncMovedIndices, + validateFractionalIndices, +} from "../fractionalIndex"; +import { getElementsInGroup } from "../groups"; +import { randomInteger } from "../random"; +import { arrayToMap } from "../utils"; +import { toBrandedType } from "../utils"; + +import { getSelectedElements } from "./selection"; + +import type { LinearElementEditor } from "../element/linearElementEditor"; import type { ExcalidrawElement, NonDeletedExcalidrawElement, @@ -10,22 +27,8 @@ import type { OrderedExcalidrawElement, Ordered, } from "../element/types"; -import { isNonDeletedElement } from "../element"; -import type { LinearElementEditor } from "../element/linearElementEditor"; -import { isFrameLikeElement } from "../element/typeChecks"; -import { getSelectedElements } from "./selection"; import type { AppState } from "../types"; import type { Assert, SameType } from "../utility-types"; -import { randomInteger } from "../random"; -import { - syncInvalidIndices, - syncMovedIndices, - validateFractionalIndices, -} from "../fractionalIndex"; -import { arrayToMap } from "../utils"; -import { toBrandedType } from "../utils"; -import { ENV } from "../constants"; -import { getElementsInGroup } from "../groups"; type ElementIdKey = InstanceType["elementId"]; type ElementKey = ExcalidrawElement | ElementIdKey; diff --git a/packages/excalidraw/scene/Shape.ts b/packages/excalidraw/scene/Shape.ts index 9c49db0c2..64d90b789 100644 --- a/packages/excalidraw/scene/Shape.ts +++ b/packages/excalidraw/scene/Shape.ts @@ -1,19 +1,9 @@ -import type { Point as RoughPoint } from "roughjs/bin/geometry"; -import type { Drawable, Options } from "roughjs/bin/core"; -import type { RoughGenerator } from "roughjs/bin/generator"; -import { getDiamondPoints, getArrowheadPoints } from "../element"; -import type { ElementShapes } from "./types"; -import type { - ExcalidrawElement, - NonDeletedExcalidrawElement, - ExcalidrawSelectionElement, - ExcalidrawLinearElement, - Arrowhead, -} from "../element/types"; -import { generateFreeDrawShape } from "../renderer/renderElement"; -import { isTransparent, assertNever } from "../utils"; +import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math"; import { simplify } from "points-on-curve"; + import { ROUGHNESS } from "../constants"; +import { getDiamondPoints, getArrowheadPoints } from "../element"; +import { headingForPointIsHorizontal } from "../element/heading"; import { isElbowArrow, isEmbeddableElement, @@ -21,11 +11,24 @@ import { isIframeLikeElement, isLinearElement, } from "../element/typeChecks"; -import { canChangeRoundness } from "./comparisons"; -import type { EmbedsValidationStatus } from "../types"; -import { pointFrom, pointDistance, type LocalPoint } from "@excalidraw/math"; +import { generateFreeDrawShape } from "../renderer/renderElement"; import { getCornerRadius, isPathALoop } from "../shapes"; -import { headingForPointIsHorizontal } from "../element/heading"; +import { isTransparent, assertNever } from "../utils"; + +import { canChangeRoundness } from "./comparisons"; + +import type { + ExcalidrawElement, + NonDeletedExcalidrawElement, + ExcalidrawSelectionElement, + ExcalidrawLinearElement, + Arrowhead, +} from "../element/types"; +import type { EmbedsValidationStatus } from "../types"; +import type { ElementShapes } from "./types"; +import type { Drawable, Options } from "roughjs/bin/core"; +import type { RoughGenerator } from "roughjs/bin/generator"; +import type { Point as RoughPoint } from "roughjs/bin/geometry"; const getDashArrayDashed = (strokeWidth: number) => [8, 8 + strokeWidth]; diff --git a/packages/excalidraw/scene/ShapeCache.ts b/packages/excalidraw/scene/ShapeCache.ts index 39d388a7b..c170b0a80 100644 --- a/packages/excalidraw/scene/ShapeCache.ts +++ b/packages/excalidraw/scene/ShapeCache.ts @@ -1,14 +1,17 @@ -import type { Drawable } from "roughjs/bin/core"; import { RoughGenerator } from "roughjs/bin/generator"; + +import { COLOR_PALETTE } from "../colors"; +import { elementWithCanvasCache } from "../renderer/renderElement"; + +import { _generateElementShape } from "./Shape"; + import type { ExcalidrawElement, ExcalidrawSelectionElement, } from "../element/types"; -import { elementWithCanvasCache } from "../renderer/renderElement"; -import { _generateElementShape } from "./Shape"; -import type { ElementShape, ElementShapes } from "./types"; -import { COLOR_PALETTE } from "../colors"; import type { AppState, EmbedsValidationStatus } from "../types"; +import type { ElementShape, ElementShapes } from "./types"; +import type { Drawable } from "roughjs/bin/core"; export class ShapeCache { private static rg = new RoughGenerator(); diff --git a/packages/excalidraw/scene/export.ts b/packages/excalidraw/scene/export.ts index 7b3325690..8ca35de2c 100644 --- a/packages/excalidraw/scene/export.ts +++ b/packages/excalidraw/scene/export.ts @@ -1,16 +1,6 @@ import rough from "roughjs/bin/rough"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, - ExcalidrawTextElement, - NonDeletedExcalidrawElement, - NonDeletedSceneElementsMap, -} from "../element/types"; -import type { Bounds } from "../element/bounds"; -import { getCommonBounds, getElementAbsoluteCoords } from "../element/bounds"; -import { renderSceneToSvg } from "../renderer/staticSvgScene"; -import { arrayToMap, distance, getFontString, toBrandedType } from "../utils"; -import type { AppState, BinaryFiles } from "../types"; + +import { getDefaultAppState } from "../appState"; import { DEFAULT_EXPORT_PADDING, FRAME_STYLE, @@ -21,27 +11,39 @@ import { MIME_TYPES, EXPORT_DATA_TYPES, } from "../constants"; -import { getDefaultAppState } from "../appState"; +import { base64ToString, decode, encode, stringToBase64 } from "../data/encode"; import { serializeAsJSON } from "../data/json"; +import { newTextElement } from "../element"; +import { getCommonBounds, getElementAbsoluteCoords } from "../element/bounds"; import { getInitializedImageElements, updateImageCache, } from "../element/image"; +import { newElementWith } from "../element/mutateElement"; +import { isFrameLikeElement } from "../element/typeChecks"; +import { Fonts } from "../fonts"; +import { syncInvalidIndices } from "../fractionalIndex"; import { getElementsOverlappingFrame, getFrameLikeElements, getFrameLikeTitle, getRootElements, } from "../frame"; -import { newTextElement } from "../element"; -import { type Mutable } from "../utility-types"; -import { newElementWith } from "../element/mutateElement"; -import { isFrameLikeElement } from "../element/typeChecks"; -import type { RenderableElementsMap } from "./types"; -import { syncInvalidIndices } from "../fractionalIndex"; import { renderStaticScene } from "../renderer/staticScene"; -import { Fonts } from "../fonts"; -import { base64ToString, decode, encode, stringToBase64 } from "../data/encode"; +import { renderSceneToSvg } from "../renderer/staticSvgScene"; +import { type Mutable } from "../utility-types"; +import { arrayToMap, distance, getFontString, toBrandedType } from "../utils"; + +import type { RenderableElementsMap } from "./types"; +import type { Bounds } from "../element/bounds"; +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, + ExcalidrawTextElement, + NonDeletedExcalidrawElement, + NonDeletedSceneElementsMap, +} from "../element/types"; +import type { AppState, BinaryFiles } from "../types"; const truncateText = (element: ExcalidrawTextElement, maxWidth: number) => { if (element.width <= maxWidth) { diff --git a/packages/excalidraw/scene/normalize.ts b/packages/excalidraw/scene/normalize.ts index 2a025fc27..0c73c5a8a 100644 --- a/packages/excalidraw/scene/normalize.ts +++ b/packages/excalidraw/scene/normalize.ts @@ -1,5 +1,7 @@ import { clamp, round } from "@excalidraw/math"; + import { MAX_ZOOM, MIN_ZOOM } from "../constants"; + import type { NormalizedZoomValue } from "../types"; export const getNormalizedZoom = (zoom: number): NormalizedZoomValue => { diff --git a/packages/excalidraw/scene/scroll.ts b/packages/excalidraw/scene/scroll.ts index 5d059e5b4..989564eb0 100644 --- a/packages/excalidraw/scene/scroll.ts +++ b/packages/excalidraw/scene/scroll.ts @@ -1,16 +1,16 @@ -import type { AppState, Offsets, PointerCoords, Zoom } from "../types"; -import type { ExcalidrawElement } from "../element/types"; import { getCommonBounds, getClosestElementBounds, getVisibleElements, } from "../element"; - import { sceneCoordsToViewportCoords, viewportCoordsToSceneCoords, } from "../utils"; +import type { ExcalidrawElement } from "../element/types"; +import type { AppState, Offsets, PointerCoords, Zoom } from "../types"; + const isOutsideViewPort = (appState: AppState, cords: Array) => { const [x1, y1, x2, y2] = cords; const { x: viewportX1, y: viewportY1 } = sceneCoordsToViewportCoords( diff --git a/packages/excalidraw/scene/scrollbars.ts b/packages/excalidraw/scene/scrollbars.ts index 70f7033fb..b44d79f2b 100644 --- a/packages/excalidraw/scene/scrollbars.ts +++ b/packages/excalidraw/scene/scrollbars.ts @@ -1,9 +1,10 @@ import { getCommonBounds } from "../element"; +import { getLanguage } from "../i18n"; +import { getGlobalCSSVariable } from "../utils"; + +import type { ExcalidrawElement } from "../element/types"; import type { InteractiveCanvasAppState } from "../types"; import type { ScrollBars } from "./types"; -import { getGlobalCSSVariable } from "../utils"; -import { getLanguage } from "../i18n"; -import type { ExcalidrawElement } from "../element/types"; export const SCROLLBAR_MARGIN = 4; export const SCROLLBAR_WIDTH = 6; diff --git a/packages/excalidraw/scene/selection.ts b/packages/excalidraw/scene/selection.ts index 3ca91cd50..02f8f05e7 100644 --- a/packages/excalidraw/scene/selection.ts +++ b/packages/excalidraw/scene/selection.ts @@ -1,11 +1,5 @@ -import type { - ElementsMap, - ElementsMapOrArray, - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "../element/types"; import { getElementAbsoluteCoords, getElementBounds } from "../element"; -import type { AppState, InteractiveCanvasAppState } from "../types"; +import { isElementInViewport } from "../element/sizeHelpers"; import { isBoundToContainer, isFrameLikeElement } from "../element/typeChecks"; import { elementOverlapsWithFrame, @@ -13,7 +7,14 @@ import { getFrameChildren, } from "../frame"; import { isShallowEqual } from "../utils"; -import { isElementInViewport } from "../element/sizeHelpers"; + +import type { + ElementsMap, + ElementsMapOrArray, + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "../element/types"; +import type { AppState, InteractiveCanvasAppState } from "../types"; /** * Frames and their containing elements are not to be selected at the same time. diff --git a/packages/excalidraw/scene/types.ts b/packages/excalidraw/scene/types.ts index c0bfd1bba..3c198d153 100644 --- a/packages/excalidraw/scene/types.ts +++ b/packages/excalidraw/scene/types.ts @@ -1,5 +1,4 @@ -import type { RoughCanvas } from "roughjs/bin/canvas"; -import type { Drawable } from "roughjs/bin/core"; +import type { UserIdleState } from "../constants"; import type { ExcalidrawElement, NonDeletedElementsMap, @@ -18,7 +17,8 @@ import type { PendingExcalidrawElements, } from "../types"; import type { MakeBrand } from "../utility-types"; -import type { UserIdleState } from "../constants"; +import type { RoughCanvas } from "roughjs/bin/canvas"; +import type { Drawable } from "roughjs/bin/core"; export type RenderableElementsMap = NonDeletedElementsMap & MakeBrand<"RenderableElementsMap">; diff --git a/packages/excalidraw/shapes.tsx b/packages/excalidraw/shapes.tsx index cfd639f2d..b2c391a42 100644 --- a/packages/excalidraw/shapes.tsx +++ b/packages/excalidraw/shapes.tsx @@ -17,6 +17,7 @@ import { getPolygonShape, type GeometricShape, } from "@excalidraw/utils/geometry/shape"; + import { ArrowIcon, DiamondIcon, @@ -36,20 +37,21 @@ import { ROUNDNESS, } from "./constants"; import { getElementAbsoluteCoords } from "./element"; -import type { Bounds } from "./element/bounds"; import { shouldTestInside } from "./element/collision"; import { LinearElementEditor } from "./element/linearElementEditor"; import { getBoundTextElement } from "./element/textElement"; +import { KEYS } from "./keys"; +import { ShapeCache } from "./scene/ShapeCache"; +import { invariant } from "./utils"; + +import type { Bounds } from "./element/bounds"; import type { ElementsMap, ExcalidrawElement, ExcalidrawLinearElement, NonDeleted, } from "./element/types"; -import { KEYS } from "./keys"; -import { ShapeCache } from "./scene/ShapeCache"; import type { NormalizedZoomValue, Zoom } from "./types"; -import { invariant } from "./utils"; export const SHAPES = [ { diff --git a/packages/excalidraw/snapping.ts b/packages/excalidraw/snapping.ts index 1b661516e..7c85f4112 100644 --- a/packages/excalidraw/snapping.ts +++ b/packages/excalidraw/snapping.ts @@ -1,4 +1,3 @@ -import type { InclusiveRange } from "@excalidraw/math"; import { pointFrom, pointRotateRads, @@ -7,26 +6,30 @@ import { rangesOverlap, type GlobalPoint, } from "@excalidraw/math"; + +import type { InclusiveRange } from "@excalidraw/math"; + import { TOOL_TYPE } from "./constants"; -import type { Bounds } from "./element/bounds"; import { getCommonBounds, getDraggedElementsBounds, getElementAbsoluteCoords, } from "./element/bounds"; -import type { MaybeTransformHandleType } from "./element/transformHandles"; import { isBoundToContainer, isFrameLikeElement } from "./element/typeChecks"; -import type { - ElementsMap, - ExcalidrawElement, - NonDeletedExcalidrawElement, -} from "./element/types"; import { getMaximumGroups } from "./groups"; import { KEYS } from "./keys"; import { getSelectedElements, getVisibleAndNonSelectedElements, } from "./scene/selection"; + +import type { Bounds } from "./element/bounds"; +import type { MaybeTransformHandleType } from "./element/transformHandles"; +import type { + ElementsMap, + ExcalidrawElement, + NonDeletedExcalidrawElement, +} from "./element/types"; import type { AppClassProperties, AppState, diff --git a/packages/excalidraw/store.ts b/packages/excalidraw/store.ts index 1343347c4..8b0065884 100644 --- a/packages/excalidraw/store.ts +++ b/packages/excalidraw/store.ts @@ -3,11 +3,12 @@ import { AppStateChange, ElementsChange } from "./change"; import { ENV } from "./constants"; import { newElementWith } from "./element/mutateElement"; import { deepCopyElement } from "./element/newElement"; -import type { OrderedExcalidrawElement } from "./element/types"; import { Emitter } from "./emitter"; +import { isShallowEqual } from "./utils"; + +import type { OrderedExcalidrawElement } from "./element/types"; import type { AppState, ObservedAppState } from "./types"; import type { ValueOf } from "./utility-types"; -import { isShallowEqual } from "./utils"; // hidden non-enumerable property for runtime checks const hiddenObservedAppStateProp = "__observedAppState"; diff --git a/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts b/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts index 9a48d19c4..120dedb7f 100644 --- a/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts +++ b/packages/excalidraw/subset/harfbuzz/harfbuzz-loader.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import binary from "./harfbuzz-wasm"; import bindings from "./harfbuzz-bindings"; +import binary from "./harfbuzz-wasm"; /** * Lazy loads wasm and respective bindings for font subsetting based on the harfbuzzjs. diff --git a/packages/excalidraw/subset/subset-main.ts b/packages/excalidraw/subset/subset-main.ts index afccf0d20..5f39af99c 100644 --- a/packages/excalidraw/subset/subset-main.ts +++ b/packages/excalidraw/subset/subset-main.ts @@ -1,6 +1,6 @@ -import { WorkerPool } from "../workers"; -import { isServerEnv, promiseTry } from "../utils"; import { WorkerInTheMainChunkError, WorkerUrlNotDefinedError } from "../errors"; +import { isServerEnv, promiseTry } from "../utils"; +import { WorkerPool } from "../workers"; import type { Commands } from "./subset-shared.chunk"; diff --git a/packages/excalidraw/subset/subset-shared.chunk.ts b/packages/excalidraw/subset/subset-shared.chunk.ts index b64a3825e..4e4b88424 100644 --- a/packages/excalidraw/subset/subset-shared.chunk.ts +++ b/packages/excalidraw/subset/subset-shared.chunk.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import loadWoff2 from "./woff2/woff2-loader"; import loadHbSubset from "./harfbuzz/harfbuzz-loader"; +import loadWoff2 from "./woff2/woff2-loader"; /** * Shared commands between the main thread and worker threads. diff --git a/packages/excalidraw/subset/woff2/woff2-loader.ts b/packages/excalidraw/subset/woff2/woff2-loader.ts index 446dc9f8b..7d5de3095 100644 --- a/packages/excalidraw/subset/woff2/woff2-loader.ts +++ b/packages/excalidraw/subset/woff2/woff2-loader.ts @@ -7,8 +7,8 @@ * In the future consider separating common utils into a separate shared chunk. */ -import binary from "./woff2-wasm"; import bindings from "./woff2-bindings"; +import binary from "./woff2-wasm"; /** * Lazy loads wasm and respective bindings for woff2 compression and decompression. diff --git a/packages/excalidraw/tests/App.test.tsx b/packages/excalidraw/tests/App.test.tsx index ad62706a5..8b86477f9 100644 --- a/packages/excalidraw/tests/App.test.tsx +++ b/packages/excalidraw/tests/App.test.tsx @@ -1,10 +1,10 @@ import React from "react"; -import * as StaticScene from "../renderer/staticScene"; -import { reseed } from "../random"; -import { render, queryByTestId, unmountComponent } from "../tests/test-utils"; +import { vi } from "vitest"; import { Excalidraw } from "../index"; -import { vi } from "vitest"; +import { reseed } from "../random"; +import * as StaticScene from "../renderer/staticScene"; +import { render, queryByTestId, unmountComponent } from "../tests/test-utils"; const renderStaticScene = vi.spyOn(StaticScene, "renderStaticScene"); diff --git a/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx index 05727a0f4..cedb70487 100644 --- a/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx +++ b/packages/excalidraw/tests/MermaidToExcalidraw.test.tsx @@ -1,9 +1,11 @@ import React from "react"; -import { render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; import { expect } from "vitest"; -import { getTextEditor, updateTextEditor } from "./queries/dom"; + +import { Excalidraw } from "../index"; + import { mockMermaidToExcalidraw } from "./helpers/mocks"; +import { getTextEditor, updateTextEditor } from "./queries/dom"; +import { render, waitFor } from "./test-utils"; mockMermaidToExcalidraw({ mockRef: true, diff --git a/packages/excalidraw/tests/actionStyles.test.tsx b/packages/excalidraw/tests/actionStyles.test.tsx index abe4a7c00..2e60000ad 100644 --- a/packages/excalidraw/tests/actionStyles.test.tsx +++ b/packages/excalidraw/tests/actionStyles.test.tsx @@ -1,4 +1,6 @@ import React from "react"; + +import { copiedStyles } from "../actions/actionStyles"; import { Excalidraw } from "../index"; import { CODES } from "../keys"; import { API } from "../tests/helpers/api"; @@ -10,7 +12,6 @@ import { screen, togglePopover, } from "../tests/test-utils"; -import { copiedStyles } from "../actions/actionStyles"; const { h } = window; diff --git a/packages/excalidraw/tests/align.test.tsx b/packages/excalidraw/tests/align.test.tsx index 47624e8f4..d29e497ec 100644 --- a/packages/excalidraw/tests/align.test.tsx +++ b/packages/excalidraw/tests/align.test.tsx @@ -1,10 +1,5 @@ import React from "react"; -import { act, unmountComponent, render } from "./test-utils"; -import { Excalidraw } from "../index"; -import { defaultLang, setLanguage } from "../i18n"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; + import { actionAlignVerticallyCentered, actionAlignHorizontallyCentered, @@ -14,6 +9,13 @@ import { actionAlignLeft, actionAlignRight, } from "../actions"; +import { defaultLang, setLanguage } from "../i18n"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { act, unmountComponent, render } from "./test-utils"; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/appState.test.tsx b/packages/excalidraw/tests/appState.test.tsx index 4a937cd56..e97c5f3be 100644 --- a/packages/excalidraw/tests/appState.test.tsx +++ b/packages/excalidraw/tests/appState.test.tsx @@ -1,10 +1,13 @@ import React from "react"; -import { fireEvent, queryByTestId, render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; + import { getDefaultAppState } from "../appState"; import { EXPORT_DATA_TYPES, MIME_TYPES } from "../constants"; +import { Excalidraw } from "../index"; + +import { API } from "./helpers/api"; import { Pointer, UI } from "./helpers/ui"; +import { fireEvent, queryByTestId, render, waitFor } from "./test-utils"; + import type { ExcalidrawTextElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/binding.test.tsx b/packages/excalidraw/tests/binding.test.tsx index 905a44e70..1c50062c1 100644 --- a/packages/excalidraw/tests/binding.test.tsx +++ b/packages/excalidraw/tests/binding.test.tsx @@ -1,13 +1,15 @@ -import React from "react"; -import { fireEvent, render } from "./test-utils"; -import { Excalidraw, isLinearElement } from "../index"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { getTransformHandles } from "../element/transformHandles"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; -import { actionWrapTextInContainer } from "../actions/actionBoundText"; -import { arrayToMap } from "../utils"; import { pointFrom } from "@excalidraw/math"; +import React from "react"; + +import { actionWrapTextInContainer } from "../actions/actionBoundText"; +import { getTransformHandles } from "../element/transformHandles"; +import { Excalidraw, isLinearElement } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { fireEvent, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/clipboard.test.tsx b/packages/excalidraw/tests/clipboard.test.tsx index c2c0a5e2d..c7e17f49d 100644 --- a/packages/excalidraw/tests/clipboard.test.tsx +++ b/packages/excalidraw/tests/clipboard.test.tsx @@ -1,22 +1,25 @@ import React from "react"; import { vi } from "vitest"; + +import { createPasteEvent, serializeAsClipboardJSON } from "../clipboard"; +import { getElementBounds } from "../element"; +import { getLineHeightInPx } from "../element/textMeasurements"; +import { getLineHeight } from "../fonts"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; +import { mockMermaidToExcalidraw } from "./helpers/mocks"; +import { Pointer, Keyboard } from "./helpers/ui"; import { render, waitFor, GlobalTestState, unmountComponent, } from "./test-utils"; -import { Pointer, Keyboard } from "./helpers/ui"; -import { Excalidraw } from "../index"; -import { KEYS } from "../keys"; -import { getLineHeightInPx } from "../element/textMeasurements"; -import { getElementBounds } from "../element"; + import type { NormalizedZoomValue } from "../types"; -import { API } from "./helpers/api"; -import { createPasteEvent, serializeAsClipboardJSON } from "../clipboard"; -import { arrayToMap } from "../utils"; -import { mockMermaidToExcalidraw } from "./helpers/mocks"; -import { getLineHeight } from "../fonts"; const { h } = window; diff --git a/packages/excalidraw/tests/contextmenu.test.tsx b/packages/excalidraw/tests/contextmenu.test.tsx index bb3f415f1..7de349516 100644 --- a/packages/excalidraw/tests/contextmenu.test.tsx +++ b/packages/excalidraw/tests/contextmenu.test.tsx @@ -1,4 +1,15 @@ import React from "react"; +import { vi } from "vitest"; + +import { copiedStyles } from "../actions/actionStyles"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as StaticScene from "../renderer/staticScene"; +import { setDateTimeForTests } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; import { render, fireEvent, @@ -12,16 +23,8 @@ import { togglePopover, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import { reseed } from "../random"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; + import type { ShortcutName } from "../actions/shortcuts"; -import { copiedStyles } from "../actions/actionStyles"; -import { API } from "./helpers/api"; -import { setDateTimeForTests } from "../utils"; -import { vi } from "vitest"; import type { ActionName } from "../actions/types"; const checkpoint = (name: string) => { diff --git a/packages/excalidraw/tests/cropElement.test.tsx b/packages/excalidraw/tests/cropElement.test.tsx index a508f5d64..ddc93e3fe 100644 --- a/packages/excalidraw/tests/cropElement.test.tsx +++ b/packages/excalidraw/tests/cropElement.test.tsx @@ -1,15 +1,18 @@ import React from "react"; import { vi } from "vitest"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import type { ExcalidrawImageElement, ImageCrop } from "../element/types"; -import { act, GlobalTestState, render, unmountComponent } from "./test-utils"; + import { Excalidraw, exportToCanvas, exportToSvg } from ".."; -import { API } from "./helpers/api"; -import type { NormalizedZoomValue } from "../types"; -import { KEYS } from "../keys"; -import { duplicateElement } from "../element"; -import { cloneJSON } from "../utils"; import { actionFlipHorizontal, actionFlipVertical } from "../actions"; +import { duplicateElement } from "../element"; +import { KEYS } from "../keys"; +import { cloneJSON } from "../utils"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; +import { act, GlobalTestState, render, unmountComponent } from "./test-utils"; + +import type { ExcalidrawImageElement, ImageCrop } from "../element/types"; +import type { NormalizedZoomValue } from "../types"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/data/reconcile.test.ts b/packages/excalidraw/tests/data/reconcile.test.ts index f0e8105a1..35a33956a 100644 --- a/packages/excalidraw/tests/data/reconcile.test.ts +++ b/packages/excalidraw/tests/data/reconcile.test.ts @@ -1,13 +1,14 @@ -import type { RemoteExcalidrawElement } from "../../data/reconcile"; import { reconcileElements } from "../../data/reconcile"; +import { syncInvalidIndices } from "../../fractionalIndex"; +import { randomInteger } from "../../random"; +import { cloneJSON } from "../../utils"; + +import type { RemoteExcalidrawElement } from "../../data/reconcile"; import type { ExcalidrawElement, OrderedExcalidrawElement, } from "../../element/types"; -import { syncInvalidIndices } from "../../fractionalIndex"; -import { randomInteger } from "../../random"; import type { AppState } from "../../types"; -import { cloneJSON } from "../../utils"; type Id = string; type ElementLike = { diff --git a/packages/excalidraw/tests/data/restore.test.ts b/packages/excalidraw/tests/data/restore.test.ts index 37a27ac6a..529284358 100644 --- a/packages/excalidraw/tests/data/restore.test.ts +++ b/packages/excalidraw/tests/data/restore.test.ts @@ -1,19 +1,21 @@ +import { pointFrom } from "@excalidraw/math"; +import { vi } from "vitest"; + +import { getDefaultAppState } from "../../appState"; +import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; import * as restore from "../../data/restore"; +import { newElementWith } from "../../element/mutateElement"; +import * as sizeHelpers from "../../element/sizeHelpers"; +import { API } from "../helpers/api"; + +import type { ImportedDataState } from "../../data/types"; import type { ExcalidrawElement, ExcalidrawFreeDrawElement, ExcalidrawLinearElement, ExcalidrawTextElement, } from "../../element/types"; -import * as sizeHelpers from "../../element/sizeHelpers"; -import { API } from "../helpers/api"; -import { getDefaultAppState } from "../../appState"; -import type { ImportedDataState } from "../../data/types"; import type { NormalizedZoomValue } from "../../types"; -import { DEFAULT_SIDEBAR, FONT_FAMILY, ROUNDNESS } from "../../constants"; -import { newElementWith } from "../../element/mutateElement"; -import { vi } from "vitest"; -import { pointFrom } from "@excalidraw/math"; describe("restoreElements", () => { const mockSizeHelper = vi.spyOn(sizeHelpers, "isInvisiblySmallElement"); diff --git a/packages/excalidraw/tests/dragCreate.test.tsx b/packages/excalidraw/tests/dragCreate.test.tsx index 743ba7947..ecdfbcb64 100644 --- a/packages/excalidraw/tests/dragCreate.test.tsx +++ b/packages/excalidraw/tests/dragCreate.test.tsx @@ -1,8 +1,12 @@ import React from "react"; +import { vi } from "vitest"; + import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveScene from "../renderer/interactiveScene"; import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveScene from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + import { render, fireEvent, @@ -10,9 +14,8 @@ import { restoreOriginalGetBoundingClientRect, unmountComponent, } from "./test-utils"; + import type { ExcalidrawLinearElement } from "../element/types"; -import { reseed } from "../random"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/elementLocking.test.tsx b/packages/excalidraw/tests/elementLocking.test.tsx index 281c26892..a1ca14683 100644 --- a/packages/excalidraw/tests/elementLocking.test.tsx +++ b/packages/excalidraw/tests/elementLocking.test.tsx @@ -1,12 +1,13 @@ import React from "react"; + +import { actionSelectAll } from "../actions"; +import { mutateElement } from "../element/mutateElement"; +import { t } from "../i18n"; import { Excalidraw } from "../index"; -import { render, unmountComponent } from "../tests/test-utils"; -import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; import { KEYS } from "../keys"; import { API } from "../tests/helpers/api"; -import { actionSelectAll } from "../actions"; -import { t } from "../i18n"; -import { mutateElement } from "../element/mutateElement"; +import { Keyboard, Pointer, UI } from "../tests/helpers/ui"; +import { render, unmountComponent } from "../tests/test-utils"; unmountComponent(); diff --git a/packages/excalidraw/tests/excalidraw.test.tsx b/packages/excalidraw/tests/excalidraw.test.tsx index 6fbcf2adc..0e33f8167 100644 --- a/packages/excalidraw/tests/excalidraw.test.tsx +++ b/packages/excalidraw/tests/excalidraw.test.tsx @@ -1,10 +1,12 @@ -import React from "react"; -import { fireEvent, GlobalTestState, toggleMenu, render } from "./test-utils"; -import { Excalidraw, Footer, MainMenu } from "../index"; import { queryByText, queryByTestId } from "@testing-library/react"; +import React from "react"; +import { useMemo } from "react"; + import { THEME } from "../constants"; import { t } from "../i18n"; -import { useMemo } from "react"; +import { Excalidraw, Footer, MainMenu } from "../index"; + +import { fireEvent, GlobalTestState, toggleMenu, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/export.test.tsx b/packages/excalidraw/tests/export.test.tsx index 3547b2978..c10336271 100644 --- a/packages/excalidraw/tests/export.test.tsx +++ b/packages/excalidraw/tests/export.test.tsx @@ -1,18 +1,21 @@ import React from "react"; -import { render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; + +import { getDefaultAppState } from "../appState"; +import { SVG_NS } from "../constants"; +import { getDataURL } from "../data/blob"; import { encodePngMetadata } from "../data/image"; import { serializeAsJSON } from "../data/json"; +import { Excalidraw } from "../index"; import { decodeSvgBase64Payload, encodeSvgBase64Payload, exportToSvg, } from "../scene/export"; + +import { API } from "./helpers/api"; +import { render, waitFor } from "./test-utils"; + import type { FileId } from "../element/types"; -import { getDataURL } from "../data/blob"; -import { getDefaultAppState } from "../appState"; -import { SVG_NS } from "../constants"; const { h } = window; diff --git a/packages/excalidraw/tests/fitToContent.test.tsx b/packages/excalidraw/tests/fitToContent.test.tsx index a4f03910b..bfd16c4e1 100644 --- a/packages/excalidraw/tests/fitToContent.test.tsx +++ b/packages/excalidraw/tests/fitToContent.test.tsx @@ -1,9 +1,10 @@ import React from "react"; -import { act, render } from "./test-utils"; -import { API } from "./helpers/api"; +import { vi } from "vitest"; import { Excalidraw } from "../index"; -import { vi } from "vitest"; + +import { API } from "./helpers/api"; +import { act, render } from "./test-utils"; const { h } = window; diff --git a/packages/excalidraw/tests/fixtures/diagramFixture.ts b/packages/excalidraw/tests/fixtures/diagramFixture.ts index 72b909af8..a4fdc1560 100644 --- a/packages/excalidraw/tests/fixtures/diagramFixture.ts +++ b/packages/excalidraw/tests/fixtures/diagramFixture.ts @@ -1,4 +1,5 @@ import { VERSIONS } from "../../constants"; + import { diamondFixture, ellipseFixture, diff --git a/packages/excalidraw/tests/fixtures/elementFixture.ts b/packages/excalidraw/tests/fixtures/elementFixture.ts index f0470ec86..a7d8c5080 100644 --- a/packages/excalidraw/tests/fixtures/elementFixture.ts +++ b/packages/excalidraw/tests/fixtures/elementFixture.ts @@ -1,5 +1,7 @@ import type { Radians } from "@excalidraw/math"; + import { DEFAULT_FONT_FAMILY } from "../../constants"; + import type { ExcalidrawElement } from "../../element/types"; const elementBase: Omit = { diff --git a/packages/excalidraw/tests/flip.test.tsx b/packages/excalidraw/tests/flip.test.tsx index e3f44b333..9d9f68611 100644 --- a/packages/excalidraw/tests/flip.test.tsx +++ b/packages/excalidraw/tests/flip.test.tsx @@ -1,4 +1,21 @@ +import { pointFrom, type Radians } from "@excalidraw/math"; import React from "react"; +import { vi } from "vitest"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { actionFlipHorizontal, actionFlipVertical } from "../actions"; +import { createPasteEvent } from "../clipboard"; +import { ROUNDNESS } from "../constants"; +import { getElementAbsoluteCoords } from "../element"; +import { newLinearElement } from "../element"; +import { getBoundTextElementPosition } from "../element/textElement"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { arrayToMap, cloneJSON } from "../utils"; + +import { API } from "./helpers/api"; +import { UI, Pointer, Keyboard } from "./helpers/ui"; import { fireEvent, GlobalTestState, @@ -7,10 +24,7 @@ import { unmountComponent, waitFor, } from "./test-utils"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { actionFlipHorizontal, actionFlipVertical } from "../actions"; -import { getElementAbsoluteCoords } from "../element"; + import type { ExcalidrawElement, ExcalidrawImageElement, @@ -18,17 +32,7 @@ import type { ExcalidrawTextElementWithContainer, FileId, } from "../element/types"; -import { newLinearElement } from "../element"; -import { Excalidraw } from "../index"; import type { NormalizedZoomValue } from "../types"; -import { ROUNDNESS } from "../constants"; -import { vi } from "vitest"; -import { KEYS } from "../keys"; -import { getBoundTextElementPosition } from "../element/textElement"; -import { createPasteEvent } from "../clipboard"; -import { arrayToMap, cloneJSON } from "../utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom, type Radians } from "@excalidraw/math"; const { h } = window; const mouse = new Pointer("mouse"); diff --git a/packages/excalidraw/tests/fractionalIndex.test.ts b/packages/excalidraw/tests/fractionalIndex.test.ts index b57af016b..dbd55bd92 100644 --- a/packages/excalidraw/tests/fractionalIndex.test.ts +++ b/packages/excalidraw/tests/fractionalIndex.test.ts @@ -1,15 +1,18 @@ /* eslint-disable no-lone-blocks */ +import { generateKeyBetween } from "fractional-indexing"; + +import { deepCopyElement } from "../element/newElement"; +import { InvalidFractionalIndexError } from "../errors"; import { syncInvalidIndices, syncMovedIndices, validateFractionalIndices, } from "../fractionalIndex"; -import { API } from "./helpers/api"; import { arrayToMap } from "../utils"; -import { InvalidFractionalIndexError } from "../errors"; + +import { API } from "./helpers/api"; + import type { ExcalidrawElement, FractionalIndex } from "../element/types"; -import { deepCopyElement } from "../element/newElement"; -import { generateKeyBetween } from "fractional-indexing"; describe("sync invalid indices with array order", () => { describe("should NOT sync empty array", () => { diff --git a/packages/excalidraw/tests/helpers/api.ts b/packages/excalidraw/tests/helpers/api.ts index 218f37116..2aa9ee999 100644 --- a/packages/excalidraw/tests/helpers/api.ts +++ b/packages/excalidraw/tests/helpers/api.ts @@ -1,3 +1,32 @@ +import fs from "fs"; +import path from "path"; +import util from "util"; + +import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; + +import { getDefaultAppState } from "../../appState"; +import { createTestHook } from "../../components/App"; +import { DEFAULT_VERTICAL_ALIGN, ROUNDNESS } from "../../constants"; +import { getMimeType } from "../../data/blob"; +import { newElement, newTextElement, newLinearElement } from "../../element"; +import { mutateElement } from "../../element/mutateElement"; +import { + newArrowElement, + newEmbeddableElement, + newFrameElement, + newFreeDrawElement, + newIframeElement, + newImageElement, + newMagicFrameElement, +} from "../../element/newElement"; +import { isLinearElementType } from "../../element/typeChecks"; +import { selectGroupsForSelectedElements } from "../../groups"; +import { getSelectedElements } from "../../scene/selection"; +import { assertNever } from "../../utils"; +import { GlobalTestState, createEvent, fireEvent, act } from "../test-utils"; + +import type { Action } from "../../actions/types"; +import type App from "../../components/App"; import type { ExcalidrawElement, ExcalidrawGenericElement, @@ -13,34 +42,8 @@ import type { ExcalidrawArrowElement, FixedSegment, } from "../../element/types"; -import { newElement, newTextElement, newLinearElement } from "../../element"; -import { DEFAULT_VERTICAL_ALIGN, ROUNDNESS } from "../../constants"; -import { getDefaultAppState } from "../../appState"; -import { GlobalTestState, createEvent, fireEvent, act } from "../test-utils"; -import fs from "fs"; -import util from "util"; -import path from "path"; -import { getMimeType } from "../../data/blob"; -import { - newArrowElement, - newEmbeddableElement, - newFrameElement, - newFreeDrawElement, - newIframeElement, - newImageElement, - newMagicFrameElement, -} from "../../element/newElement"; import type { AppState } from "../../types"; -import { getSelectedElements } from "../../scene/selection"; -import { isLinearElementType } from "../../element/typeChecks"; import type { Mutable } from "../../utility-types"; -import { assertNever } from "../../utils"; -import type App from "../../components/App"; -import { createTestHook } from "../../components/App"; -import type { Action } from "../../actions/types"; -import { mutateElement } from "../../element/mutateElement"; -import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; -import { selectGroupsForSelectedElements } from "../../groups"; const readFile = util.promisify(fs.readFile); // so that window.h is available when App.tsx is not imported as well. diff --git a/packages/excalidraw/tests/helpers/mocks.ts b/packages/excalidraw/tests/helpers/mocks.ts index a87523ec1..10e1dee2b 100644 --- a/packages/excalidraw/tests/helpers/mocks.ts +++ b/packages/excalidraw/tests/helpers/mocks.ts @@ -1,7 +1,8 @@ -import { vi } from "vitest"; import * as MermaidToExcalidraw from "@excalidraw/mermaid-to-excalidraw"; -import type { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw"; import React from "react"; +import { vi } from "vitest"; + +import type { parseMermaidToExcalidraw } from "@excalidraw/mermaid-to-excalidraw"; export const mockMermaidToExcalidraw = (opts: { parseMermaidToExcalidraw: typeof parseMermaidToExcalidraw; diff --git a/packages/excalidraw/tests/helpers/ui.ts b/packages/excalidraw/tests/helpers/ui.ts index b9b7023c1..a72e3fa74 100644 --- a/packages/excalidraw/tests/helpers/ui.ts +++ b/packages/excalidraw/tests/helpers/ui.ts @@ -1,3 +1,33 @@ +import { pointFrom, pointRotateRads } from "@excalidraw/math"; + +import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; + +import { createTestHook } from "../../components/App"; +import { getCommonBounds, getElementPointsCoords } from "../../element/bounds"; +import { cropElement } from "../../element/cropElement"; +import { mutateElement } from "../../element/mutateElement"; +import { + getTransformHandles, + getTransformHandlesFromCoords, + OMIT_SIDES_FOR_FRAME, + OMIT_SIDES_FOR_MULTIPLE_ELEMENTS, + type TransformHandle, + type TransformHandleDirection, +} from "../../element/transformHandles"; +import { + isLinearElement, + isFreeDrawElement, + isTextElement, + isFrameLikeElement, +} from "../../element/typeChecks"; +import { KEYS } from "../../keys"; +import { arrayToMap } from "../../utils"; +import { getTextEditor } from "../queries/dom"; +import { act, fireEvent, GlobalTestState, screen } from "../test-utils"; + +import { API } from "./api"; + +import type { TransformHandleType } from "../../element/transformHandles"; import type { ExcalidrawElement, ExcalidrawLinearElement, @@ -10,32 +40,6 @@ import type { ExcalidrawTextElementWithContainer, ExcalidrawImageElement, } from "../../element/types"; -import type { TransformHandleType } from "../../element/transformHandles"; -import { - getTransformHandles, - getTransformHandlesFromCoords, - OMIT_SIDES_FOR_FRAME, - OMIT_SIDES_FOR_MULTIPLE_ELEMENTS, - type TransformHandle, - type TransformHandleDirection, -} from "../../element/transformHandles"; -import { KEYS } from "../../keys"; -import { act, fireEvent, GlobalTestState, screen } from "../test-utils"; -import { mutateElement } from "../../element/mutateElement"; -import { API } from "./api"; -import { - isLinearElement, - isFreeDrawElement, - isTextElement, - isFrameLikeElement, -} from "../../element/typeChecks"; -import { getCommonBounds, getElementPointsCoords } from "../../element/bounds"; -import { getTextEditor } from "../queries/dom"; -import { arrayToMap } from "../../utils"; -import { createTestHook } from "../../components/App"; -import type { GlobalPoint, LocalPoint, Radians } from "@excalidraw/math"; -import { pointFrom, pointRotateRads } from "@excalidraw/math"; -import { cropElement } from "../../element/cropElement"; import type { ToolType } from "../../types"; // so that window.h is available when App.tsx is not imported as well. diff --git a/packages/excalidraw/tests/history.test.tsx b/packages/excalidraw/tests/history.test.tsx index ffddec49f..6e7066b90 100644 --- a/packages/excalidraw/tests/history.test.tsx +++ b/packages/excalidraw/tests/history.test.tsx @@ -1,6 +1,43 @@ import React from "react"; +import { + queryByText, + fireEvent, + queryByTestId, + waitFor, +} from "@testing-library/react"; +import { vi } from "vitest"; +import { pointFrom } from "@excalidraw/math"; + +import type { LocalPoint, Radians } from "@excalidraw/math"; + import "../global.d.ts"; +import "../../utils/test-utils"; + +import { + actionSendBackward, + actionBringForward, + actionSendToBack, +} from "../actions"; +import { createUndoAction, createRedoAction } from "../actions/actionHistory"; +import { actionToggleViewMode } from "../actions/actionToggleViewMode"; +import { getDefaultAppState } from "../appState"; +import { HistoryEntry } from "../history"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; import * as StaticScene from "../renderer/staticScene"; +import { EXPORT_DATA_TYPES, MIME_TYPES, ORIG_ID } from "../constants"; +import { Snapshot, CaptureUpdateAction } from "../store"; +import { arrayToMap } from "../utils"; +import { + COLOR_PALETTE, + DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, + DEFAULT_ELEMENT_STROKE_COLOR_INDEX, +} from "../colors"; +import { newElementWith } from "../element/mutateElement"; +import { AppStateChange, ElementsChange } from "../change"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; import { GlobalTestState, act, @@ -9,24 +46,7 @@ import { togglePopover, getCloneByOrigId, } from "./test-utils"; -import "../../utils/test-utils"; -import { Excalidraw } from "../index"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { API } from "./helpers/api"; -import { getDefaultAppState } from "../appState"; -import { fireEvent, queryByTestId, waitFor } from "@testing-library/react"; -import { createUndoAction, createRedoAction } from "../actions/actionHistory"; -import { actionToggleViewMode } from "../actions/actionToggleViewMode"; -import { EXPORT_DATA_TYPES, MIME_TYPES, ORIG_ID } from "../constants"; -import type { AppState } from "../types"; -import { arrayToMap } from "../utils"; -import { - COLOR_PALETTE, - DEFAULT_ELEMENT_BACKGROUND_COLOR_INDEX, - DEFAULT_ELEMENT_STROKE_COLOR_INDEX, -} from "../colors"; -import { KEYS } from "../keys"; -import { newElementWith } from "../element/mutateElement"; + import type { ExcalidrawElbowArrowElement, ExcalidrawFrameElement, @@ -37,18 +57,7 @@ import type { FractionalIndex, SceneElementsMap, } from "../element/types"; -import { - actionSendBackward, - actionBringForward, - actionSendToBack, -} from "../actions"; -import { vi } from "vitest"; -import { queryByText } from "@testing-library/react"; -import { HistoryEntry } from "../history"; -import { AppStateChange, ElementsChange } from "../change"; -import { Snapshot, CaptureUpdateAction } from "../store"; -import type { LocalPoint, Radians } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; +import type { AppState } from "../types"; const { h } = window; diff --git a/packages/excalidraw/tests/library.test.tsx b/packages/excalidraw/tests/library.test.tsx index 7b48407b7..b084d835b 100644 --- a/packages/excalidraw/tests/library.test.tsx +++ b/packages/excalidraw/tests/library.test.tsx @@ -1,18 +1,20 @@ +import { act, queryByTestId } from "@testing-library/react"; import React from "react"; import { vi } from "vitest"; -import { fireEvent, getCloneByOrigId, render, waitFor } from "./test-utils"; -import { act, queryByTestId } from "@testing-library/react"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; import { MIME_TYPES, ORIG_ID } from "../constants"; -import type { LibraryItem, LibraryItems } from "../types"; -import { UI } from "./helpers/ui"; +import { parseLibraryJSON } from "../data/blob"; import { serializeLibraryAsJSON } from "../data/json"; import { distributeLibraryItemsOnSquareGrid } from "../data/library"; -import type { ExcalidrawGenericElement } from "../element/types"; import { getCommonBoundingBox } from "../element/bounds"; -import { parseLibraryJSON } from "../data/blob"; +import { Excalidraw } from "../index"; + +import { API } from "./helpers/api"; +import { UI } from "./helpers/ui"; +import { fireEvent, getCloneByOrigId, render, waitFor } from "./test-utils"; + +import type { ExcalidrawGenericElement } from "../element/types"; +import type { LibraryItem, LibraryItems } from "../types"; const { h } = window; diff --git a/packages/excalidraw/tests/linearElementEditor.test.tsx b/packages/excalidraw/tests/linearElementEditor.test.tsx index 98d6058c2..162dbb3f0 100644 --- a/packages/excalidraw/tests/linearElementEditor.test.tsx +++ b/packages/excalidraw/tests/linearElementEditor.test.tsx @@ -1,14 +1,25 @@ +import { pointCenter, pointFrom } from "@excalidraw/math"; +import { act, queryByTestId, queryByText } from "@testing-library/react"; import React from "react"; -import type { - ExcalidrawElement, - ExcalidrawLinearElement, - ExcalidrawTextElementWithContainer, - FontString, -} from "../element/types"; +import { vi } from "vitest"; + +import type { GlobalPoint } from "@excalidraw/math"; + +import { ROUNDNESS, VERTICAL_ALIGN } from "../constants"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { + getBoundTextElementPosition, + getBoundTextMaxWidth, +} from "../element/textElement"; +import * as textElementUtils from "../element/textElement"; +import { wrapText } from "../element/textWrapping"; import { Excalidraw, mutateElement } from "../index"; +import { KEYS } from "../keys"; import { reseed } from "../random"; -import * as StaticScene from "../renderer/staticScene"; import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; +import { API } from "../tests/helpers/api"; +import { arrayToMap } from "../utils"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { @@ -18,21 +29,13 @@ import { GlobalTestState, unmountComponent, } from "./test-utils"; -import { API } from "../tests/helpers/api"; -import { KEYS } from "../keys"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { act, queryByTestId, queryByText } from "@testing-library/react"; -import { - getBoundTextElementPosition, - getBoundTextMaxWidth, -} from "../element/textElement"; -import * as textElementUtils from "../element/textElement"; -import { ROUNDNESS, VERTICAL_ALIGN } from "../constants"; -import { vi } from "vitest"; -import { arrayToMap } from "../utils"; -import type { GlobalPoint } from "@excalidraw/math"; -import { pointCenter, pointFrom } from "@excalidraw/math"; -import { wrapText } from "../element/textWrapping"; + +import type { + ExcalidrawElement, + ExcalidrawLinearElement, + ExcalidrawTextElementWithContainer, + FontString, +} from "../element/types"; const renderInteractiveScene = vi.spyOn( InteractiveCanvas, diff --git a/packages/excalidraw/tests/move.test.tsx b/packages/excalidraw/tests/move.test.tsx index 528f9554d..855496f44 100644 --- a/packages/excalidraw/tests/move.test.tsx +++ b/packages/excalidraw/tests/move.test.tsx @@ -1,19 +1,22 @@ import React from "react"; +import { vi } from "vitest"; + import "../../utils/test-utils"; -import { render, fireEvent, act, unmountComponent } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { reseed } from "../random"; import { bindOrUnbindLinearElement } from "../element/binding"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + +import { UI, Pointer, Keyboard } from "./helpers/ui"; +import { render, fireEvent, act, unmountComponent } from "./test-utils"; + import type { ExcalidrawLinearElement, NonDeleted, ExcalidrawRectangleElement, } from "../element/types"; -import { UI, Pointer, Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; -import { vi } from "vitest"; import type Scene from "../scene/Scene"; unmountComponent(); diff --git a/packages/excalidraw/tests/multiPointCreate.test.tsx b/packages/excalidraw/tests/multiPointCreate.test.tsx index df94eb9da..5cbce4966 100644 --- a/packages/excalidraw/tests/multiPointCreate.test.tsx +++ b/packages/excalidraw/tests/multiPointCreate.test.tsx @@ -1,4 +1,12 @@ import React from "react"; +import { vi } from "vitest"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; + import { render, fireEvent, @@ -6,13 +14,8 @@ import { restoreOriginalGetBoundingClientRect, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { KEYS } from "../keys"; + import type { ExcalidrawLinearElement } from "../element/types"; -import { reseed } from "../random"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/packages/events.test.tsx b/packages/excalidraw/tests/packages/events.test.tsx index ad8b3c6d9..3e79239c8 100644 --- a/packages/excalidraw/tests/packages/events.test.tsx +++ b/packages/excalidraw/tests/packages/events.test.tsx @@ -1,11 +1,13 @@ import React from "react"; import { vi } from "vitest"; + import { Excalidraw, CaptureUpdateAction } from "../../index"; -import type { ExcalidrawImperativeAPI } from "../../types"; import { resolvablePromise } from "../../utils"; -import { render } from "../test-utils"; -import { Pointer } from "../helpers/ui"; import { API } from "../helpers/api"; +import { Pointer } from "../helpers/ui"; +import { render } from "../test-utils"; + +import type { ExcalidrawImperativeAPI } from "../../types"; describe("event callbacks", () => { const h = window.h; diff --git a/packages/excalidraw/tests/queries/toolQueries.ts b/packages/excalidraw/tests/queries/toolQueries.ts index df0afa117..ed168735d 100644 --- a/packages/excalidraw/tests/queries/toolQueries.ts +++ b/packages/excalidraw/tests/queries/toolQueries.ts @@ -1,7 +1,9 @@ import { queries, buildQueries } from "@testing-library/react"; -import type { ToolType } from "../../types"; + import { TOOL_TYPE } from "../../constants"; +import type { ToolType } from "../../types"; + const _getAllByToolName = (container: HTMLElement, tool: ToolType | "lock") => { const toolTitle = tool === "lock" ? "lock" : TOOL_TYPE[tool]; return queries.getAllByTestId(container, `toolbar-${toolTitle}`); diff --git a/packages/excalidraw/tests/regressionTests.test.tsx b/packages/excalidraw/tests/regressionTests.test.tsx index a3e45bca6..8407f0766 100644 --- a/packages/excalidraw/tests/regressionTests.test.tsx +++ b/packages/excalidraw/tests/regressionTests.test.tsx @@ -1,10 +1,13 @@ import React from "react"; -import type { ExcalidrawElement } from "../element/types"; -import { CODES, KEYS } from "../keys"; +import { vi } from "vitest"; + +import { FONT_FAMILY } from "../constants"; import { Excalidraw } from "../index"; +import { CODES, KEYS } from "../keys"; import { reseed } from "../random"; import * as StaticScene from "../renderer/staticScene"; import { setDateTimeForTests } from "../utils"; + import { API } from "./helpers/api"; import { Keyboard, Pointer, UI } from "./helpers/ui"; import { @@ -15,8 +18,8 @@ import { togglePopover, unmountComponent, } from "./test-utils"; -import { FONT_FAMILY } from "../constants"; -import { vi } from "vitest"; + +import type { ExcalidrawElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/resize.test.tsx b/packages/excalidraw/tests/resize.test.tsx index 3ebd8cf81..055b097b3 100644 --- a/packages/excalidraw/tests/resize.test.tsx +++ b/packages/excalidraw/tests/resize.test.tsx @@ -1,24 +1,28 @@ +import { pointFrom } from "@excalidraw/math"; import React from "react"; -import { render, unmountComponent } from "./test-utils"; + +import type { LocalPoint } from "@excalidraw/math"; + +import { getElementPointsCoords } from "../element/bounds"; +import { LinearElementEditor } from "../element/linearElementEditor"; +import { resizeSingleElement } from "../element/resizeElements"; +import { isLinearElement } from "../element/typeChecks"; +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { getSizeFromPoints } from "../points"; import { reseed } from "../random"; +import { arrayToMap } from "../utils"; + +import { API } from "./helpers/api"; import { UI, Keyboard, Pointer } from "./helpers/ui"; +import { render, unmountComponent } from "./test-utils"; + +import type { Bounds } from "../element/bounds"; import type { ExcalidrawElbowArrowElement, ExcalidrawFreeDrawElement, ExcalidrawLinearElement, } from "../element/types"; -import type { Bounds } from "../element/bounds"; -import { getElementPointsCoords } from "../element/bounds"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; -import { KEYS } from "../keys"; -import { isLinearElement } from "../element/typeChecks"; -import { LinearElementEditor } from "../element/linearElementEditor"; -import { arrayToMap } from "../utils"; -import type { LocalPoint } from "@excalidraw/math"; -import { pointFrom } from "@excalidraw/math"; -import { resizeSingleElement } from "../element/resizeElements"; -import { getSizeFromPoints } from "../points"; unmountComponent(); diff --git a/packages/excalidraw/tests/rotate.test.tsx b/packages/excalidraw/tests/rotate.test.tsx index 367313ea9..2c678f45b 100644 --- a/packages/excalidraw/tests/rotate.test.tsx +++ b/packages/excalidraw/tests/rotate.test.tsx @@ -1,10 +1,12 @@ import React from "react"; -import { render, unmountComponent } from "./test-utils"; -import { reseed } from "../random"; -import { UI } from "./helpers/ui"; -import { Excalidraw } from "../index"; import { expect } from "vitest"; +import { Excalidraw } from "../index"; +import { reseed } from "../random"; + +import { UI } from "./helpers/ui"; +import { render, unmountComponent } from "./test-utils"; + unmountComponent(); beforeEach(() => { diff --git a/packages/excalidraw/tests/scene/export.test.ts b/packages/excalidraw/tests/scene/export.test.ts index 6fd8a8b85..43c37eb28 100644 --- a/packages/excalidraw/tests/scene/export.test.ts +++ b/packages/excalidraw/tests/scene/export.test.ts @@ -1,8 +1,7 @@ -import type { - ExcalidrawTextElement, - FractionalIndex, - NonDeletedExcalidrawElement, -} from "../../element/types"; +import { exportToCanvas, exportToSvg } from "@excalidraw/utils"; + +import { FONT_FAMILY, FRAME_STYLE } from "../../constants"; +import { prepareElementsForExport } from "../../data"; import * as exportUtils from "../../scene/export"; import { diamondFixture, @@ -11,9 +10,12 @@ import { textFixture, } from "../fixtures/elementFixture"; import { API } from "../helpers/api"; -import { exportToCanvas, exportToSvg } from "@excalidraw/utils"; -import { FONT_FAMILY, FRAME_STYLE } from "../../constants"; -import { prepareElementsForExport } from "../../data"; + +import type { + ExcalidrawTextElement, + FractionalIndex, + NonDeletedExcalidrawElement, +} from "../../element/types"; describe("exportToSvg", () => { const ELEMENT_HEIGHT = 100; diff --git a/packages/excalidraw/tests/scroll.test.tsx b/packages/excalidraw/tests/scroll.test.tsx index 1a3f80c14..2ccc4546f 100644 --- a/packages/excalidraw/tests/scroll.test.tsx +++ b/packages/excalidraw/tests/scroll.test.tsx @@ -1,14 +1,16 @@ import React from "react"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + +import { API } from "./helpers/api"; +import { Keyboard } from "./helpers/ui"; import { mockBoundingClientRect, render, restoreOriginalGetBoundingClientRect, waitFor, } from "./test-utils"; -import { Excalidraw } from "../index"; -import { API } from "./helpers/api"; -import { Keyboard } from "./helpers/ui"; -import { KEYS } from "../keys"; const { h } = window; diff --git a/packages/excalidraw/tests/search.test.tsx b/packages/excalidraw/tests/search.test.tsx index 68ad65826..d3622d4b1 100644 --- a/packages/excalidraw/tests/search.test.tsx +++ b/packages/excalidraw/tests/search.test.tsx @@ -1,11 +1,14 @@ import React from "react"; -import { act, render, waitFor } from "./test-utils"; -import { Excalidraw } from "../index"; + import { CANVAS_SEARCH_TAB, CLASSES, DEFAULT_SIDEBAR } from "../constants"; -import { Keyboard } from "./helpers/ui"; +import { Excalidraw } from "../index"; import { KEYS } from "../keys"; -import { updateTextEditor } from "./queries/dom"; + import { API } from "./helpers/api"; +import { Keyboard } from "./helpers/ui"; +import { updateTextEditor } from "./queries/dom"; +import { act, render, waitFor } from "./test-utils"; + import type { ExcalidrawTextElement } from "../element/types"; const { h } = window; diff --git a/packages/excalidraw/tests/selection.test.tsx b/packages/excalidraw/tests/selection.test.tsx index 0b1f6e50d..d93d3eff5 100644 --- a/packages/excalidraw/tests/selection.test.tsx +++ b/packages/excalidraw/tests/selection.test.tsx @@ -1,4 +1,15 @@ import React from "react"; +import { vi } from "vitest"; + +import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; +import { reseed } from "../random"; +import * as InteractiveCanvas from "../renderer/interactiveScene"; +import * as StaticScene from "../renderer/staticScene"; +import { SHAPES } from "../shapes"; + +import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; import { render, fireEvent, @@ -7,15 +18,6 @@ import { assertSelectedElements, unmountComponent, } from "./test-utils"; -import { Excalidraw } from "../index"; -import * as StaticScene from "../renderer/staticScene"; -import * as InteractiveCanvas from "../renderer/interactiveScene"; -import { KEYS } from "../keys"; -import { reseed } from "../random"; -import { API } from "./helpers/api"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { SHAPES } from "../shapes"; -import { vi } from "vitest"; unmountComponent(); diff --git a/packages/excalidraw/tests/shortcuts.test.tsx b/packages/excalidraw/tests/shortcuts.test.tsx index e02ed0193..ee2234ecc 100644 --- a/packages/excalidraw/tests/shortcuts.test.tsx +++ b/packages/excalidraw/tests/shortcuts.test.tsx @@ -1,6 +1,8 @@ import React from "react"; -import { KEYS } from "../keys"; + import { Excalidraw } from "../index"; +import { KEYS } from "../keys"; + import { API } from "./helpers/api"; import { Keyboard } from "./helpers/ui"; import { fireEvent, render, waitFor } from "./test-utils"; diff --git a/packages/excalidraw/tests/test-utils.ts b/packages/excalidraw/tests/test-utils.ts index 84936f520..73b340982 100644 --- a/packages/excalidraw/tests/test-utils.ts +++ b/packages/excalidraw/tests/test-utils.ts @@ -1,6 +1,4 @@ import "pepjs"; - -import type { RenderResult, RenderOptions } from "@testing-library/react"; import { act } from "@testing-library/react"; import { render, @@ -9,16 +7,20 @@ import { fireEvent, cleanup, } from "@testing-library/react"; - -import * as toolQueries from "./queries/toolQueries"; -import type { ImportedDataState } from "../data/types"; -import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants"; -import { getSelectedElements } from "../scene/selection"; -import type { ExcalidrawElement } from "../element/types"; -import { UI } from "./helpers/ui"; import ansi from "ansicolor"; + +import { STORAGE_KEYS } from "../../../excalidraw-app/app_constants"; import { ORIG_ID } from "../constants"; +import { getSelectedElements } from "../scene/selection"; import { arrayToMap } from "../utils"; + +import { UI } from "./helpers/ui"; +import * as toolQueries from "./queries/toolQueries"; + +import type { RenderResult, RenderOptions } from "@testing-library/react"; + +import type { ImportedDataState } from "../data/types"; +import type { ExcalidrawElement } from "../element/types"; import type { AllPossibleKeys } from "../utility-types"; export { cleanup as unmountComponent }; diff --git a/packages/excalidraw/tests/tool.test.tsx b/packages/excalidraw/tests/tool.test.tsx index 662c61baa..f70d1ccdd 100644 --- a/packages/excalidraw/tests/tool.test.tsx +++ b/packages/excalidraw/tests/tool.test.tsx @@ -1,9 +1,12 @@ import React from "react"; + import { Excalidraw } from "../index"; -import type { ExcalidrawImperativeAPI } from "../types"; import { resolvablePromise } from "../utils"; -import { act, render } from "./test-utils"; + import { Pointer } from "./helpers/ui"; +import { act, render } from "./test-utils"; + +import type { ExcalidrawImperativeAPI } from "../types"; describe("setActiveTool()", () => { const h = window.h; diff --git a/packages/excalidraw/tests/viewMode.test.tsx b/packages/excalidraw/tests/viewMode.test.tsx index 66eca8c7f..c190ee0e3 100644 --- a/packages/excalidraw/tests/viewMode.test.tsx +++ b/packages/excalidraw/tests/viewMode.test.tsx @@ -1,10 +1,12 @@ import React from "react"; -import { render, GlobalTestState } from "./test-utils"; + +import { CURSOR_TYPE } from "../constants"; import { Excalidraw } from "../index"; import { KEYS } from "../keys"; -import { Keyboard, Pointer, UI } from "./helpers/ui"; -import { CURSOR_TYPE } from "../constants"; + import { API } from "./helpers/api"; +import { Keyboard, Pointer, UI } from "./helpers/ui"; +import { render, GlobalTestState } from "./test-utils"; const mouse = new Pointer("mouse"); const touch = new Pointer("touch"); diff --git a/packages/excalidraw/tests/zindex.test.tsx b/packages/excalidraw/tests/zindex.test.tsx index f15d55931..c8e166aff 100644 --- a/packages/excalidraw/tests/zindex.test.tsx +++ b/packages/excalidraw/tests/zindex.test.tsx @@ -1,7 +1,5 @@ import React from "react"; -import { act, getCloneByOrigId, render, unmountComponent } from "./test-utils"; -import { Excalidraw } from "../index"; -import { reseed } from "../random"; + import { actionSendBackward, actionBringForward, @@ -9,14 +7,19 @@ import { actionSendToBack, actionDuplicateSelection, } from "../actions"; -import type { AppState } from "../types"; -import { API } from "./helpers/api"; import { selectGroupsForSelectedElements } from "../groups"; +import { Excalidraw } from "../index"; +import { reseed } from "../random"; + +import { API } from "./helpers/api"; +import { act, getCloneByOrigId, render, unmountComponent } from "./test-utils"; + import type { ExcalidrawElement, ExcalidrawFrameElement, ExcalidrawSelectionElement, } from "../element/types"; +import type { AppState } from "../types"; unmountComponent(); diff --git a/packages/excalidraw/types.ts b/packages/excalidraw/types.ts index 0562736cd..64c0ac298 100644 --- a/packages/excalidraw/types.ts +++ b/packages/excalidraw/types.ts @@ -1,5 +1,19 @@ -import type { JSX } from "react"; -import type React from "react"; +import type { Action } from "./actions/types"; +import type { Spreadsheet } from "./charts"; +import type { ClipboardData } from "./clipboard"; +import type App from "./components/App"; +import type Library from "./data/library"; +import type { FileSystemHandle } from "./data/filesystem"; +import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants"; +import type { ContextMenuItems } from "./components/ContextMenu"; +import type { SnapLine } from "./snapping"; +import type { Merge, MaybePromise, ValueOf, MakeBrand } from "./utility-types"; +import type { CaptureUpdateActionType } from "./store"; +import type { UserIdleState } from "./constants"; +import type { ImportedDataState } from "./data/types"; +import type { SuggestedBinding } from "./element/binding"; +import type { LinearElementEditor } from "./element/linearElementEditor"; +import type { MaybeTransformHandleType } from "./element/transformHandles"; import type { PointerType, ExcalidrawLinearElement, @@ -24,25 +38,11 @@ import type { OrderedExcalidrawElement, ExcalidrawNonSelectionElement, } from "./element/types"; -import type { Action } from "./actions/types"; -import type { LinearElementEditor } from "./element/linearElementEditor"; -import type { SuggestedBinding } from "./element/binding"; -import type { ImportedDataState } from "./data/types"; -import type App from "./components/App"; -import type { throttleRAF } from "./utils"; -import type { Spreadsheet } from "./charts"; import type { Language } from "./i18n"; -import type { ClipboardData } from "./clipboard"; import type { isOverScrollBars } from "./scene/scrollbars"; -import type { MaybeTransformHandleType } from "./element/transformHandles"; -import type Library from "./data/library"; -import type { FileSystemHandle } from "./data/filesystem"; -import type { IMAGE_MIME_TYPES, MIME_TYPES } from "./constants"; -import type { ContextMenuItems } from "./components/ContextMenu"; -import type { SnapLine } from "./snapping"; -import type { Merge, MaybePromise, ValueOf, MakeBrand } from "./utility-types"; -import type { CaptureUpdateActionType } from "./store"; -import type { UserIdleState } from "./constants"; +import type { throttleRAF } from "./utils"; +import type React from "react"; +import type { JSX } from "react"; export type SocketId = string & { _brand: "SocketId" }; diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index e3e18eb93..84f6637f1 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -1,7 +1,7 @@ -import Pool from "es6-promise-pool"; import { average } from "@excalidraw/math"; +import Pool from "es6-promise-pool"; + import { COLOR_PALETTE } from "./colors"; -import type { EVENT } from "./constants"; import { DEFAULT_VERSION, FONT_FAMILY, @@ -9,6 +9,8 @@ import { isDarwin, WINDOWS_EMOJI_FALLBACK_FONT, } from "./constants"; + +import type { EVENT } from "./constants"; import type { ExcalidrawBindableElement, FontFamilyValues, diff --git a/packages/excalidraw/visualdebug.ts b/packages/excalidraw/visualdebug.ts index 862f2cf20..6b7014864 100644 --- a/packages/excalidraw/visualdebug.ts +++ b/packages/excalidraw/visualdebug.ts @@ -1,4 +1,3 @@ -import type { Curve } from "@excalidraw/math"; import { isLineSegment, lineSegment, @@ -6,10 +5,14 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + +import type { Curve } from "@excalidraw/math"; import type { LineSegment } from "@excalidraw/utils"; -import type { Bounds } from "./element/bounds"; + import { isBounds } from "./element/typeChecks"; +import type { Bounds } from "./element/bounds"; + // The global data holder to collect the debug operations declare global { interface Window { diff --git a/packages/excalidraw/zindex.ts b/packages/excalidraw/zindex.ts index 1118ed533..8ffcec5d1 100644 --- a/packages/excalidraw/zindex.ts +++ b/packages/excalidraw/zindex.ts @@ -1,15 +1,16 @@ import { isFrameLikeElement } from "./element/typeChecks"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, -} from "./element/types"; import { syncMovedIndices } from "./fractionalIndex"; import { getElementsInGroup } from "./groups"; import { getSelectedElements } from "./scene"; import Scene from "./scene/Scene"; -import type { AppState } from "./types"; import { arrayToMap, findIndex, findLastIndex } from "./utils"; +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, +} from "./element/types"; +import type { AppState } from "./types"; + const isOfTargetFrame = (element: ExcalidrawElement, frameId: string) => { return element.frameId === frameId || element.id === frameId; }; diff --git a/packages/math/angle.ts b/packages/math/angle.ts index 8d473cf55..353dc5dad 100644 --- a/packages/math/angle.ts +++ b/packages/math/angle.ts @@ -1,3 +1,5 @@ +import { PRECISION } from "./utils"; + import type { Degrees, GlobalPoint, @@ -5,7 +7,6 @@ import type { PolarCoords, Radians, } from "./types"; -import { PRECISION } from "./utils"; // TODO: Simplify with modulo and fix for angles beyond 4*Math.PI and - 4*Math.PI export const normalizeRadians = (angle: Radians): Radians => { diff --git a/packages/math/curve.test.ts b/packages/math/curve.test.ts index 94670d7ab..8d60a7346 100644 --- a/packages/math/curve.test.ts +++ b/packages/math/curve.test.ts @@ -1,4 +1,5 @@ import "../utils/test-utils"; + import { curve, curveClosestPoint, diff --git a/packages/math/curve.ts b/packages/math/curve.ts index 9b275ceec..cd466bbc7 100644 --- a/packages/math/curve.ts +++ b/packages/math/curve.ts @@ -1,7 +1,8 @@ -import type { Bounds } from "../excalidraw/element/bounds"; import { isPoint, pointDistance, pointFrom } from "./point"; import { rectangle, rectangleIntersectLineSegment } from "./rectangle"; + import type { Curve, GlobalPoint, LineSegment, LocalPoint } from "./types"; +import type { Bounds } from "../excalidraw/element/bounds"; /** * diff --git a/packages/math/ellipse.test.ts b/packages/math/ellipse.test.ts index 507cc5a1a..bcaab2a5d 100644 --- a/packages/math/ellipse.test.ts +++ b/packages/math/ellipse.test.ts @@ -8,6 +8,7 @@ import { import { line } from "./line"; import { pointFrom } from "./point"; import { lineSegment } from "./segment"; + import type { Ellipse, GlobalPoint } from "./types"; describe("point and ellipse", () => { diff --git a/packages/math/ellipse.ts b/packages/math/ellipse.ts index c32def0eb..741a77df3 100644 --- a/packages/math/ellipse.ts +++ b/packages/math/ellipse.ts @@ -4,13 +4,6 @@ import { pointFromVector, pointsEqual, } from "./point"; -import type { - Ellipse, - GlobalPoint, - Line, - LineSegment, - LocalPoint, -} from "./types"; import { PRECISION } from "./utils"; import { vector, @@ -20,6 +13,14 @@ import { vectorScale, } from "./vector"; +import type { + Ellipse, + GlobalPoint, + Line, + LineSegment, + LocalPoint, +} from "./types"; + /** * Construct an Ellipse object from the parameters * diff --git a/packages/math/line.ts b/packages/math/line.ts index bcb4f6d90..889fa08ce 100644 --- a/packages/math/line.ts +++ b/packages/math/line.ts @@ -1,4 +1,5 @@ import { pointFrom } from "./point"; + import type { GlobalPoint, Line, LocalPoint } from "./types"; /** diff --git a/packages/math/point.test.ts b/packages/math/point.test.ts index 89cc4f8f3..0ed59ee9a 100644 --- a/packages/math/point.test.ts +++ b/packages/math/point.test.ts @@ -1,4 +1,5 @@ import { pointFrom, pointRotateRads } from "./point"; + import type { Radians } from "./types"; describe("rotate", () => { diff --git a/packages/math/point.ts b/packages/math/point.ts index 92df18773..f6234c8ea 100644 --- a/packages/math/point.ts +++ b/packages/math/point.ts @@ -1,4 +1,7 @@ import { degreesToRadians } from "./angle"; +import { PRECISION } from "./utils"; +import { vectorFromPoint, vectorScale } from "./vector"; + import type { LocalPoint, GlobalPoint, @@ -6,8 +9,6 @@ import type { Degrees, Vector, } from "./types"; -import { PRECISION } from "./utils"; -import { vectorFromPoint, vectorScale } from "./vector"; /** * Create a properly typed Point instance from the X and Y coordinates. diff --git a/packages/math/polygon.ts b/packages/math/polygon.ts index 783bc4cf3..762c82dbf 100644 --- a/packages/math/polygon.ts +++ b/packages/math/polygon.ts @@ -1,8 +1,9 @@ import { pointsEqual } from "./point"; import { lineSegment, pointOnLineSegment } from "./segment"; -import type { GlobalPoint, LocalPoint, Polygon } from "./types"; import { PRECISION } from "./utils"; +import type { GlobalPoint, LocalPoint, Polygon } from "./types"; + export function polygon( ...points: Point[] ) { diff --git a/packages/math/range.ts b/packages/math/range.ts index d90530cba..dee3d7edf 100644 --- a/packages/math/range.ts +++ b/packages/math/range.ts @@ -1,4 +1,5 @@ import { toBrandedType } from "@excalidraw/excalidraw/utils"; + import type { InclusiveRange } from "./types"; /** diff --git a/packages/math/rectangle.ts b/packages/math/rectangle.ts index 7dde15ded..394b5c2f8 100644 --- a/packages/math/rectangle.ts +++ b/packages/math/rectangle.ts @@ -1,5 +1,6 @@ import { pointFrom } from "./point"; import { lineSegment, lineSegmentIntersectionPoints } from "./segment"; + import type { GlobalPoint, LineSegment, LocalPoint, Rectangle } from "./types"; export function rectangle

( diff --git a/packages/math/segment.ts b/packages/math/segment.ts index 60943aacb..e38978b7e 100644 --- a/packages/math/segment.ts +++ b/packages/math/segment.ts @@ -5,7 +5,6 @@ import { pointFromVector, pointRotateRads, } from "./point"; -import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; import { PRECISION } from "./utils"; import { vectorAdd, @@ -15,6 +14,8 @@ import { vectorSubtract, } from "./vector"; +import type { GlobalPoint, LineSegment, LocalPoint, Radians } from "./types"; + /** * Create a line segment from two points. * diff --git a/packages/utils/bbox.ts b/packages/utils/bbox.ts index 19a1a5430..61c75a668 100644 --- a/packages/utils/bbox.ts +++ b/packages/utils/bbox.ts @@ -4,6 +4,7 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; + import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; export type LineSegment

= [P, P]; diff --git a/packages/utils/collision.test.ts b/packages/utils/collision.test.ts index 744bea367..24f96e985 100644 --- a/packages/utils/collision.test.ts +++ b/packages/utils/collision.test.ts @@ -1,4 +1,3 @@ -import type { Curve, Degrees, GlobalPoint } from "@excalidraw/math"; import { curve, degreesToRadians, @@ -7,7 +6,11 @@ import { pointFrom, pointRotateDegs, } from "@excalidraw/math"; + +import type { Curve, Degrees, GlobalPoint } from "@excalidraw/math"; + import { pointOnCurve, pointOnPolyline } from "./collision"; + import type { Polyline } from "./geometry/shape"; describe("point and curve", () => { diff --git a/packages/utils/collision.ts b/packages/utils/collision.ts index fb48f4e45..f90019418 100644 --- a/packages/utils/collision.ts +++ b/packages/utils/collision.ts @@ -1,10 +1,3 @@ -import type { Polycurve, Polyline } from "./geometry/shape"; -import { - pointInEllipse, - pointOnEllipse, - type GeometricShape, -} from "./geometry/shape"; -import type { Curve } from "@excalidraw/math"; import { lineSegment, pointFrom, @@ -17,6 +10,16 @@ import { type Polygon, } from "@excalidraw/math"; +import type { Curve } from "@excalidraw/math"; + +import { + pointInEllipse, + pointOnEllipse, + type GeometricShape, +} from "./geometry/shape"; + +import type { Polycurve, Polyline } from "./geometry/shape"; + // check if the given point is considered on the given shape's border export const isPointOnShape = ( point: Point, diff --git a/packages/utils/export.test.ts b/packages/utils/export.test.ts index e2af763b5..86bbe80b7 100644 --- a/packages/utils/export.test.ts +++ b/packages/utils/export.test.ts @@ -1,9 +1,9 @@ -import * as utils from "."; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import * as mockedSceneExportUtils from "@excalidraw/excalidraw/scene/export"; import { diagramFactory } from "@excalidraw/excalidraw/tests/fixtures/diagramFixture"; import { vi } from "vitest"; -import * as mockedSceneExportUtils from "@excalidraw/excalidraw/scene/export"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import * as utils from "."; const exportToSvgSpy = vi.spyOn(mockedSceneExportUtils, "exportToSvg"); diff --git a/packages/utils/export.ts b/packages/utils/export.ts index 22287ce7e..6de25c62b 100644 --- a/packages/utils/export.ts +++ b/packages/utils/export.ts @@ -1,23 +1,24 @@ -import { - exportToCanvas as _exportToCanvas, - exportToSvg as _exportToSvg, -} from "@excalidraw/excalidraw/scene/export"; import { getDefaultAppState } from "@excalidraw/excalidraw/appState"; -import type { AppState, BinaryFiles } from "@excalidraw/excalidraw/types"; -import type { - ExcalidrawElement, - ExcalidrawFrameLikeElement, - NonDeleted, -} from "@excalidraw/excalidraw/element/types"; -import { restore } from "@excalidraw/excalidraw/data/restore"; -import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; -import { encodePngMetadata } from "@excalidraw/excalidraw/data/image"; -import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; import { copyBlobToClipboardAsPng, copyTextToSystemClipboard, copyToClipboard, } from "@excalidraw/excalidraw/clipboard"; +import { MIME_TYPES } from "@excalidraw/excalidraw/constants"; +import { encodePngMetadata } from "@excalidraw/excalidraw/data/image"; +import { serializeAsJSON } from "@excalidraw/excalidraw/data/json"; +import { restore } from "@excalidraw/excalidraw/data/restore"; +import { + exportToCanvas as _exportToCanvas, + exportToSvg as _exportToSvg, +} from "@excalidraw/excalidraw/scene/export"; + +import type { + ExcalidrawElement, + ExcalidrawFrameLikeElement, + NonDeleted, +} from "@excalidraw/excalidraw/element/types"; +import type { AppState, BinaryFiles } from "@excalidraw/excalidraw/types"; export { MIME_TYPES }; diff --git a/packages/utils/geometry/geometry.test.ts b/packages/utils/geometry/geometry.test.ts index e9ad067fe..6ddab71b0 100644 --- a/packages/utils/geometry/geometry.test.ts +++ b/packages/utils/geometry/geometry.test.ts @@ -1,9 +1,3 @@ -import type { - GlobalPoint, - LineSegment, - Polygon, - Radians, -} from "@excalidraw/math"; import { pointFrom, lineSegment, @@ -13,6 +7,14 @@ import { polygonIncludesPoint, segmentsIntersectAt, } from "@excalidraw/math"; + +import type { + GlobalPoint, + LineSegment, + Polygon, + Radians, +} from "@excalidraw/math"; + import { pointInEllipse, pointOnEllipse, type Ellipse } from "./shape"; describe("point and line", () => { diff --git a/packages/utils/geometry/shape.ts b/packages/utils/geometry/shape.ts index 10fc06e31..ea3cde3f6 100644 --- a/packages/utils/geometry/shape.ts +++ b/packages/utils/geometry/shape.ts @@ -12,7 +12,8 @@ * to pure shapes */ -import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; +import { getElementAbsoluteCoords } from "@excalidraw/excalidraw/element"; +import { invariant } from "@excalidraw/excalidraw/utils"; import { curve, lineSegment, @@ -32,7 +33,8 @@ import { type GlobalPoint, type LocalPoint, } from "@excalidraw/math"; -import { getElementAbsoluteCoords } from "@excalidraw/excalidraw/element"; +import { pointsOnBezierCurves } from "points-on-curve"; + import type { ElementsMap, ExcalidrawBindableElement, @@ -49,9 +51,9 @@ import type { ExcalidrawSelectionElement, ExcalidrawTextElement, } from "@excalidraw/excalidraw/element/types"; -import { pointsOnBezierCurves } from "points-on-curve"; +import type { Curve, LineSegment, Polygon, Radians } from "@excalidraw/math"; + import type { Drawable, Op } from "roughjs/bin/core"; -import { invariant } from "@excalidraw/excalidraw/utils"; // a polyline (made up term here) is a line consisting of other line segments // this corresponds to a straight line element in the editor but it could also diff --git a/packages/utils/utils.unmocked.test.ts b/packages/utils/utils.unmocked.test.ts index 341adef95..417eabda1 100644 --- a/packages/utils/utils.unmocked.test.ts +++ b/packages/utils/utils.unmocked.test.ts @@ -1,8 +1,10 @@ -import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; -import * as utils from "./index"; -import { API } from "@excalidraw/excalidraw/tests/helpers/api"; -import { decodeSvgBase64Payload } from "@excalidraw/excalidraw/scene/export"; import { decodePngMetadata } from "@excalidraw/excalidraw/data/image"; +import { decodeSvgBase64Payload } from "@excalidraw/excalidraw/scene/export"; +import { API } from "@excalidraw/excalidraw/tests/helpers/api"; + +import type { ImportedDataState } from "@excalidraw/excalidraw/data/types"; + +import * as utils from "./index"; // NOTE this test file is using the actual API, unmocked. Hence splitting it // from the other test file, because I couldn't figure out how to test diff --git a/packages/utils/withinBounds.test.ts b/packages/utils/withinBounds.test.ts index 85354d742..b07d0bc33 100644 --- a/packages/utils/withinBounds.test.ts +++ b/packages/utils/withinBounds.test.ts @@ -1,5 +1,7 @@ -import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; import { API } from "@excalidraw/excalidraw/tests/helpers/api"; + +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; + import { elementPartiallyOverlapsWithOrContainsBBox, elementsOverlappingBBox, diff --git a/packages/utils/withinBounds.ts b/packages/utils/withinBounds.ts index 8d52eb3ad..71bc78969 100644 --- a/packages/utils/withinBounds.ts +++ b/packages/utils/withinBounds.ts @@ -1,9 +1,4 @@ -import type { - ExcalidrawElement, - ExcalidrawFreeDrawElement, - ExcalidrawLinearElement, - NonDeletedExcalidrawElement, -} from "@excalidraw/excalidraw/element/types"; +import { getElementBounds } from "@excalidraw/excalidraw/element/bounds"; import { isArrowElement, isExcalidrawElement, @@ -11,10 +6,7 @@ import { isLinearElement, isTextElement, } from "@excalidraw/excalidraw/element/typeChecks"; -import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; -import { getElementBounds } from "@excalidraw/excalidraw/element/bounds"; import { arrayToMap } from "@excalidraw/excalidraw/utils"; -import type { LocalPoint } from "@excalidraw/math"; import { rangeIncludesValue, pointFrom, @@ -22,6 +14,15 @@ import { rangeInclusive, } from "@excalidraw/math"; +import type { Bounds } from "@excalidraw/excalidraw/element/bounds"; +import type { + ExcalidrawElement, + ExcalidrawFreeDrawElement, + ExcalidrawLinearElement, + NonDeletedExcalidrawElement, +} from "@excalidraw/excalidraw/element/types"; +import type { LocalPoint } from "@excalidraw/math"; + type Element = NonDeletedExcalidrawElement; type Elements = readonly NonDeletedExcalidrawElement[]; diff --git a/scripts/autorelease.js b/scripts/autorelease.js index f506cf13c..6ca5af213 100644 --- a/scripts/autorelease.js +++ b/scripts/autorelease.js @@ -1,5 +1,6 @@ -const fs = require("fs"); const { exec, execSync } = require("child_process"); +const fs = require("fs"); + const core = require("@actions/core"); const excalidrawDir = `${__dirname}/../packages/excalidraw`; diff --git a/scripts/buildMath.js b/scripts/buildMath.js index fd2f820ea..ba421b48c 100644 --- a/scripts/buildMath.js +++ b/scripts/buildMath.js @@ -1,4 +1,5 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); diff --git a/scripts/buildPackage.js b/scripts/buildPackage.js index 653af50f2..3dd15eeca 100644 --- a/scripts/buildPackage.js +++ b/scripts/buildPackage.js @@ -1,6 +1,8 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); + const { parseEnvVariables } = require("../packages/excalidraw/env.cjs"); const ENV_VARS = { diff --git a/scripts/buildUtils.js b/scripts/buildUtils.js index 65b947385..b5718f57e 100644 --- a/scripts/buildUtils.js +++ b/scripts/buildUtils.js @@ -1,6 +1,8 @@ const path = require("path"); + const { build } = require("esbuild"); const { sassPlugin } = require("esbuild-sass-plugin"); + const { woff2ServerPlugin } = require("./woff2/woff2-esbuild-plugins"); // contains all dependencies bundled inside diff --git a/scripts/prerelease.js b/scripts/prerelease.js index 3b8080d33..005a6cf5f 100644 --- a/scripts/prerelease.js +++ b/scripts/prerelease.js @@ -1,5 +1,6 @@ const fs = require("fs"); const util = require("util"); + const exec = util.promisify(require("child_process").exec); const updateChangelog = require("./updateChangelog"); diff --git a/scripts/woff2/woff2-esbuild-plugins.js b/scripts/woff2/woff2-esbuild-plugins.js index 19ebafc93..2116dd059 100644 --- a/scripts/woff2/woff2-esbuild-plugins.js +++ b/scripts/woff2/woff2-esbuild-plugins.js @@ -1,9 +1,10 @@ +const { execSync } = require("child_process"); const fs = require("fs"); const path = require("path"); -const { execSync } = require("child_process"); -const which = require("which"); -const wawoff = require("wawoff2"); + const { Font } = require("fonteditor-core"); +const wawoff = require("wawoff2"); +const which = require("which"); /** * Custom esbuild plugin to: diff --git a/setupTests.ts b/setupTests.ts index 20d2cc517..2aec616b4 100644 --- a/setupTests.ts +++ b/setupTests.ts @@ -1,11 +1,13 @@ +import fs from "fs"; + // vitest.setup.ts import "vitest-canvas-mock"; import "@testing-library/jest-dom"; -import fs from "fs"; import { vi } from "vitest"; + import polyfill from "./packages/excalidraw/polyfill"; -import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills"; import { yellow } from "./packages/excalidraw/tests/helpers/colorize"; +import { testPolyfills } from "./packages/excalidraw/tests/helpers/polyfills"; // mock for pep.js not working with setPointerCapture() HTMLElement.prototype.setPointerCapture = vi.fn(); diff --git a/yarn.lock b/yarn.lock index 23e087849..ccd0827fb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5354,7 +5354,7 @@ eslint-plugin-flowtype@^8.0.3: lodash "^4.17.21" string-natural-compare "^3.0.1" -eslint-plugin-import@^2.25.3: +eslint-plugin-import@2.31.0, eslint-plugin-import@^2.25.3: version "2.31.0" resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7" integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A== From 30983d801a12b658d4f6b3ee4bd7471186291c78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Sat, 15 Mar 2025 12:31:25 +0100 Subject: [PATCH 42/51] fix: Arrow conversion regression (#9241) Signed-off-by: Mark Tolmacs --- .../excalidraw/actions/actionProperties.tsx | 91 +++++++++----- packages/excalidraw/element/binding.ts | 116 ++++++++---------- packages/excalidraw/element/elbowArrow.ts | 24 ++-- .../tests/__snapshots__/history.test.tsx.snap | 8 +- 4 files changed, 129 insertions(+), 110 deletions(-) diff --git a/packages/excalidraw/actions/actionProperties.tsx b/packages/excalidraw/actions/actionProperties.tsx index 1e24d9bed..5a7590667 100644 --- a/packages/excalidraw/actions/actionProperties.tsx +++ b/packages/excalidraw/actions/actionProperties.tsx @@ -111,6 +111,8 @@ import { tupleToCoors, } from "../utils"; +import { updateElbowArrowPoints } from "../element/elbowArrow"; + import { register } from "./register"; import type { @@ -1572,7 +1574,7 @@ export const actionChangeArrowType = register({ if (!isArrowElement(el)) { return el; } - const newElement = newElementWith(el, { + let newElement = newElementWith(el, { roundness: value === ARROW_TYPE.round ? { @@ -1587,6 +1589,8 @@ export const actionChangeArrowType = register({ }); if (isElbowArrow(newElement)) { + newElement.fixedSegments = null; + const elementsMap = app.scene.getNonDeletedElementsMap(); app.dismissLinearEditor(); @@ -1661,46 +1665,71 @@ export const actionChangeArrowType = register({ endHoveredElement && bindLinearElement(newElement, endHoveredElement, "end", elementsMap); - mutateElement(newElement, { - points: [finalStartPoint, finalEndPoint].map( - (p): LocalPoint => - pointFrom(p[0] - newElement.x, p[1] - newElement.y), - ), - ...(startElement && newElement.startBinding + const startBinding = + startElement && newElement.startBinding ? { - startBinding: { - // @ts-ignore TS cannot discern check above - ...newElement.startBinding!, - ...calculateFixedPointForElbowArrowBinding( - newElement, - startElement, - "start", - elementsMap, - ), - }, + // @ts-ignore TS cannot discern check above + ...newElement.startBinding!, + ...calculateFixedPointForElbowArrowBinding( + newElement, + startElement, + "start", + elementsMap, + ), } - : {}), - ...(endElement && newElement.endBinding + : null; + const endBinding = + endElement && newElement.endBinding ? { - endBinding: { - // @ts-ignore TS cannot discern check above - ...newElement.endBinding, - ...calculateFixedPointForElbowArrowBinding( - newElement, - endElement, - "end", - elementsMap, - ), - }, + // @ts-ignore TS cannot discern check above + ...newElement.endBinding, + ...calculateFixedPointForElbowArrowBinding( + newElement, + endElement, + "end", + elementsMap, + ), } - : {}), - }); + : null; + + newElement = { + ...newElement, + startBinding, + endBinding, + ...updateElbowArrowPoints(newElement, elementsMap, { + points: [finalStartPoint, finalEndPoint].map( + (p): LocalPoint => + pointFrom(p[0] - newElement.x, p[1] - newElement.y), + ), + startBinding, + endBinding, + fixedSegments: null, + }), + }; LinearElementEditor.updateEditorMidPointsCache( newElement, elementsMap, app.state, ); + } else { + const elementsMap = app.scene.getNonDeletedElementsMap(); + if (newElement.startBinding) { + const startElement = elementsMap.get( + newElement.startBinding.elementId, + ) as ExcalidrawBindableElement; + if (startElement) { + bindLinearElement(newElement, startElement, "start", elementsMap); + } + } + if (newElement.endBinding) { + const endElement = elementsMap.get( + newElement.endBinding.elementId, + ) as ExcalidrawBindableElement; + if (endElement) { + bindLinearElement(newElement, endElement, "end", elementsMap); + } + } } return newElement; diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index fa472d211..93c5292f1 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -487,32 +487,31 @@ export const bindLinearElement = ( return; } - const binding: PointBinding | FixedPointBinding = { + let binding: PointBinding | FixedPointBinding = { elementId: hoveredElement.id, - ...(isElbowArrow(linearElement) - ? { - ...calculateFixedPointForElbowArrowBinding( - linearElement, - hoveredElement, - startOrEnd, - elementsMap, - ), - focus: 0, - gap: 0, - } - : { - ...normalizePointBinding( - calculateFocusAndGap( - linearElement, - hoveredElement, - startOrEnd, - elementsMap, - ), - hoveredElement, - ), - }), + ...normalizePointBinding( + calculateFocusAndGap( + linearElement, + hoveredElement, + startOrEnd, + elementsMap, + ), + hoveredElement, + ), }; + if (isElbowArrow(linearElement)) { + binding = { + ...binding, + ...calculateFixedPointForElbowArrowBinding( + linearElement, + hoveredElement, + startOrEnd, + elementsMap, + ), + }; + } + mutateElement(linearElement, { [startOrEnd === "start" ? "startBinding" : "endBinding"]: binding, }); @@ -1272,39 +1271,35 @@ const updateBoundPoint = ( pointDistance(adjacentPoint, edgePointAbsolute) + pointDistance(adjacentPoint, center) + Math.max(bindableElement.width, bindableElement.height) * 2; - const intersections = intersectElementWithLineSegment( - bindableElement, - lineSegment( - adjacentPoint, - pointFromVector( - vectorScale( - vectorNormalize(vectorFromPoint(focusPointAbsolute, adjacentPoint)), - interceptorLength, - ), + const intersections = [ + ...intersectElementWithLineSegment( + bindableElement, + lineSegment( adjacentPoint, + pointFromVector( + vectorScale( + vectorNormalize( + vectorFromPoint(focusPointAbsolute, adjacentPoint), + ), + interceptorLength, + ), + adjacentPoint, + ), ), + binding.gap, + ).sort( + (g, h) => + pointDistanceSq(g, adjacentPoint) - pointDistanceSq(h, adjacentPoint), ), - binding.gap, - ).sort( - (g, h) => - pointDistanceSq(g, adjacentPoint) - pointDistanceSq(h, adjacentPoint), - ); - - // debugClear(); - // debugDrawPoint(intersections[0], { color: "red", permanent: true }); - // debugDrawLine( - // lineSegment( - // adjacentPoint, - // pointFromVector( - // vectorScale( - // vectorNormalize(vectorFromPoint(focusPointAbsolute, adjacentPoint)), - // interceptorLength, - // ), - // adjacentPoint, - // ), - // ), - // { permanent: true, color: "green" }, - // ); + // Fallback when arrow doesn't point to the shape + pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(focusPointAbsolute, adjacentPoint)), + pointDistance(adjacentPoint, edgePointAbsolute), + ), + adjacentPoint, + ), + ]; if (intersections.length > 1) { // The adjacent point is outside the shape (+ gap) @@ -1727,21 +1722,6 @@ const determineFocusDistance = ( ) .sort((g, h) => Math.abs(g) - Math.abs(h)); - // debugClear(); - // [ - // lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[0]), - // lineSegmentIntersectionPoints(rotatedInterceptor, interceptees[1]), - // ] - // .filter((p): p is GlobalPoint => p !== null) - // .forEach((p) => debugDrawPoint(p, { color: "black", permanent: true })); - // debugDrawPoint(determineFocusPoint(element, ordered[0] ?? 0, rotatedA), { - // color: "red", - // permanent: true, - // }); - // debugDrawLine(rotatedInterceptor, { color: "green", permanent: true }); - // debugDrawLine(interceptees[0], { color: "red", permanent: true }); - // debugDrawLine(interceptees[1], { color: "red", permanent: true }); - const signedDistanceRatio = ordered[0] ?? 0; return signedDistanceRatio; diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 5b8dc3813..5e44b6ea6 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -998,23 +998,32 @@ export const updateElbowArrowPoints = ( // 0. During all element replacement in the scene, we just need to renormalize // the arrow // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed + const { + startBinding: updatedStartBinding, + endBinding: updatedEndBinding, + ...restOfTheUpdates + } = updates; const startBinding = - typeof updates.startBinding !== "undefined" - ? updates.startBinding + typeof updatedStartBinding !== "undefined" + ? updatedStartBinding : arrow.startBinding; const endBinding = - typeof updates.endBinding !== "undefined" - ? updates.endBinding + typeof updatedEndBinding !== "undefined" + ? updatedEndBinding : arrow.endBinding; const startElement = startBinding && getBindableElementForId(startBinding.elementId, elementsMap); const endElement = endBinding && getBindableElementForId(endBinding.elementId, elementsMap); + if ( + (startBinding && !startElement) || + (endBinding && !endElement) || (elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || - startElement?.id !== startBinding?.elementId || - endElement?.id !== endBinding?.elementId + (Object.keys(restOfTheUpdates).length === 0 && + (startElement?.id !== startBinding?.elementId || + endElement?.id !== endBinding?.elementId)) ) { return normalizeArrowElementUpdate( updatedPoints.map((p) => @@ -1074,7 +1083,8 @@ export const updateElbowArrowPoints = ( p, arrow.points[i] ?? pointFrom(Infinity, Infinity), ), - ) + ) && + validateElbowPoints(updatedPoints) ) { return {}; } diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index 165c135fe..d740e975c 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -818,8 +818,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl "type": "arrow", "updated": 1, "version": 30, - "width": 50, - "x": 200, + "width": 0, + "x": "149.29289", "y": 0, } `; @@ -852,7 +852,7 @@ History { 0, ], [ - 50, + 0, 0, ], ], @@ -937,7 +937,7 @@ History { 0, ], [ - 50, + 0, 0, ], ], From 99d8bff1751b0bcfaacd1b0f32689df63ab42f86 Mon Sep 17 00:00:00 2001 From: David Luzar <5153846+dwelle@users.noreply.github.com> Date: Sat, 15 Mar 2025 20:05:42 +0100 Subject: [PATCH 43/51] fix: elements offset incorrectly when action-duplicated during drag (#9275) * fix: elements offset incorrectly when action-duplicated during drag * prevent duplicate action during drag altogether --- .../actions/actionDuplicateSelection.tsx | 4 ++++ packages/excalidraw/element/dragElements.ts | 21 ++++++++++++------- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index ce225a1d6..0125f0288 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -52,6 +52,10 @@ export const actionDuplicateSelection = register({ icon: DuplicateIcon, trackEvent: { category: "element" }, perform: (elements, appState, formData, app) => { + if (appState.selectedElementsAreBeingDragged) { + return false; + } + // duplicate selected point(s) if editing a line if (appState.editingLinearElement) { // TODO: Invariants should be checked here instead of duplicateSelectedPoints() diff --git a/packages/excalidraw/element/dragElements.ts b/packages/excalidraw/element/dragElements.ts index 4cc408b21..e3a6a48b3 100644 --- a/packages/excalidraw/element/dragElements.ts +++ b/packages/excalidraw/element/dragElements.ts @@ -17,7 +17,7 @@ import { } from "./typeChecks"; import type { Bounds } from "./bounds"; -import type { NonDeletedExcalidrawElement } from "./types"; +import type { ExcalidrawElement, NonDeletedExcalidrawElement } from "./types"; import type Scene from "../scene/Scene"; import type { AppState, @@ -78,13 +78,20 @@ export const dragSelectedElements = ( } } - const commonBounds = getCommonBounds( - Array.from(elementsToUpdate).map( - (el) => pointerDownState.originalElements.get(el.id) ?? el, - ), - ); + const origElements: ExcalidrawElement[] = []; + + for (const element of elementsToUpdate) { + const origElement = pointerDownState.originalElements.get(element.id); + // if original element is not set (e.g. when you duplicate during a drag + // operation), exit to avoid undefined behavior + if (!origElement) { + return; + } + origElements.push(origElement); + } + const adjustedOffset = calculateOffset( - commonBounds, + getCommonBounds(origElements), offset, snapOffset, gridSize, From 58990b41ae3f2339e5bb2616f870d79e3f8d6463 Mon Sep 17 00:00:00 2001 From: WalterMitty Date: Sat, 22 Mar 2025 17:06:23 +0800 Subject: [PATCH 44/51] fix: 'Rotate' spell error (#9288) --- packages/math/point.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/math/point.ts b/packages/math/point.ts index f6234c8ea..b6054a10a 100644 --- a/packages/math/point.ts +++ b/packages/math/point.ts @@ -97,7 +97,7 @@ export function pointsEqual( } /** - * Roate a point by [angle] radians. + * Rotate a point by [angle] radians. * * @param point The point to rotate * @param center The point to rotate around, the center point @@ -116,7 +116,7 @@ export function pointRotateRads( } /** - * Roate a point by [angle] degree. + * Rotate a point by [angle] degree. * * @param point The point to rotate * @param center The point to rotate around, the center point From 77aca48c8437b5bcc356b144c9677616ca80c7ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Sun, 23 Mar 2025 18:39:33 +0100 Subject: [PATCH 45/51] fix: Refactor and merge duplication and binding (#9246) --- .../excalidraw/actions/actionAddToLibrary.ts | 2 +- .../actions/actionDeleteSelected.tsx | 1 + .../actions/actionDuplicateSelection.test.tsx | 2 +- .../actions/actionDuplicateSelection.tsx | 349 +++---------- packages/excalidraw/actions/actionFlip.ts | 3 +- packages/excalidraw/clipboard.ts | 3 +- packages/excalidraw/components/App.tsx | 238 +++------ .../components/LibraryMenuItems.tsx | 10 +- .../excalidraw/components/Stats/DragInput.tsx | 3 +- packages/excalidraw/element/binding.ts | 336 ++++++------ ...{newElement.test.ts => duplicate.test.tsx} | 345 ++++++++++++- packages/excalidraw/element/duplicate.ts | 484 ++++++++++++++++++ .../excalidraw/element/elbowArrow.test.tsx | 6 +- packages/excalidraw/element/elbowArrow.ts | 81 +-- packages/excalidraw/element/flowchart.ts | 4 +- packages/excalidraw/element/heading.ts | 8 +- packages/excalidraw/element/index.ts | 2 +- .../excalidraw/element/linearElementEditor.ts | 93 +++- packages/excalidraw/element/newElement.ts | 272 +--------- packages/excalidraw/element/textElement.ts | 44 +- packages/excalidraw/groups.ts | 5 +- .../excalidraw/renderer/interactiveScene.ts | 37 +- packages/excalidraw/store.ts | 3 +- .../__snapshots__/contextmenu.test.tsx.snap | 4 +- .../tests/__snapshots__/history.test.tsx.snap | 10 +- .../tests/__snapshots__/move.test.tsx.snap | 10 +- .../regressionTests.test.tsx.snap | 16 +- .../excalidraw/tests/fractionalIndex.test.ts | 3 +- .../excalidraw/tests/regressionTests.test.tsx | 4 + 29 files changed, 1293 insertions(+), 1085 deletions(-) rename packages/excalidraw/element/{newElement.test.ts => duplicate.test.tsx} (52%) create mode 100644 packages/excalidraw/element/duplicate.ts diff --git a/packages/excalidraw/actions/actionAddToLibrary.ts b/packages/excalidraw/actions/actionAddToLibrary.ts index b246918a0..b79353308 100644 --- a/packages/excalidraw/actions/actionAddToLibrary.ts +++ b/packages/excalidraw/actions/actionAddToLibrary.ts @@ -1,5 +1,5 @@ import { LIBRARY_DISABLED_TYPES } from "../constants"; -import { deepCopyElement } from "../element/newElement"; +import { deepCopyElement } from "../element/duplicate"; import { t } from "../i18n"; import { randomId } from "../random"; import { CaptureUpdateAction } from "../store"; diff --git a/packages/excalidraw/actions/actionDeleteSelected.tsx b/packages/excalidraw/actions/actionDeleteSelected.tsx index fe3f8c5d7..7e5ed919c 100644 --- a/packages/excalidraw/actions/actionDeleteSelected.tsx +++ b/packages/excalidraw/actions/actionDeleteSelected.tsx @@ -288,6 +288,7 @@ export const actionDeleteSelected = register({ activeTool: updateActiveTool(appState, { type: "selection" }), multiElement: null, activeEmbeddable: null, + selectedLinearElement: null, }, captureUpdate: isSomeElementSelected( getNonDeletedElements(elements), diff --git a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx index 2c1d44e92..bbaae2ed6 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.test.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.test.tsx @@ -258,7 +258,7 @@ describe("actionDuplicateSelection", () => { assertElements(h.elements, [ { id: frame.id }, { id: text.id, frameId: frame.id }, - { [ORIG_ID]: text.id, frameId: frame.id }, + { [ORIG_ID]: text.id, frameId: frame.id, selected: true }, ]); }); diff --git a/packages/excalidraw/actions/actionDuplicateSelection.tsx b/packages/excalidraw/actions/actionDuplicateSelection.tsx index 0125f0288..a6dd9d2e1 100644 --- a/packages/excalidraw/actions/actionDuplicateSelection.tsx +++ b/packages/excalidraw/actions/actionDuplicateSelection.tsx @@ -1,29 +1,10 @@ import { ToolButton } from "../components/ToolButton"; import { DuplicateIcon } from "../components/icons"; import { DEFAULT_GRID_SIZE } from "../constants"; -import { duplicateElement, getNonDeletedElements } from "../element"; -import { fixBindingsAfterDuplication } from "../element/binding"; -import { - bindTextToShapeAfterDuplication, - getBoundTextElement, - getContainerElement, -} from "../element/textElement"; -import { - hasBoundTextElement, - isBoundToContainer, - isFrameLikeElement, -} from "../element/typeChecks"; -import { normalizeElementOrder } from "../element/sortElements"; +import { getNonDeletedElements } from "../element"; +import { isBoundToContainer, isLinearElement } from "../element/typeChecks"; import { LinearElementEditor } from "../element/linearElementEditor"; -import { - bindElementsToFramesAfterDuplication, - getFrameChildren, -} from "../frame"; -import { - selectGroupsForSelectedElements, - getSelectedGroupForElement, - getElementsInGroup, -} from "../groups"; +import { selectGroupsForSelectedElements } from "../groups"; import { t } from "../i18n"; import { KEYS } from "../keys"; import { isSomeElementSelected } from "../scene"; @@ -32,19 +13,15 @@ import { getSelectedElements, } from "../scene/selection"; import { CaptureUpdateAction } from "../store"; -import { - arrayToMap, - castArray, - findLastIndex, - getShortcutKey, - invariant, -} from "../utils"; +import { arrayToMap, getShortcutKey } from "../utils"; + +import { syncMovedIndices } from "../fractionalIndex"; + +import { duplicateElements } from "../element/duplicate"; import { register } from "./register"; -import type { ActionResult } from "./types"; import type { ExcalidrawElement } from "../element/types"; -import type { AppState } from "../types"; export const actionDuplicateSelection = register({ name: "duplicateSelection", @@ -75,20 +52,54 @@ export const actionDuplicateSelection = register({ } } - const nextState = duplicateElements(elements, appState); - - if (app.props.onDuplicate && nextState.elements) { - const mappedElements = app.props.onDuplicate( - nextState.elements, + let { newElements: duplicatedElements, elementsWithClones: nextElements } = + duplicateElements({ + type: "in-place", elements, - ); + idsOfElementsToDuplicate: arrayToMap( + getSelectedElements(elements, appState, { + includeBoundTextElement: true, + includeElementsInFrames: true, + }), + ), + appState, + randomizeSeed: true, + overrides: (element) => ({ + x: element.x + DEFAULT_GRID_SIZE / 2, + y: element.y + DEFAULT_GRID_SIZE / 2, + }), + reverseOrder: false, + }); + + if (app.props.onDuplicate && nextElements) { + const mappedElements = app.props.onDuplicate(nextElements, elements); if (mappedElements) { - nextState.elements = mappedElements; + nextElements = mappedElements; } } return { - ...nextState, + elements: syncMovedIndices(nextElements, arrayToMap(duplicatedElements)), + appState: { + ...appState, + ...updateLinearElementEditors(duplicatedElements), + ...selectGroupsForSelectedElements( + { + editingGroupId: appState.editingGroupId, + selectedElementIds: excludeElementsInFramesFromSelection( + duplicatedElements, + ).reduce((acc: Record, element) => { + if (!isBoundToContainer(element)) { + acc[element.id] = true; + } + return acc; + }, {}), + }, + getNonDeletedElements(nextElements), + appState, + null, + ), + }, captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; }, @@ -107,259 +118,23 @@ export const actionDuplicateSelection = register({ ), }); -const duplicateElements = ( - elements: readonly ExcalidrawElement[], - appState: AppState, -): Partial> => { - // --------------------------------------------------------------------------- - - const groupIdMap = new Map(); - const newElements: ExcalidrawElement[] = []; - const oldElements: ExcalidrawElement[] = []; - const oldIdToDuplicatedId = new Map(); - const duplicatedElementsMap = new Map(); - - const elementsMap = arrayToMap(elements); - - const duplicateAndOffsetElement = < - T extends ExcalidrawElement | ExcalidrawElement[], - >( - element: T, - ): T extends ExcalidrawElement[] - ? ExcalidrawElement[] - : ExcalidrawElement | null => { - const elements = castArray(element); - - const _newElements = elements.reduce( - (acc: ExcalidrawElement[], element) => { - if (processedIds.has(element.id)) { - return acc; - } - - processedIds.set(element.id, true); - - const newElement = duplicateElement( - appState.editingGroupId, - groupIdMap, - element, - { - x: element.x + DEFAULT_GRID_SIZE / 2, - y: element.y + DEFAULT_GRID_SIZE / 2, - }, - ); - - processedIds.set(newElement.id, true); - - duplicatedElementsMap.set(newElement.id, newElement); - oldIdToDuplicatedId.set(element.id, newElement.id); - - oldElements.push(element); - newElements.push(newElement); - - acc.push(newElement); - return acc; - }, - [], +const updateLinearElementEditors = (clonedElements: ExcalidrawElement[]) => { + const linears = clonedElements.filter(isLinearElement); + if (linears.length === 1) { + const linear = linears[0]; + const boundElements = linear.boundElements?.map((def) => def.id) ?? []; + const onlySingleLinearSelected = clonedElements.every( + (el) => el.id === linear.id || boundElements.includes(el.id), ); - return ( - Array.isArray(element) ? _newElements : _newElements[0] || null - ) as T extends ExcalidrawElement[] - ? ExcalidrawElement[] - : ExcalidrawElement | null; - }; - - elements = normalizeElementOrder(elements); - - const idsOfElementsToDuplicate = arrayToMap( - getSelectedElements(elements, appState, { - includeBoundTextElement: true, - includeElementsInFrames: true, - }), - ); - - // Ids of elements that have already been processed so we don't push them - // into the array twice if we end up backtracking when retrieving - // discontiguous group of elements (can happen due to a bug, or in edge - // cases such as a group containing deleted elements which were not selected). - // - // This is not enough to prevent duplicates, so we do a second loop afterwards - // to remove them. - // - // For convenience we mark even the newly created ones even though we don't - // loop over them. - const processedIds = new Map(); - - const elementsWithClones: ExcalidrawElement[] = elements.slice(); - - const insertAfterIndex = ( - index: number, - elements: ExcalidrawElement | null | ExcalidrawElement[], - ) => { - invariant(index !== -1, "targetIndex === -1 "); - - if (!Array.isArray(elements) && !elements) { - return; + if (onlySingleLinearSelected) { + return { + selectedLinearElement: new LinearElementEditor(linear), + }; } - - elementsWithClones.splice(index + 1, 0, ...castArray(elements)); - }; - - const frameIdsToDuplicate = new Set( - elements - .filter( - (el) => idsOfElementsToDuplicate.has(el.id) && isFrameLikeElement(el), - ) - .map((el) => el.id), - ); - - for (const element of elements) { - if (processedIds.has(element.id)) { - continue; - } - - if (!idsOfElementsToDuplicate.has(element.id)) { - continue; - } - - // groups - // ------------------------------------------------------------------------- - - const groupId = getSelectedGroupForElement(appState, element); - if (groupId) { - const groupElements = getElementsInGroup(elements, groupId).flatMap( - (element) => - isFrameLikeElement(element) - ? [...getFrameChildren(elements, element.id), element] - : [element], - ); - - const targetIndex = findLastIndex(elementsWithClones, (el) => { - return el.groupIds?.includes(groupId); - }); - - insertAfterIndex(targetIndex, duplicateAndOffsetElement(groupElements)); - continue; - } - - // frame duplication - // ------------------------------------------------------------------------- - - if (element.frameId && frameIdsToDuplicate.has(element.frameId)) { - continue; - } - - if (isFrameLikeElement(element)) { - const frameId = element.id; - - const frameChildren = getFrameChildren(elements, frameId); - - const targetIndex = findLastIndex(elementsWithClones, (el) => { - return el.frameId === frameId || el.id === frameId; - }); - - insertAfterIndex( - targetIndex, - duplicateAndOffsetElement([...frameChildren, element]), - ); - continue; - } - - // text container - // ------------------------------------------------------------------------- - - if (hasBoundTextElement(element)) { - const boundTextElement = getBoundTextElement(element, elementsMap); - - const targetIndex = findLastIndex(elementsWithClones, (el) => { - return ( - el.id === element.id || - ("containerId" in el && el.containerId === element.id) - ); - }); - - if (boundTextElement) { - insertAfterIndex( - targetIndex, - duplicateAndOffsetElement([element, boundTextElement]), - ); - } else { - insertAfterIndex(targetIndex, duplicateAndOffsetElement(element)); - } - - continue; - } - - if (isBoundToContainer(element)) { - const container = getContainerElement(element, elementsMap); - - const targetIndex = findLastIndex(elementsWithClones, (el) => { - return el.id === element.id || el.id === container?.id; - }); - - if (container) { - insertAfterIndex( - targetIndex, - duplicateAndOffsetElement([container, element]), - ); - } else { - insertAfterIndex(targetIndex, duplicateAndOffsetElement(element)); - } - - continue; - } - - // default duplication (regular elements) - // ------------------------------------------------------------------------- - - insertAfterIndex( - findLastIndex(elementsWithClones, (el) => el.id === element.id), - duplicateAndOffsetElement(element), - ); } - // --------------------------------------------------------------------------- - - bindTextToShapeAfterDuplication( - elementsWithClones, - oldElements, - oldIdToDuplicatedId, - ); - fixBindingsAfterDuplication( - elementsWithClones, - oldElements, - oldIdToDuplicatedId, - ); - bindElementsToFramesAfterDuplication( - elementsWithClones, - oldElements, - oldIdToDuplicatedId, - ); - - const nextElementsToSelect = - excludeElementsInFramesFromSelection(newElements); - return { - elements: elementsWithClones, - appState: { - ...appState, - ...selectGroupsForSelectedElements( - { - editingGroupId: appState.editingGroupId, - selectedElementIds: nextElementsToSelect.reduce( - (acc: Record, element) => { - if (!isBoundToContainer(element)) { - acc[element.id] = true; - } - return acc; - }, - {}, - ), - }, - getNonDeletedElements(elementsWithClones), - appState, - null, - ), - }, + selectedLinearElement: null, }; }; diff --git a/packages/excalidraw/actions/actionFlip.ts b/packages/excalidraw/actions/actionFlip.ts index bfc7fb721..6c91445a3 100644 --- a/packages/excalidraw/actions/actionFlip.ts +++ b/packages/excalidraw/actions/actionFlip.ts @@ -6,7 +6,6 @@ import { } from "../element/binding"; import { getCommonBoundingBox } from "../element/bounds"; import { mutateElement, newElementWith } from "../element/mutateElement"; -import { deepCopyElement } from "../element/newElement"; import { resizeMultipleElements } from "../element/resizeElements"; import { isArrowElement, @@ -19,6 +18,8 @@ import { getSelectedElements } from "../scene"; import { CaptureUpdateAction } from "../store"; import { arrayToMap } from "../utils"; +import { deepCopyElement } from "../element/duplicate"; + import { register } from "./register"; import type { diff --git a/packages/excalidraw/clipboard.ts b/packages/excalidraw/clipboard.ts index 1b0e9942a..397c350ff 100644 --- a/packages/excalidraw/clipboard.ts +++ b/packages/excalidraw/clipboard.ts @@ -6,7 +6,6 @@ import { } from "./constants"; import { createFile, isSupportedImageFileType } from "./data/blob"; import { mutateElement } from "./element/mutateElement"; -import { deepCopyElement } from "./element/newElement"; import { isFrameLikeElement, isInitializedImageElement, @@ -15,6 +14,8 @@ import { ExcalidrawError } from "./errors"; import { getContainingFrame } from "./frame"; import { arrayToMap, isMemberOf, isPromiseLike } from "./utils"; +import { deepCopyElement } from "./element/duplicate"; + import type { Spreadsheet } from "./charts"; import type { ExcalidrawElement, diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 6017b73b7..8239493ba 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -126,7 +126,6 @@ import { restore, restoreElements } from "../data/restore"; import { dragNewElement, dragSelectedElements, - duplicateElement, getCommonBounds, getCursorForResizingElement, getDragOffsetXY, @@ -152,7 +151,6 @@ import { bindOrUnbindLinearElement, bindOrUnbindLinearElements, fixBindingsAfterDeletion, - fixBindingsAfterDuplication, getHoveredElementForBinding, isBindingEnabled, isLinearElementSimpleAndAlreadyBound, @@ -163,9 +161,8 @@ import { } from "../element/binding"; import { LinearElementEditor } from "../element/linearElementEditor"; import { mutateElement, newElementWith } from "../element/mutateElement"; +import { deepCopyElement, duplicateElements } from "../element/duplicate"; import { - deepCopyElement, - duplicateElements, newFrameElement, newFreeDrawElement, newEmbeddableElement, @@ -292,7 +289,6 @@ import { } from "../element/image"; import { fileOpen } from "../data/filesystem"; import { - bindTextToShapeAfterDuplication, getBoundTextElement, getContainerCenter, getContainerElement, @@ -309,7 +305,6 @@ import { Fonts, getLineHeight } from "../fonts"; import { getFrameChildren, isCursorInFrame, - bindElementsToFramesAfterDuplication, addElementsToFrame, replaceAllElementsInFrame, removeElementsFromFrame, @@ -3224,17 +3219,16 @@ class App extends React.Component { const [gridX, gridY] = getGridPoint(dx, dy, this.getEffectiveGridSize()); - const newElements = duplicateElements( - elements.map((element) => { + const { newElements } = duplicateElements({ + type: "everything", + elements: elements.map((element) => { return newElementWith(element, { x: element.x + gridX - minX, y: element.y + gridY - minY, }); }), - { - randomizeSeed: !opts.retainSeed, - }, - ); + randomizeSeed: !opts.retainSeed, + }); const prevElements = this.scene.getElementsIncludingDeleted(); let nextElements = [...prevElements, ...newElements]; @@ -6095,7 +6089,12 @@ class App extends React.Component { this.setState({ activeEmbeddable: { element: hitElement, state: "hover" }, }); - } else if (!hitElement || !isElbowArrow(hitElement)) { + } else if ( + !hitElement || + // Ebow arrows can only be moved when unconnected + !isElbowArrow(hitElement) || + !(hitElement.startBinding || hitElement.endBinding) + ) { setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE); if (this.state.activeEmbeddable?.state === "hover") { this.setState({ activeEmbeddable: null }); @@ -6288,7 +6287,13 @@ class App extends React.Component { if (isHoveringAPointHandle || segmentMidPointHoveredCoords) { setCursor(this.interactiveCanvas, CURSOR_TYPE.POINTER); } else if (this.hitElement(scenePointerX, scenePointerY, element)) { - setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE); + if ( + // Ebow arrows can only be moved when unconnected + !isElbowArrow(element) || + !(element.startBinding || element.endBinding) + ) { + setCursor(this.interactiveCanvas, CURSOR_TYPE.MOVE); + } } } else if (this.hitElement(scenePointerX, scenePointerY, element)) { if ( @@ -8138,6 +8143,7 @@ class App extends React.Component { ...this.state.selectedLinearElement, pointerDownState: ret.pointerDownState, selectedPointsIndices: ret.selectedPointsIndices, + segmentMidPointHoveredCoords: null, }, }); } @@ -8147,6 +8153,7 @@ class App extends React.Component { ...this.state.editingLinearElement, pointerDownState: ret.pointerDownState, selectedPointsIndices: ret.selectedPointsIndices, + segmentMidPointHoveredCoords: null, }, }); } @@ -8160,7 +8167,7 @@ class App extends React.Component { return; } - const didDrag = LinearElementEditor.handlePointDragging( + const newLinearElementEditor = LinearElementEditor.handlePointDragging( event, this, pointerCoords.x, @@ -8174,29 +8181,18 @@ class App extends React.Component { linearElementEditor, this.scene, ); - if (didDrag) { + if (newLinearElementEditor) { pointerDownState.lastCoords.x = pointerCoords.x; pointerDownState.lastCoords.y = pointerCoords.y; pointerDownState.drag.hasOccurred = true; - if ( - this.state.editingLinearElement && - !this.state.editingLinearElement.isDragging - ) { - this.setState({ - editingLinearElement: { - ...this.state.editingLinearElement, - isDragging: true, - }, - }); - } - if (!this.state.selectedLinearElement.isDragging) { - this.setState({ - selectedLinearElement: { - ...this.state.selectedLinearElement, - isDragging: true, - }, - }); - } + + this.setState({ + editingLinearElement: this.state.editingLinearElement + ? newLinearElementEditor + : null, + selectedLinearElement: newLinearElementEditor, + }); + return; } } @@ -8422,145 +8418,55 @@ class App extends React.Component { pointerDownState.hit.hasBeenDuplicated = true; - const nextElements = []; - const elementsToAppend = []; - const groupIdMap = new Map(); - const oldIdToDuplicatedId = new Map(); - const hitElement = pointerDownState.hit.element; - const selectedElementIds = new Set( - this.scene - .getSelectedElements({ - selectedElementIds: this.state.selectedElementIds, - includeBoundTextElement: true, - includeElementsInFrames: true, - }) - .map((element) => element.id), - ); - const elements = this.scene.getElementsIncludingDeleted(); - - for (const element of elements) { - const isInSelection = - selectedElementIds.has(element.id) || - // case: the state.selectedElementIds might not have been - // updated yet by the time this mousemove event is fired - (element.id === hitElement?.id && - pointerDownState.hit.wasAddedToSelection); - // NOTE (mtolmacs): This is a temporary fix for very large scenes - if ( - Math.abs(element.x) > 1e7 || - Math.abs(element.x) > 1e7 || - Math.abs(element.width) > 1e7 || - Math.abs(element.height) > 1e7 - ) { - console.error( - `Alt+dragging element in scene with invalid dimensions`, - element.x, - element.y, - element.width, - element.height, - isInSelection, - ); - - return; - } - - if (isInSelection) { - const duplicatedElement = duplicateElement( - this.state.editingGroupId, - groupIdMap, - element, - ); - - // NOTE (mtolmacs): This is a temporary fix for very large scenes - if ( - Math.abs(duplicatedElement.x) > 1e7 || - Math.abs(duplicatedElement.x) > 1e7 || - Math.abs(duplicatedElement.width) > 1e7 || - Math.abs(duplicatedElement.height) > 1e7 - ) { - console.error( - `Alt+dragging duplicated element with invalid dimensions`, - duplicatedElement.x, - duplicatedElement.y, - duplicatedElement.width, - duplicatedElement.height, - ); - - return; - } - - const origElement = pointerDownState.originalElements.get( - element.id, - )!; - - // NOTE (mtolmacs): This is a temporary fix for very large scenes - if ( - Math.abs(origElement.x) > 1e7 || - Math.abs(origElement.x) > 1e7 || - Math.abs(origElement.width) > 1e7 || - Math.abs(origElement.height) > 1e7 - ) { - console.error( - `Alt+dragging duplicated element with invalid dimensions`, - origElement.x, - origElement.y, - origElement.width, - origElement.height, - ); - - return; - } - - mutateElement(duplicatedElement, { - x: origElement.x, - y: origElement.y, - }); - - // put duplicated element to pointerDownState.originalElements - // so that we can snap to the duplicated element without releasing - pointerDownState.originalElements.set( - duplicatedElement.id, - duplicatedElement, - ); - - nextElements.push(duplicatedElement); - elementsToAppend.push(element); - oldIdToDuplicatedId.set(element.id, duplicatedElement.id); - } else { - nextElements.push(element); - } + const hitElement = pointerDownState.hit.element; + const selectedElements = this.scene.getSelectedElements({ + selectedElementIds: this.state.selectedElementIds, + includeBoundTextElement: true, + includeElementsInFrames: true, + }); + if ( + hitElement && + !selectedElements.find((el) => el.id === hitElement.id) + ) { + selectedElements.push(hitElement); } - let nextSceneElements: ExcalidrawElement[] = [ - ...nextElements, - ...elementsToAppend, - ]; + const { newElements: clonedElements, elementsWithClones } = + duplicateElements({ + type: "in-place", + elements, + appState: this.state, + randomizeSeed: true, + idsOfElementsToDuplicate: new Map( + selectedElements.map((el) => [el.id, el]), + ), + overrides: (el) => { + const origEl = pointerDownState.originalElements.get(el.id); + + if (origEl) { + return { + x: origEl.x, + y: origEl.y, + }; + } + + return {}; + }, + reverseOrder: true, + }); + clonedElements.forEach((element) => { + pointerDownState.originalElements.set(element.id, element); + }); const mappedNewSceneElements = this.props.onDuplicate?.( - nextSceneElements, + elementsWithClones, elements, ); - nextSceneElements = mappedNewSceneElements || nextSceneElements; - - syncMovedIndices(nextSceneElements, arrayToMap(elementsToAppend)); - - bindTextToShapeAfterDuplication( - nextElements, - elementsToAppend, - oldIdToDuplicatedId, - ); - fixBindingsAfterDuplication( - nextSceneElements, - elementsToAppend, - oldIdToDuplicatedId, - "duplicatesServeAsOld", - ); - bindElementsToFramesAfterDuplication( - nextSceneElements, - elementsToAppend, - oldIdToDuplicatedId, + const nextSceneElements = syncMovedIndices( + mappedNewSceneElements || elementsWithClones, + arrayToMap(clonedElements), ); this.scene.replaceAllElements(nextSceneElements); diff --git a/packages/excalidraw/components/LibraryMenuItems.tsx b/packages/excalidraw/components/LibraryMenuItems.tsx index af5b9d3e6..3e32021e0 100644 --- a/packages/excalidraw/components/LibraryMenuItems.tsx +++ b/packages/excalidraw/components/LibraryMenuItems.tsx @@ -8,18 +8,20 @@ import React, { import { MIME_TYPES } from "../constants"; import { serializeLibraryAsJSON } from "../data/json"; -import { duplicateElements } from "../element/newElement"; import { useLibraryCache } from "../hooks/useLibraryItemSvg"; import { useScrollPosition } from "../hooks/useScrollPosition"; import { t } from "../i18n"; import { arrayToMap } from "../utils"; +import { duplicateElements } from "../element/duplicate"; + import { LibraryMenuControlButtons } from "./LibraryMenuControlButtons"; import { LibraryDropdownMenu } from "./LibraryMenuHeaderContent"; import { LibraryMenuSection, LibraryMenuSectionGrid, } from "./LibraryMenuSection"; + import Spinner from "./Spinner"; import Stack from "./Stack"; @@ -160,7 +162,11 @@ export default function LibraryMenuItems({ ...item, // duplicate each library item before inserting on canvas to confine // ids and bindings to each library item. See #6465 - elements: duplicateElements(item.elements, { randomizeSeed: true }), + elements: duplicateElements({ + type: "everything", + elements: item.elements, + randomizeSeed: true, + }).newElements, }; }); }, diff --git a/packages/excalidraw/components/Stats/DragInput.tsx b/packages/excalidraw/components/Stats/DragInput.tsx index fbea33e55..4ee8c7580 100644 --- a/packages/excalidraw/components/Stats/DragInput.tsx +++ b/packages/excalidraw/components/Stats/DragInput.tsx @@ -1,8 +1,9 @@ import clsx from "clsx"; import { useEffect, useRef, useState } from "react"; +import { deepCopyElement } from "@excalidraw/excalidraw/element/duplicate"; + import { EVENT } from "../../constants"; -import { deepCopyElement } from "../../element/newElement"; import { KEYS } from "../../keys"; import { CaptureUpdateAction } from "../../store"; import { cloneJSON } from "../../utils"; diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 93c5292f1..6799d1a6b 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -13,7 +13,6 @@ import { vectorCross, pointsEqual, lineSegmentIntersectionPoints, - round, PRECISION, } from "@excalidraw/math"; import { isPointOnShape } from "@excalidraw/utils/collision"; @@ -24,7 +23,10 @@ import { KEYS } from "../keys"; import { aabbForElement, getElementShape, pointInsideBounds } from "../shapes"; import { arrayToMap, + invariant, isBindingFallthroughEnabled, + isDevEnv, + isTestEnv, tupleToCoors, } from "../utils"; @@ -36,11 +38,8 @@ import { import { intersectElementWithLineSegment } from "./collision"; import { distanceToBindableElement } from "./distance"; import { - compareHeading, - HEADING_DOWN, - HEADING_RIGHT, - HEADING_UP, headingForPointFromElement, + headingIsHorizontal, vectorToHeading, type Heading, } from "./heading"; @@ -50,7 +49,6 @@ import { getBoundTextElement, handleBindTextResize } from "./textElement"; import { isArrowElement, isBindableElement, - isBindingElement, isBoundToContainer, isElbowArrow, isFixedPointBinding, @@ -60,6 +58,10 @@ import { isTextElement, } from "./typeChecks"; +import { updateElbowArrowPoints } from "./elbowArrow"; + +import type { Mutable } from "../utility-types"; + import type { Bounds } from "./bounds"; import type { ElementUpdate } from "./mutateElement"; import type { @@ -837,14 +839,19 @@ export const updateBoundElements = ( }> => update !== null, ); - LinearElementEditor.movePoints(element, updates, { - ...(changedElement.id === element.startBinding?.elementId - ? { startBinding: bindings.startBinding } - : {}), - ...(changedElement.id === element.endBinding?.elementId - ? { endBinding: bindings.endBinding } - : {}), - }); + LinearElementEditor.movePoints( + element, + updates, + { + ...(changedElement.id === element.startBinding?.elementId + ? { startBinding: bindings.startBinding } + : {}), + ...(changedElement.id === element.endBinding?.elementId + ? { endBinding: bindings.endBinding } + : {}), + }, + elementsMap as NonDeletedSceneElementsMap, + ); const boundText = getBoundTextElement(element, elementsMap); if (boundText && !boundText.isDeleted) { @@ -925,103 +932,104 @@ const getDistanceForBinding = ( export const bindPointToSnapToElementOutline = ( arrow: ExcalidrawElbowArrowElement, - bindableElement: ExcalidrawBindableElement | undefined, + bindableElement: ExcalidrawBindableElement, startOrEnd: "start" | "end", ): GlobalPoint => { - const aabb = bindableElement && aabbForElement(bindableElement); + if (isDevEnv() || isTestEnv()) { + invariant(arrow.points.length > 1, "Arrow should have at least 2 points"); + } + + const aabb = aabbForElement(bindableElement); const localP = arrow.points[startOrEnd === "start" ? 0 : arrow.points.length - 1]; const globalP = pointFrom( arrow.x + localP[0], arrow.y + localP[1], ); - const p = isRectanguloidElement(bindableElement) + const edgePoint = isRectanguloidElement(bindableElement) ? avoidRectangularCorner(bindableElement, globalP) : globalP; + const elbowed = isElbowArrow(arrow); + const center = getCenterForBounds(aabb); + const adjacentPointIdx = startOrEnd === "start" ? 1 : arrow.points.length - 2; + const adjacentPoint = pointRotateRads( + pointFrom( + arrow.x + arrow.points[adjacentPointIdx][0], + arrow.y + arrow.points[adjacentPointIdx][1], + ), + center, + arrow.angle ?? 0, + ); - if (bindableElement && aabb) { - const center = getCenterForBounds(aabb); - - const intersection = intersectElementWithLineSegment( + let intersection: GlobalPoint | null = null; + if (elbowed) { + const isHorizontal = headingIsHorizontal( + headingForPointFromElement(bindableElement, aabb, globalP), + ); + const otherPoint = pointFrom( + isHorizontal ? center[0] : edgePoint[0], + !isHorizontal ? center[1] : edgePoint[1], + ); + intersection = intersectElementWithLineSegment( bindableElement, lineSegment( - center, + otherPoint, pointFromVector( vectorScale( - vectorNormalize(vectorFromPoint(p, center)), - Math.max(bindableElement.width, bindableElement.height), + vectorNormalize(vectorFromPoint(edgePoint, otherPoint)), + Math.max(bindableElement.width, bindableElement.height) * 2, ), - center, + otherPoint, ), ), )[0]; - const currentDistance = pointDistance(p, center); - const fullDistance = Math.max( - pointDistance(intersection ?? p, center), - PRECISION, - ); - const ratio = round(currentDistance / fullDistance, 6); - - switch (true) { - case ratio > 0.9: - if ( - currentDistance - fullDistance > FIXED_BINDING_DISTANCE || - // Too close to determine vector from intersection to p - pointDistanceSq(p, intersection) < PRECISION - ) { - return p; - } - - return pointFromVector( + } else { + intersection = intersectElementWithLineSegment( + bindableElement, + lineSegment( + adjacentPoint, + pointFromVector( vectorScale( - vectorNormalize(vectorFromPoint(p, intersection ?? center)), - ratio > 1 ? FIXED_BINDING_DISTANCE : -FIXED_BINDING_DISTANCE, + vectorNormalize(vectorFromPoint(edgePoint, adjacentPoint)), + pointDistance(edgePoint, adjacentPoint) + + Math.max(bindableElement.width, bindableElement.height) * 2, ), - intersection ?? center, - ); - - default: - return headingToMidBindPoint(p, bindableElement, aabb); - } + adjacentPoint, + ), + ), + FIXED_BINDING_DISTANCE, + ).sort( + (g, h) => + pointDistanceSq(g, adjacentPoint) - pointDistanceSq(h, adjacentPoint), + )[0]; } - return p; -}; - -const headingToMidBindPoint = ( - p: GlobalPoint, - bindableElement: ExcalidrawBindableElement, - aabb: Bounds, -): GlobalPoint => { - const center = getCenterForBounds(aabb); - const heading = vectorToHeading(vectorFromPoint(p, center)); - - switch (true) { - case compareHeading(heading, HEADING_UP): - return pointRotateRads( - pointFrom((aabb[0] + aabb[2]) / 2 + 0.1, aabb[1]), - center, - bindableElement.angle, - ); - case compareHeading(heading, HEADING_RIGHT): - return pointRotateRads( - pointFrom(aabb[2], (aabb[1] + aabb[3]) / 2 + 0.1), - center, - bindableElement.angle, - ); - case compareHeading(heading, HEADING_DOWN): - return pointRotateRads( - pointFrom((aabb[0] + aabb[2]) / 2 - 0.1, aabb[3]), - center, - bindableElement.angle, - ); - default: - return pointRotateRads( - pointFrom(aabb[0], (aabb[1] + aabb[3]) / 2 - 0.1), - center, - bindableElement.angle, - ); + if ( + !intersection || + // Too close to determine vector from intersection to edgePoint + pointDistanceSq(edgePoint, intersection) < PRECISION + ) { + return edgePoint; } + + if (elbowed) { + const scalar = + pointDistanceSq(edgePoint, center) - + pointDistanceSq(intersection, center) > + 0 + ? FIXED_BINDING_DISTANCE + : -FIXED_BINDING_DISTANCE; + + return pointFromVector( + vectorScale( + vectorNormalize(vectorFromPoint(edgePoint, intersection)), + scalar, + ), + intersection, + ); + } + + return edgePoint; }; export const avoidRectangularCorner = ( @@ -1411,107 +1419,75 @@ const getLinearElementEdgeCoors = ( ); }; -// We need to: -// 1: Update elements not selected to point to duplicated elements -// 2: Update duplicated elements to point to other duplicated elements export const fixBindingsAfterDuplication = ( - sceneElements: readonly ExcalidrawElement[], - oldElements: readonly ExcalidrawElement[], + newElements: ExcalidrawElement[], oldIdToDuplicatedId: Map, - // There are three copying mechanisms: Copy-paste, duplication and alt-drag. - // Only when alt-dragging the new "duplicates" act as the "old", while - // the "old" elements act as the "new copy" - essentially working reverse - // to the other two. - duplicatesServeAsOld?: "duplicatesServeAsOld" | undefined, -): void => { - // First collect all the binding/bindable elements, so we only update - // each once, regardless of whether they were duplicated or not. - const allBoundElementIds: Set = new Set(); - const allBindableElementIds: Set = new Set(); - const shouldReverseRoles = duplicatesServeAsOld === "duplicatesServeAsOld"; - const duplicateIdToOldId = new Map( - [...oldIdToDuplicatedId].map(([key, value]) => [value, key]), - ); - oldElements.forEach((oldElement) => { - const { boundElements } = oldElement; - if (boundElements != null && boundElements.length > 0) { - boundElements.forEach((boundElement) => { - if (shouldReverseRoles && !oldIdToDuplicatedId.has(boundElement.id)) { - allBoundElementIds.add(boundElement.id); - } + duplicatedElementsMap: NonDeletedSceneElementsMap, +) => { + for (const element of newElements) { + if ("boundElements" in element && element.boundElements) { + Object.assign(element, { + boundElements: element.boundElements.reduce( + ( + acc: Mutable>, + binding, + ) => { + const newBindingId = oldIdToDuplicatedId.get(binding.id); + if (newBindingId) { + acc.push({ ...binding, id: newBindingId }); + } + return acc; + }, + [], + ), }); - allBindableElementIds.add(oldIdToDuplicatedId.get(oldElement.id)!); } - if (isBindingElement(oldElement)) { - if (oldElement.startBinding != null) { - const { elementId } = oldElement.startBinding; - if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) { - allBindableElementIds.add(elementId); - } - } - if (oldElement.endBinding != null) { - const { elementId } = oldElement.endBinding; - if (shouldReverseRoles && !oldIdToDuplicatedId.has(elementId)) { - allBindableElementIds.add(elementId); - } - } - if (oldElement.startBinding != null || oldElement.endBinding != null) { - allBoundElementIds.add(oldIdToDuplicatedId.get(oldElement.id)!); - } + + if ("containerId" in element && element.containerId) { + Object.assign(element, { + containerId: oldIdToDuplicatedId.get(element.containerId) ?? null, + }); } - }); - // Update the linear elements - ( - sceneElements.filter(({ id }) => - allBoundElementIds.has(id), - ) as ExcalidrawLinearElement[] - ).forEach((element) => { - const { startBinding, endBinding } = element; - mutateElement(element, { - startBinding: newBindingAfterDuplication( - startBinding, - oldIdToDuplicatedId, - ), - endBinding: newBindingAfterDuplication(endBinding, oldIdToDuplicatedId), - }); - }); + if ("endBinding" in element && element.endBinding) { + const newEndBindingId = oldIdToDuplicatedId.get( + element.endBinding.elementId, + ); + Object.assign(element, { + endBinding: newEndBindingId + ? { + ...element.endBinding, + elementId: newEndBindingId, + } + : null, + }); + } + if ("startBinding" in element && element.startBinding) { + const newEndBindingId = oldIdToDuplicatedId.get( + element.startBinding.elementId, + ); + Object.assign(element, { + startBinding: newEndBindingId + ? { + ...element.startBinding, + elementId: newEndBindingId, + } + : null, + }); + } - // Update the bindable shapes - sceneElements - .filter(({ id }) => allBindableElementIds.has(id)) - .forEach((bindableElement) => { - const oldElementId = duplicateIdToOldId.get(bindableElement.id); - const boundElements = sceneElements.find( - ({ id }) => id === oldElementId, - )?.boundElements; - - if (boundElements && boundElements.length > 0) { - mutateElement(bindableElement, { - boundElements: boundElements.map((boundElement) => - oldIdToDuplicatedId.has(boundElement.id) - ? { - id: oldIdToDuplicatedId.get(boundElement.id)!, - type: boundElement.type, - } - : boundElement, - ), - }); - } - }); -}; - -const newBindingAfterDuplication = ( - binding: PointBinding | null, - oldIdToDuplicatedId: Map, -): PointBinding | null => { - if (binding == null) { - return null; + if (isElbowArrow(element)) { + Object.assign( + element, + updateElbowArrowPoints(element, duplicatedElementsMap, { + points: [ + element.points[0], + element.points[element.points.length - 1], + ], + }), + ); + } } - return { - ...binding, - elementId: oldIdToDuplicatedId.get(binding.elementId) ?? binding.elementId, - }; }; export const fixBindingsAfterDeletion = ( diff --git a/packages/excalidraw/element/newElement.test.ts b/packages/excalidraw/element/duplicate.test.tsx similarity index 52% rename from packages/excalidraw/element/newElement.test.ts rename to packages/excalidraw/element/duplicate.test.tsx index 418ede1be..8e070ff98 100644 --- a/packages/excalidraw/element/newElement.test.ts +++ b/packages/excalidraw/element/duplicate.test.tsx @@ -1,16 +1,32 @@ +import React from "react"; import { pointFrom } from "@excalidraw/math"; import type { LocalPoint } from "@excalidraw/math"; -import { FONT_FAMILY, ROUNDNESS } from "../constants"; +import { FONT_FAMILY, ORIG_ID, ROUNDNESS } from "../constants"; import { API } from "../tests/helpers/api"; import { isPrimitive } from "../utils"; +import { + act, + assertElements, + getCloneByOrigId, + render, +} from "../tests/test-utils"; +import { Excalidraw } from ".."; +import { actionDuplicateSelection } from "../actions"; + +import { Keyboard, Pointer } from "../tests/helpers/ui"; + import { mutateElement } from "./mutateElement"; -import { duplicateElement, duplicateElements } from "./newElement"; + +import { duplicateElement, duplicateElements } from "./duplicate"; import type { ExcalidrawLinearElement } from "./types"; +const { h } = window; +const mouse = new Pointer("mouse"); + const assertCloneObjects = (source: any, clone: any) => { for (const key in clone) { if (clone.hasOwnProperty(key) && !isPrimitive(clone[key])) { @@ -45,7 +61,7 @@ describe("duplicating single elements", () => { points: [pointFrom(1, 2), pointFrom(3, 4)], }); - const copy = duplicateElement(null, new Map(), element); + const copy = duplicateElement(null, new Map(), element, undefined, true); assertCloneObjects(element, copy); @@ -64,6 +80,8 @@ describe("duplicating single elements", () => { ...element, id: copy.id, seed: copy.seed, + version: copy.version, + versionNonce: copy.versionNonce, }); }); @@ -149,7 +167,10 @@ describe("duplicating multiple elements", () => { // ------------------------------------------------------------------------- const origElements = [rectangle1, text1, arrow1, arrow2, text2] as const; - const clonedElements = duplicateElements(origElements); + const { newElements: clonedElements } = duplicateElements({ + type: "everything", + elements: origElements, + }); // generic id in-equality checks // -------------------------------------------------------------------------- @@ -206,6 +227,7 @@ describe("duplicating multiple elements", () => { type: clonedText1.type, }), ); + expect(clonedRectangle.type).toBe("rectangle"); clonedArrows.forEach((arrow) => { expect( @@ -281,7 +303,7 @@ describe("duplicating multiple elements", () => { const arrow3 = API.createElement({ type: "arrow", - id: "arrow2", + id: "arrow3", startBinding: { elementId: "rectangle-not-exists", focus: 0.2, @@ -299,9 +321,11 @@ describe("duplicating multiple elements", () => { // ------------------------------------------------------------------------- const origElements = [rectangle1, text1, arrow1, arrow2, arrow3] as const; - const clonedElements = duplicateElements( - origElements, - ) as any as typeof origElements; + const { newElements: clonedElements } = duplicateElements({ + type: "everything", + elements: origElements, + }) as any as { newElements: typeof origElements }; + const [ clonedRectangle, clonedText1, @@ -321,7 +345,6 @@ describe("duplicating multiple elements", () => { elementId: clonedRectangle.id, }); expect(clonedArrow2.endBinding).toBe(null); - expect(clonedArrow3.startBinding).toBe(null); expect(clonedArrow3.endBinding).toEqual({ ...arrow3.endBinding, @@ -345,9 +368,10 @@ describe("duplicating multiple elements", () => { }); const origElements = [rectangle1, rectangle2, rectangle3] as const; - const clonedElements = duplicateElements( - origElements, - ) as any as typeof origElements; + const { newElements: clonedElements } = duplicateElements({ + type: "everything", + elements: origElements, + }) as any as { newElements: typeof origElements }; const [clonedRectangle1, clonedRectangle2, clonedRectangle3] = clonedElements; @@ -368,10 +392,305 @@ describe("duplicating multiple elements", () => { groupIds: ["g1"], }); - const [clonedRectangle1] = duplicateElements([rectangle1]); + const { + newElements: [clonedRectangle1], + } = duplicateElements({ type: "everything", elements: [rectangle1] }); expect(typeof clonedRectangle1.groupIds[0]).toBe("string"); expect(rectangle1.groupIds[0]).not.toBe(clonedRectangle1.groupIds[0]); }); }); }); + +describe("duplication z-order", () => { + beforeEach(async () => { + await render(); + }); + + it("duplication z order with Cmd+D for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + API.setSelectedElements([rectangle1]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { [ORIG_ID]: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with Cmd+D for the highest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + API.setSelectedElements([rectangle3]); + + act(() => { + h.app.actionManager.executeAction(actionDuplicateSelection); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { id: rectangle2.id }, + { id: rectangle3.id }, + { [ORIG_ID]: rectangle3.id, selected: true }, + ]); + }); + + it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 5, rectangle1.y + 5); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with alt+drag for the highest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle3); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle3.x + 5, rectangle3.y + 5); + mouse.up(rectangle3.x + 5, rectangle3.y + 5); + }); + + assertElements(h.elements, [ + { id: rectangle1.id }, + { id: rectangle2.id }, + { [ORIG_ID]: rectangle3.id }, + { id: rectangle3.id, selected: true }, + ]); + }); + + it("duplication z order with alt+drag for the lowest z-ordered element should be +1 for the clone", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 5, rectangle1.y + 5); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id }, + { id: rectangle3.id }, + ]); + }); + + it("duplication z order with alt+drag with grouped elements should consider the group together when determining z-index", () => { + const rectangle1 = API.createElement({ + type: "rectangle", + x: 0, + y: 0, + groupIds: ["group1"], + }); + const rectangle2 = API.createElement({ + type: "rectangle", + x: 10, + y: 10, + groupIds: ["group1"], + }); + const rectangle3 = API.createElement({ + type: "rectangle", + x: 20, + y: 20, + groupIds: ["group1"], + }); + + API.setElements([rectangle1, rectangle2, rectangle3]); + + mouse.select(rectangle1); + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle1.x + 5, rectangle1.y + 5); + mouse.up(rectangle1.x + 15, rectangle1.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle1.id }, + { [ORIG_ID]: rectangle2.id }, + { [ORIG_ID]: rectangle3.id }, + { id: rectangle1.id, selected: true }, + { id: rectangle2.id, selected: true }, + { id: rectangle3.id, selected: true }, + ]); + }); + + it("reverse-duplicating text container (in-order)", async () => { + const [rectangle, text] = API.createTextContainer(); + API.setElements([rectangle, text]); + API.setSelectedElements([rectangle, text]); + + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle.x + 5, rectangle.y + 5); + mouse.up(rectangle.x + 15, rectangle.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle.id }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id)?.id, + }, + { id: rectangle.id, selected: true }, + { id: text.id, containerId: rectangle.id, selected: true }, + ]); + }); + + it("reverse-duplicating text container (out-of-order)", async () => { + const [rectangle, text] = API.createTextContainer(); + API.setElements([text, rectangle]); + API.setSelectedElements([rectangle, text]); + + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(rectangle.x + 5, rectangle.y + 5); + mouse.up(rectangle.x + 15, rectangle.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: rectangle.id }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(rectangle.id)?.id, + }, + { id: rectangle.id, selected: true }, + { id: text.id, containerId: rectangle.id, selected: true }, + ]); + }); + + it("reverse-duplicating labeled arrows (in-order)", async () => { + const [arrow, text] = API.createLabeledArrow(); + + API.setElements([arrow, text]); + API.setSelectedElements([arrow, text]); + + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(arrow.x + 5, arrow.y + 5); + mouse.up(arrow.x + 15, arrow.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: arrow.id }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(arrow.id)?.id, + }, + { id: arrow.id, selected: true }, + { id: text.id, containerId: arrow.id, selected: true }, + ]); + }); + + it("reverse-duplicating labeled arrows (out-of-order)", async () => { + const [arrow, text] = API.createLabeledArrow(); + + API.setElements([text, arrow]); + API.setSelectedElements([arrow, text]); + + Keyboard.withModifierKeys({ alt: true }, () => { + mouse.down(arrow.x + 5, arrow.y + 5); + mouse.up(arrow.x + 15, arrow.y + 15); + }); + + assertElements(h.elements, [ + { [ORIG_ID]: arrow.id }, + { + [ORIG_ID]: text.id, + containerId: getCloneByOrigId(arrow.id)?.id, + }, + { id: arrow.id, selected: true }, + { id: text.id, containerId: arrow.id, selected: true }, + ]); + }); +}); diff --git a/packages/excalidraw/element/duplicate.ts b/packages/excalidraw/element/duplicate.ts new file mode 100644 index 000000000..c126c57c9 --- /dev/null +++ b/packages/excalidraw/element/duplicate.ts @@ -0,0 +1,484 @@ +import { ORIG_ID } from "../constants"; +import { + getElementsInGroup, + getNewGroupIdsForDuplication, + getSelectedGroupForElement, +} from "../groups"; + +import { randomId, randomInteger } from "../random"; + +import { + arrayToMap, + castArray, + findLastIndex, + getUpdatedTimestamp, + isTestEnv, +} from "../utils"; + +import { + bindElementsToFramesAfterDuplication, + getFrameChildren, +} from "../frame"; + +import { normalizeElementOrder } from "./sortElements"; + +import { bumpVersion } from "./mutateElement"; + +import { + hasBoundTextElement, + isBoundToContainer, + isFrameLikeElement, +} from "./typeChecks"; + +import { getBoundTextElement, getContainerElement } from "./textElement"; + +import { fixBindingsAfterDuplication } from "./binding"; + +import type { AppState } from "../types"; +import type { Mutable } from "../utility-types"; + +import type { + ElementsMap, + ExcalidrawElement, + GroupId, + NonDeletedSceneElementsMap, +} from "./types"; + +/** + * Duplicate an element, often used in the alt-drag operation. + * Note that this method has gotten a bit complicated since the + * introduction of gruoping/ungrouping elements. + * @param editingGroupId The current group being edited. The new + * element will inherit this group and its + * parents. + * @param groupIdMapForOperation A Map that maps old group IDs to + * duplicated ones. If you are duplicating + * multiple elements at once, share this map + * amongst all of them + * @param element Element to duplicate + * @param overrides Any element properties to override + */ +export const duplicateElement = ( + editingGroupId: AppState["editingGroupId"], + groupIdMapForOperation: Map, + element: TElement, + overrides?: Partial, + randomizeSeed?: boolean, +): Readonly => { + let copy = deepCopyElement(element); + + if (isTestEnv()) { + __test__defineOrigId(copy, element.id); + } + + copy.id = randomId(); + copy.updated = getUpdatedTimestamp(); + if (randomizeSeed) { + copy.seed = randomInteger(); + bumpVersion(copy); + } + + copy.groupIds = getNewGroupIdsForDuplication( + copy.groupIds, + editingGroupId, + (groupId) => { + if (!groupIdMapForOperation.has(groupId)) { + groupIdMapForOperation.set(groupId, randomId()); + } + return groupIdMapForOperation.get(groupId)!; + }, + ); + if (overrides) { + copy = Object.assign(copy, overrides); + } + return copy; +}; + +export const duplicateElements = ( + opts: { + elements: readonly ExcalidrawElement[]; + randomizeSeed?: boolean; + overrides?: ( + originalElement: ExcalidrawElement, + ) => Partial; + } & ( + | { + /** + * Duplicates all elements in array. + * + * Use this when programmaticaly duplicating elements, without direct + * user interaction. + */ + type: "everything"; + } + | { + /** + * Duplicates specified elements and inserts them back into the array + * in specified order. + * + * Use this when duplicating Scene elements, during user interaction + * such as alt-drag or on duplicate action. + */ + type: "in-place"; + idsOfElementsToDuplicate: Map< + ExcalidrawElement["id"], + ExcalidrawElement + >; + appState: { + editingGroupId: AppState["editingGroupId"]; + selectedGroupIds: AppState["selectedGroupIds"]; + }; + /** + * If true, duplicated elements are inserted _before_ specified + * elements. Case: alt-dragging elements to duplicate them. + * + * TODO: remove this once (if) we stop replacing the original element + * with the duplicated one in the scene array. + */ + reverseOrder: boolean; + } + ), +) => { + let { elements } = opts; + + const appState = + "appState" in opts + ? opts.appState + : ({ + editingGroupId: null, + selectedGroupIds: {}, + } as const); + + const reverseOrder = opts.type === "in-place" ? opts.reverseOrder : false; + + // Ids of elements that have already been processed so we don't push them + // into the array twice if we end up backtracking when retrieving + // discontiguous group of elements (can happen due to a bug, or in edge + // cases such as a group containing deleted elements which were not selected). + // + // This is not enough to prevent duplicates, so we do a second loop afterwards + // to remove them. + // + // For convenience we mark even the newly created ones even though we don't + // loop over them. + const processedIds = new Map(); + const groupIdMap = new Map(); + const newElements: ExcalidrawElement[] = []; + const oldElements: ExcalidrawElement[] = []; + const oldIdToDuplicatedId = new Map(); + const duplicatedElementsMap = new Map(); + const elementsMap = arrayToMap(elements) as ElementsMap; + const _idsOfElementsToDuplicate = + opts.type === "in-place" + ? opts.idsOfElementsToDuplicate + : new Map(elements.map((el) => [el.id, el])); + + // For sanity + if (opts.type === "in-place") { + for (const groupId of Object.keys(opts.appState.selectedGroupIds)) { + elements + .filter((el) => el.groupIds?.includes(groupId)) + .forEach((el) => _idsOfElementsToDuplicate.set(el.id, el)); + } + } + + elements = normalizeElementOrder(elements); + + const elementsWithClones: ExcalidrawElement[] = elements.slice(); + + // helper functions + // ------------------------------------------------------------------------- + + // Used for the heavy lifing of copying a single element, a group of elements + // an element with bound text etc. + const copyElements = ( + element: T, + ): T extends ExcalidrawElement[] + ? ExcalidrawElement[] + : ExcalidrawElement | null => { + const elements = castArray(element); + + const _newElements = elements.reduce( + (acc: ExcalidrawElement[], element) => { + if (processedIds.has(element.id)) { + return acc; + } + + processedIds.set(element.id, true); + + const newElement = duplicateElement( + appState.editingGroupId, + groupIdMap, + element, + opts.overrides?.(element), + opts.randomizeSeed, + ); + + processedIds.set(newElement.id, true); + + duplicatedElementsMap.set(newElement.id, newElement); + oldIdToDuplicatedId.set(element.id, newElement.id); + + oldElements.push(element); + newElements.push(newElement); + + acc.push(newElement); + return acc; + }, + [], + ); + + return ( + Array.isArray(element) ? _newElements : _newElements[0] || null + ) as T extends ExcalidrawElement[] + ? ExcalidrawElement[] + : ExcalidrawElement | null; + }; + + // Helper to position cloned elements in the Z-order the product needs it + const insertBeforeOrAfterIndex = ( + index: number, + elements: ExcalidrawElement | null | ExcalidrawElement[], + ) => { + if (!elements) { + return; + } + + if (reverseOrder && index < 1) { + elementsWithClones.unshift(...castArray(elements)); + return; + } + + if (!reverseOrder && index > elementsWithClones.length - 1) { + elementsWithClones.push(...castArray(elements)); + return; + } + + elementsWithClones.splice( + index + (reverseOrder ? 0 : 1), + 0, + ...castArray(elements), + ); + }; + + const frameIdsToDuplicate = new Set( + elements + .filter( + (el) => _idsOfElementsToDuplicate.has(el.id) && isFrameLikeElement(el), + ) + .map((el) => el.id), + ); + + for (const element of elements) { + if (processedIds.has(element.id)) { + continue; + } + + if (!_idsOfElementsToDuplicate.has(element.id)) { + continue; + } + + // groups + // ------------------------------------------------------------------------- + + const groupId = getSelectedGroupForElement(appState, element); + if (groupId) { + const groupElements = getElementsInGroup(elements, groupId).flatMap( + (element) => + isFrameLikeElement(element) + ? [...getFrameChildren(elements, element.id), element] + : [element], + ); + + const targetIndex = reverseOrder + ? elementsWithClones.findIndex((el) => { + return el.groupIds?.includes(groupId); + }) + : findLastIndex(elementsWithClones, (el) => { + return el.groupIds?.includes(groupId); + }); + + insertBeforeOrAfterIndex(targetIndex, copyElements(groupElements)); + continue; + } + + // frame duplication + // ------------------------------------------------------------------------- + + if (element.frameId && frameIdsToDuplicate.has(element.frameId)) { + continue; + } + + if (isFrameLikeElement(element)) { + const frameId = element.id; + + const frameChildren = getFrameChildren(elements, frameId); + + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return el.frameId === frameId || el.id === frameId; + }); + + insertBeforeOrAfterIndex( + targetIndex, + copyElements([...frameChildren, element]), + ); + continue; + } + + // text container + // ------------------------------------------------------------------------- + + if (hasBoundTextElement(element)) { + const boundTextElement = getBoundTextElement(element, elementsMap); + + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return ( + el.id === element.id || + ("containerId" in el && el.containerId === element.id) + ); + }); + + if (boundTextElement) { + insertBeforeOrAfterIndex( + targetIndex + (reverseOrder ? -1 : 0), + copyElements([element, boundTextElement]), + ); + } else { + insertBeforeOrAfterIndex(targetIndex, copyElements(element)); + } + + continue; + } + + if (isBoundToContainer(element)) { + const container = getContainerElement(element, elementsMap); + + const targetIndex = findLastIndex(elementsWithClones, (el) => { + return el.id === element.id || el.id === container?.id; + }); + + if (container) { + insertBeforeOrAfterIndex( + targetIndex, + copyElements([container, element]), + ); + } else { + insertBeforeOrAfterIndex(targetIndex, copyElements(element)); + } + + continue; + } + + // default duplication (regular elements) + // ------------------------------------------------------------------------- + + insertBeforeOrAfterIndex( + findLastIndex(elementsWithClones, (el) => el.id === element.id), + copyElements(element), + ); + } + + // --------------------------------------------------------------------------- + + fixBindingsAfterDuplication( + newElements, + oldIdToDuplicatedId, + duplicatedElementsMap as NonDeletedSceneElementsMap, + ); + + bindElementsToFramesAfterDuplication( + elementsWithClones, + oldElements, + oldIdToDuplicatedId, + ); + + return { + newElements, + elementsWithClones, + }; +}; + +// Simplified deep clone for the purpose of cloning ExcalidrawElement. +// +// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set, +// Typed arrays and other non-null objects. +// +// Adapted from https://github.com/lukeed/klona +// +// The reason for `deepCopyElement()` wrapper is type safety (only allow +// passing ExcalidrawElement as the top-level argument). +const _deepCopyElement = (val: any, depth: number = 0) => { + // only clone non-primitives + if (val == null || typeof val !== "object") { + return val; + } + + const objectType = Object.prototype.toString.call(val); + + if (objectType === "[object Object]") { + const tmp = + typeof val.constructor === "function" + ? Object.create(Object.getPrototypeOf(val)) + : {}; + for (const key in val) { + if (val.hasOwnProperty(key)) { + // don't copy non-serializable objects like these caches. They'll be + // populated when the element is rendered. + if (depth === 0 && (key === "shape" || key === "canvas")) { + continue; + } + tmp[key] = _deepCopyElement(val[key], depth + 1); + } + } + return tmp; + } + + if (Array.isArray(val)) { + let k = val.length; + const arr = new Array(k); + while (k--) { + arr[k] = _deepCopyElement(val[k], depth + 1); + } + return arr; + } + + // we're not cloning non-array & non-plain-object objects because we + // don't support them on excalidraw elements yet. If we do, we need to make + // sure we start cloning them, so let's warn about it. + if (import.meta.env.DEV) { + if ( + objectType !== "[object Object]" && + objectType !== "[object Array]" && + objectType.startsWith("[object ") + ) { + console.warn( + `_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`, + ); + } + } + + return val; +}; + +/** + * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or + * any value. The purpose is to to break object references for immutability + * reasons, whenever we want to keep the original element, but ensure it's not + * mutated. + * + * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set, + * Typed arrays and other non-null objects. + */ +export const deepCopyElement = ( + val: T, +): Mutable => { + return _deepCopyElement(val); +}; + +const __test__defineOrigId = (clonedObj: object, origId: string) => { + Object.defineProperty(clonedObj, ORIG_ID, { + value: origId, + writable: false, + enumerable: false, + }); +}; diff --git a/packages/excalidraw/element/elbowArrow.test.tsx b/packages/excalidraw/element/elbowArrow.test.tsx index 91e280d30..621d2640f 100644 --- a/packages/excalidraw/element/elbowArrow.test.tsx +++ b/packages/excalidraw/element/elbowArrow.test.tsx @@ -358,7 +358,7 @@ describe("elbow arrow ui", () => { expect(arrow.endBinding).not.toBe(null); }); - it("keeps arrow shape when only the bound arrow is duplicated", async () => { + it("changes arrow shape to unbind variant if only the connected elbow arrow is duplicated", async () => { UI.createElement("rectangle", { x: -150, y: -150, @@ -404,8 +404,8 @@ describe("elbow arrow ui", () => { expect(duplicatedArrow.elbowed).toBe(true); expect(duplicatedArrow.points).toEqual([ [0, 0], - [45, 0], - [45, 200], + [0, 100], + [90, 100], [90, 200], ]); }); diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index 5e44b6ea6..a8c22abcc 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -238,16 +238,6 @@ const handleSegmentRenormalization = ( nextPoints.map((p) => pointFrom(p[0] - arrow.x, p[1] - arrow.y), ), - arrow.startBinding && - getBindableElementForId( - arrow.startBinding.elementId, - elementsMap, - ), - arrow.endBinding && - getBindableElementForId( - arrow.endBinding.elementId, - elementsMap, - ), ), ) ?? [], ), @@ -341,9 +331,6 @@ const handleSegmentRelease = ( y, ), ], - startBinding && - getBindableElementForId(startBinding.elementId, elementsMap), - endBinding && getBindableElementForId(endBinding.elementId, elementsMap), { isDragging: false }, ); @@ -983,6 +970,8 @@ export const updateElbowArrowPoints = ( ); } + const fixedSegments = updates.fixedSegments ?? arrow.fixedSegments ?? []; + const updatedPoints: readonly LocalPoint[] = updates.points ? updates.points && updates.points.length === 2 ? arrow.points.map((p, idx) => @@ -995,7 +984,7 @@ export const updateElbowArrowPoints = ( : updates.points.slice() : arrow.points.slice(); - // 0. During all element replacement in the scene, we just need to renormalize + // During all element replacement in the scene, we just need to renormalize // the arrow // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed const { @@ -1016,11 +1005,12 @@ export const updateElbowArrowPoints = ( getBindableElementForId(startBinding.elementId, elementsMap); const endElement = endBinding && getBindableElementForId(endBinding.elementId, elementsMap); + const areUpdatedPointsValid = validateElbowPoints(updatedPoints); if ( - (startBinding && !startElement) || - (endBinding && !endElement) || - (elementsMap.size === 0 && validateElbowPoints(updatedPoints)) || + (startBinding && !startElement && areUpdatedPointsValid) || + (endBinding && !endElement && areUpdatedPointsValid) || + (elementsMap.size === 0 && areUpdatedPointsValid) || (Object.keys(restOfTheUpdates).length === 0 && (startElement?.id !== startBinding?.elementId || endElement?.id !== endBinding?.elementId)) @@ -1055,12 +1045,22 @@ export const updateElbowArrowPoints = ( }, elementsMap, updatedPoints, - startElement, - endElement, options, ); - const fixedSegments = updates.fixedSegments ?? arrow.fixedSegments ?? []; + // 0. During all element replacement in the scene, we just need to renormalize + // the arrow + // TODO (dwelle,mtolmacs): Remove this once Scene.getScene() is removed + if (elementsMap.size === 0 && areUpdatedPointsValid) { + return normalizeArrowElementUpdate( + updatedPoints.map((p) => + pointFrom(arrow.x + p[0], arrow.y + p[1]), + ), + arrow.fixedSegments, + arrow.startIsSpecial, + arrow.endIsSpecial, + ); + } //// // 1. Renormalize the arrow @@ -1084,7 +1084,7 @@ export const updateElbowArrowPoints = ( arrow.points[i] ?? pointFrom(Infinity, Infinity), ), ) && - validateElbowPoints(updatedPoints) + areUpdatedPointsValid ) { return {}; } @@ -1195,8 +1195,6 @@ const getElbowArrowData = ( }, elementsMap: NonDeletedSceneElementsMap, nextPoints: readonly LocalPoint[], - startElement: ExcalidrawBindableElement | null, - endElement: ExcalidrawBindableElement | null, options?: { isDragging?: boolean; zoom?: AppState["zoom"]; @@ -1211,8 +1209,8 @@ const getElbowArrowData = ( GlobalPoint >(nextPoints[nextPoints.length - 1], vector(arrow.x, arrow.y)); - let hoveredStartElement = startElement; - let hoveredEndElement = endElement; + let hoveredStartElement = null; + let hoveredEndElement = null; if (options?.isDragging) { const elements = Array.from(elementsMap.values()); hoveredStartElement = @@ -1221,39 +1219,47 @@ const getElbowArrowData = ( elementsMap, elements, options?.zoom, - ) || startElement; + ) || null; hoveredEndElement = getHoveredElement( origEndGlobalPoint, elementsMap, elements, options?.zoom, - ) || endElement; + ) || null; + } else { + hoveredStartElement = arrow.startBinding + ? getBindableElementForId(arrow.startBinding.elementId, elementsMap) || + null + : null; + hoveredEndElement = arrow.endBinding + ? getBindableElementForId(arrow.endBinding.elementId, elementsMap) || null + : null; } const startGlobalPoint = getGlobalPoint( { ...arrow, + type: "arrow", elbowed: true, points: nextPoints, } as ExcalidrawElbowArrowElement, "start", arrow.startBinding?.fixedPoint, origStartGlobalPoint, - startElement, hoveredStartElement, options?.isDragging, ); const endGlobalPoint = getGlobalPoint( { ...arrow, + type: "arrow", elbowed: true, points: nextPoints, } as ExcalidrawElbowArrowElement, "end", arrow.endBinding?.fixedPoint, origEndGlobalPoint, - endElement, hoveredEndElement, options?.isDragging, ); @@ -2199,36 +2205,35 @@ const getGlobalPoint = ( startOrEnd: "start" | "end", fixedPointRatio: [number, number] | undefined | null, initialPoint: GlobalPoint, - boundElement?: ExcalidrawBindableElement | null, - hoveredElement?: ExcalidrawBindableElement | null, + element?: ExcalidrawBindableElement | null, isDragging?: boolean, ): GlobalPoint => { if (isDragging) { - if (hoveredElement) { + if (element) { const snapPoint = bindPointToSnapToElementOutline( arrow, - hoveredElement, + element, startOrEnd, ); - return snapToMid(hoveredElement, snapPoint); + return snapToMid(element, snapPoint); } return initialPoint; } - if (boundElement) { + if (element) { const fixedGlobalPoint = getGlobalFixedPointForBindableElement( fixedPointRatio || [0, 0], - boundElement, + element, ); // NOTE: Resize scales the binding position point too, so we need to update it return Math.abs( - distanceToBindableElement(boundElement, fixedGlobalPoint) - + distanceToBindableElement(element, fixedGlobalPoint) - FIXED_BINDING_DISTANCE, ) > 0.01 - ? bindPointToSnapToElementOutline(arrow, boundElement, startOrEnd) + ? bindPointToSnapToElementOutline(arrow, element, startOrEnd) : fixedGlobalPoint; } diff --git a/packages/excalidraw/element/flowchart.ts b/packages/excalidraw/element/flowchart.ts index 9880f27af..1790ef3f0 100644 --- a/packages/excalidraw/element/flowchart.ts +++ b/packages/excalidraw/element/flowchart.ts @@ -1,4 +1,4 @@ -import { pointFrom, type LocalPoint } from "@excalidraw/math"; +import { type GlobalPoint, pointFrom, type LocalPoint } from "@excalidraw/math"; import { elementOverlapsWithFrame, elementsAreInFrameBounds } from "../frame"; import { KEYS } from "../keys"; @@ -94,7 +94,7 @@ const getNodeRelatives = ( const heading = headingForPointFromElement(node, aabbForElement(node), [ edgePoint[0] + el.x, edgePoint[1] + el.y, - ] as Readonly); + ] as Readonly); acc.push({ relative, diff --git a/packages/excalidraw/element/heading.ts b/packages/excalidraw/element/heading.ts index ddebeca53..474923515 100644 --- a/packages/excalidraw/element/heading.ts +++ b/packages/excalidraw/element/heading.ts @@ -1,4 +1,5 @@ import { + normalizeRadians, pointFrom, pointRotateRads, pointScaleFromOrigin, @@ -30,8 +31,9 @@ export const headingForDiamond = ( b: Point, ) => { const angle = radiansToDegrees( - Math.atan2(b[1] - a[1], b[0] - a[0]) as Radians, + normalizeRadians(Math.atan2(b[1] - a[1], b[0] - a[0]) as Radians), ); + if (angle >= 315 || angle < 45) { return HEADING_UP; } else if (angle >= 45 && angle < 135) { @@ -77,9 +79,7 @@ export const headingIsVertical = (a: Heading) => !headingIsHorizontal(a); // Gets the heading for the point by creating a bounding box around the rotated // close fitting bounding box, then creating 4 search cones around the center of // the external bbox. -export const headingForPointFromElement = < - Point extends GlobalPoint | LocalPoint, ->( +export const headingForPointFromElement = ( element: Readonly, aabb: Readonly, p: Readonly, diff --git a/packages/excalidraw/element/index.ts b/packages/excalidraw/element/index.ts index abe84e031..6244e2740 100644 --- a/packages/excalidraw/element/index.ts +++ b/packages/excalidraw/element/index.ts @@ -14,8 +14,8 @@ export { newLinearElement, newArrowElement, newImageElement, - duplicateElement, } from "./newElement"; +export { duplicateElement } from "./duplicate"; export { getElementAbsoluteCoords, getElementBounds, diff --git a/packages/excalidraw/element/linearElementEditor.ts b/packages/excalidraw/element/linearElementEditor.ts index f9b23f048..adc436236 100644 --- a/packages/excalidraw/element/linearElementEditor.ts +++ b/packages/excalidraw/element/linearElementEditor.ts @@ -25,14 +25,19 @@ import { import { getGridPoint } from "../snapping"; import { invariant, tupleToCoors } from "../utils"; +import Scene from "../scene/Scene"; + import { bindOrUnbindLinearElement, getHoveredElementForBinding, isBindingEnabled, } from "./binding"; + +import { updateElbowArrowPoints } from "./elbowArrow"; + import { getElementPointsCoords, getMinMaxXYFromCurvePathOps } from "./bounds"; import { headingIsHorizontal, vectorToHeading } from "./heading"; -import { mutateElement } from "./mutateElement"; +import { bumpVersion, mutateElement } from "./mutateElement"; import { getBoundTextElement, handleBindTextResize } from "./textElement"; import { isBindingElement, @@ -57,7 +62,6 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import type Scene from "../scene/Scene"; import type { Store } from "../store"; import type { AppState, @@ -67,6 +71,7 @@ import type { NullableGridSize, Zoom, } from "../types"; + import type { Mutable } from "../utility-types"; const editorMidPointsCache: { @@ -232,15 +237,15 @@ export class LinearElementEditor { ) => void, linearElementEditor: LinearElementEditor, scene: Scene, - ): boolean { + ): LinearElementEditor | null { if (!linearElementEditor) { - return false; + return null; } const { elementId } = linearElementEditor; const elementsMap = scene.getNonDeletedElementsMap(); const element = LinearElementEditor.getElement(elementId, elementsMap); if (!element) { - return false; + return null; } if ( @@ -248,24 +253,18 @@ export class LinearElementEditor { !linearElementEditor.pointerDownState.lastClickedIsEndPoint && linearElementEditor.pointerDownState.lastClickedPoint !== 0 ) { - return false; + return null; } const selectedPointsIndices = isElbowArrow(element) - ? linearElementEditor.selectedPointsIndices - ?.reduce( - (startEnd, index) => - (index === 0 - ? [0, startEnd[1]] - : [startEnd[0], element.points.length - 1]) as [ - boolean | number, - boolean | number, - ], - [false, false] as [number | boolean, number | boolean], - ) - .filter( - (idx: number | boolean): idx is number => typeof idx === "number", - ) + ? [ + !!linearElementEditor.selectedPointsIndices?.includes(0) + ? 0 + : undefined, + !!linearElementEditor.selectedPointsIndices?.find((idx) => idx > 0) + ? element.points.length - 1 + : undefined, + ].filter((idx): idx is number => idx !== undefined) : linearElementEditor.selectedPointsIndices; const lastClickedPoint = isElbowArrow(element) ? linearElementEditor.pointerDownState.lastClickedPoint > 0 @@ -274,9 +273,7 @@ export class LinearElementEditor { : linearElementEditor.pointerDownState.lastClickedPoint; // point that's being dragged (out of all selected points) - const draggingPoint = element.points[lastClickedPoint] as - | [number, number] - | undefined; + const draggingPoint = element.points[lastClickedPoint]; if (selectedPointsIndices && draggingPoint) { if ( @@ -384,10 +381,28 @@ export class LinearElementEditor { } } - return true; + return { + ...linearElementEditor, + selectedPointsIndices, + segmentMidPointHoveredCoords: + lastClickedPoint !== 0 && + lastClickedPoint !== element.points.length - 1 + ? this.getPointGlobalCoordinates( + element, + draggingPoint, + elementsMap, + ) + : null, + hoverPointIndex: + lastClickedPoint === 0 || + lastClickedPoint === element.points.length - 1 + ? lastClickedPoint + : -1, + isDragging: true, + }; } - return false; + return null; } static handlePointerUp( @@ -1264,6 +1279,7 @@ export class LinearElementEditor { startBinding?: PointBinding | null; endBinding?: PointBinding | null; }, + sceneElementsMap?: NonDeletedSceneElementsMap, ) { const { points } = element; @@ -1307,6 +1323,7 @@ export class LinearElementEditor { dragging || targetPoint.isDragging === true, false, ), + sceneElementsMap, }, ); } @@ -1420,6 +1437,7 @@ export class LinearElementEditor { options?: { isDragging?: boolean; zoom?: AppState["zoom"]; + sceneElementsMap?: NonDeletedSceneElementsMap; }, ) { if (isElbowArrow(element)) { @@ -1445,9 +1463,28 @@ export class LinearElementEditor { updates.points = Array.from(nextPoints); - mutateElement(element, updates, true, { - isDragging: options?.isDragging, - }); + if (!options?.sceneElementsMap || Scene.getScene(element)) { + mutateElement(element, updates, true, { + isDragging: options?.isDragging, + }); + } else { + // The element is not in the scene, so we need to use the provided + // scene map. + Object.assign(element, { + ...updates, + angle: 0 as Radians, + + ...updateElbowArrowPoints( + element, + options.sceneElementsMap, + updates, + { + isDragging: options?.isDragging, + }, + ), + }); + } + bumpVersion(element); } else { const nextCoords = getElementPointsCoords(element, nextPoints); const prevCoords = getElementPointsCoords(element, element.points); diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index d11c4c20f..8d0a9bbd8 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -6,21 +6,14 @@ import { DEFAULT_FONT_SIZE, DEFAULT_TEXT_ALIGN, DEFAULT_VERTICAL_ALIGN, - ORIG_ID, VERTICAL_ALIGN, } from "../constants"; import { getLineHeight } from "../fonts"; -import { getNewGroupIdsForDuplication } from "../groups"; import { randomInteger, randomId } from "../random"; -import { - arrayToMap, - getFontString, - getUpdatedTimestamp, - isTestEnv, -} from "../utils"; +import { getFontString, getUpdatedTimestamp } from "../utils"; import { getResizedElementAbsoluteCoords } from "./bounds"; -import { bumpVersion, newElementWith } from "./mutateElement"; +import { newElementWith } from "./mutateElement"; import { getBoundTextMaxWidth } from "./textElement"; import { normalizeText, measureText } from "./textMeasurements"; import { wrapText } from "./textWrapping"; @@ -35,7 +28,6 @@ import type { ExcalidrawGenericElement, NonDeleted, TextAlign, - GroupId, VerticalAlign, Arrowhead, ExcalidrawFreeDrawElement, @@ -50,8 +42,7 @@ import type { FixedSegment, ExcalidrawElbowArrowElement, } from "./types"; -import type { AppState } from "../types"; -import type { MarkOptional, Merge, Mutable } from "../utility-types"; +import type { MarkOptional, Merge } from "../utility-types"; export type ElementConstructorOpts = MarkOptional< Omit, @@ -538,260 +529,3 @@ export const newImageElement = ( crop: opts.crop ?? null, }; }; - -// Simplified deep clone for the purpose of cloning ExcalidrawElement. -// -// Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set, -// Typed arrays and other non-null objects. -// -// Adapted from https://github.com/lukeed/klona -// -// The reason for `deepCopyElement()` wrapper is type safety (only allow -// passing ExcalidrawElement as the top-level argument). -const _deepCopyElement = (val: any, depth: number = 0) => { - // only clone non-primitives - if (val == null || typeof val !== "object") { - return val; - } - - const objectType = Object.prototype.toString.call(val); - - if (objectType === "[object Object]") { - const tmp = - typeof val.constructor === "function" - ? Object.create(Object.getPrototypeOf(val)) - : {}; - for (const key in val) { - if (val.hasOwnProperty(key)) { - // don't copy non-serializable objects like these caches. They'll be - // populated when the element is rendered. - if (depth === 0 && (key === "shape" || key === "canvas")) { - continue; - } - tmp[key] = _deepCopyElement(val[key], depth + 1); - } - } - return tmp; - } - - if (Array.isArray(val)) { - let k = val.length; - const arr = new Array(k); - while (k--) { - arr[k] = _deepCopyElement(val[k], depth + 1); - } - return arr; - } - - // we're not cloning non-array & non-plain-object objects because we - // don't support them on excalidraw elements yet. If we do, we need to make - // sure we start cloning them, so let's warn about it. - if (import.meta.env.DEV) { - if ( - objectType !== "[object Object]" && - objectType !== "[object Array]" && - objectType.startsWith("[object ") - ) { - console.warn( - `_deepCloneElement: unexpected object type ${objectType}. This value will not be cloned!`, - ); - } - } - - return val; -}; - -/** - * Clones ExcalidrawElement data structure. Does not regenerate id, nonce, or - * any value. The purpose is to to break object references for immutability - * reasons, whenever we want to keep the original element, but ensure it's not - * mutated. - * - * Only clones plain objects and arrays. Doesn't clone Date, RegExp, Map, Set, - * Typed arrays and other non-null objects. - */ -export const deepCopyElement = ( - val: T, -): Mutable => { - return _deepCopyElement(val); -}; - -const __test__defineOrigId = (clonedObj: object, origId: string) => { - Object.defineProperty(clonedObj, ORIG_ID, { - value: origId, - writable: false, - enumerable: false, - }); -}; - -/** - * utility wrapper to generate new id. - */ -const regenerateId = () => { - return randomId(); -}; - -/** - * Duplicate an element, often used in the alt-drag operation. - * Note that this method has gotten a bit complicated since the - * introduction of gruoping/ungrouping elements. - * @param editingGroupId The current group being edited. The new - * element will inherit this group and its - * parents. - * @param groupIdMapForOperation A Map that maps old group IDs to - * duplicated ones. If you are duplicating - * multiple elements at once, share this map - * amongst all of them - * @param element Element to duplicate - * @param overrides Any element properties to override - */ -export const duplicateElement = ( - editingGroupId: AppState["editingGroupId"], - groupIdMapForOperation: Map, - element: TElement, - overrides?: Partial, -): Readonly => { - let copy = deepCopyElement(element); - - if (isTestEnv()) { - __test__defineOrigId(copy, element.id); - } - - copy.id = regenerateId(); - copy.boundElements = null; - copy.updated = getUpdatedTimestamp(); - copy.seed = randomInteger(); - copy.groupIds = getNewGroupIdsForDuplication( - copy.groupIds, - editingGroupId, - (groupId) => { - if (!groupIdMapForOperation.has(groupId)) { - groupIdMapForOperation.set(groupId, regenerateId()); - } - return groupIdMapForOperation.get(groupId)!; - }, - ); - if (overrides) { - copy = Object.assign(copy, overrides); - } - return copy; -}; - -/** - * Clones elements, regenerating their ids (including bindings) and group ids. - * - * If bindings don't exist in the elements array, they are removed. Therefore, - * it's advised to supply the whole elements array, or sets of elements that - * are encapsulated (such as library items), if the purpose is to retain - * bindings to the cloned elements intact. - * - * NOTE by default does not randomize or regenerate anything except the id. - */ -export const duplicateElements = ( - elements: readonly ExcalidrawElement[], - opts?: { - /** NOTE also updates version flags and `updated` */ - randomizeSeed: boolean; - }, -) => { - const clonedElements: ExcalidrawElement[] = []; - - const origElementsMap = arrayToMap(elements); - - // used for for migrating old ids to new ids - const elementNewIdsMap = new Map< - /* orig */ ExcalidrawElement["id"], - /* new */ ExcalidrawElement["id"] - >(); - - const maybeGetNewId = (id: ExcalidrawElement["id"]) => { - // if we've already migrated the element id, return the new one directly - if (elementNewIdsMap.has(id)) { - return elementNewIdsMap.get(id)!; - } - // if we haven't migrated the element id, but an old element with the same - // id exists, generate a new id for it and return it - if (origElementsMap.has(id)) { - const newId = regenerateId(); - elementNewIdsMap.set(id, newId); - return newId; - } - // if old element doesn't exist, return null to mark it for removal - return null; - }; - - const groupNewIdsMap = new Map(); - - for (const element of elements) { - const clonedElement: Mutable = _deepCopyElement(element); - - clonedElement.id = maybeGetNewId(element.id)!; - if (isTestEnv()) { - __test__defineOrigId(clonedElement, element.id); - } - - if (opts?.randomizeSeed) { - clonedElement.seed = randomInteger(); - bumpVersion(clonedElement); - } - - if (clonedElement.groupIds) { - clonedElement.groupIds = clonedElement.groupIds.map((groupId) => { - if (!groupNewIdsMap.has(groupId)) { - groupNewIdsMap.set(groupId, regenerateId()); - } - return groupNewIdsMap.get(groupId)!; - }); - } - - if ("containerId" in clonedElement && clonedElement.containerId) { - const newContainerId = maybeGetNewId(clonedElement.containerId); - clonedElement.containerId = newContainerId; - } - - if ("boundElements" in clonedElement && clonedElement.boundElements) { - clonedElement.boundElements = clonedElement.boundElements.reduce( - ( - acc: Mutable>, - binding, - ) => { - const newBindingId = maybeGetNewId(binding.id); - if (newBindingId) { - acc.push({ ...binding, id: newBindingId }); - } - return acc; - }, - [], - ); - } - - if ("endBinding" in clonedElement && clonedElement.endBinding) { - const newEndBindingId = maybeGetNewId(clonedElement.endBinding.elementId); - clonedElement.endBinding = newEndBindingId - ? { - ...clonedElement.endBinding, - elementId: newEndBindingId, - } - : null; - } - if ("startBinding" in clonedElement && clonedElement.startBinding) { - const newEndBindingId = maybeGetNewId( - clonedElement.startBinding.elementId, - ); - clonedElement.startBinding = newEndBindingId - ? { - ...clonedElement.startBinding, - elementId: newEndBindingId, - } - : null; - } - - if (clonedElement.frameId) { - clonedElement.frameId = maybeGetNewId(clonedElement.frameId); - } - - clonedElements.push(clonedElement); - } - - return clonedElements; -}; diff --git a/packages/excalidraw/element/textElement.ts b/packages/excalidraw/element/textElement.ts index 9893ba5d6..b8399f038 100644 --- a/packages/excalidraw/element/textElement.ts +++ b/packages/excalidraw/element/textElement.ts @@ -6,7 +6,7 @@ import { TEXT_ALIGN, VERTICAL_ALIGN, } from "../constants"; -import { getFontString, arrayToMap } from "../utils"; +import { getFontString } from "../utils"; import { resetOriginalContainerCache, @@ -112,48 +112,6 @@ export const redrawTextBoundingBox = ( mutateElement(textElement, boundTextUpdates, informMutation); }; -export const bindTextToShapeAfterDuplication = ( - newElements: ExcalidrawElement[], - oldElements: ExcalidrawElement[], - oldIdToDuplicatedId: Map, -): void => { - const newElementsMap = arrayToMap(newElements) as Map< - ExcalidrawElement["id"], - ExcalidrawElement - >; - oldElements.forEach((element) => { - const newElementId = oldIdToDuplicatedId.get(element.id) as string; - const boundTextElementId = getBoundTextElementId(element); - - if (boundTextElementId) { - const newTextElementId = oldIdToDuplicatedId.get(boundTextElementId); - if (newTextElementId) { - const newContainer = newElementsMap.get(newElementId); - if (newContainer) { - mutateElement(newContainer, { - boundElements: (element.boundElements || []) - .filter( - (boundElement) => - boundElement.id !== newTextElementId && - boundElement.id !== boundTextElementId, - ) - .concat({ - type: "text", - id: newTextElementId, - }), - }); - } - const newTextElement = newElementsMap.get(newTextElementId); - if (newTextElement && isTextElement(newTextElement)) { - mutateElement(newTextElement, { - containerId: newContainer ? newElementId : null, - }); - } - } - } - }); -}; - export const handleBindTextResize = ( container: NonDeletedExcalidrawElement, elementsMap: ElementsMap, diff --git a/packages/excalidraw/groups.ts b/packages/excalidraw/groups.ts index cedc4af0f..61b493fd4 100644 --- a/packages/excalidraw/groups.ts +++ b/packages/excalidraw/groups.ts @@ -214,7 +214,10 @@ export const isSelectedViaGroup = ( ) => getSelectedGroupForElement(appState, element) != null; export const getSelectedGroupForElement = ( - appState: InteractiveCanvasAppState, + appState: Pick< + InteractiveCanvasAppState, + "editingGroupId" | "selectedGroupIds" + >, element: ExcalidrawElement, ) => element.groupIds diff --git a/packages/excalidraw/renderer/interactiveScene.ts b/packages/excalidraw/renderer/interactiveScene.ts index 257decd62..b0971f9f2 100644 --- a/packages/excalidraw/renderer/interactiveScene.ts +++ b/packages/excalidraw/renderer/interactiveScene.ts @@ -886,23 +886,24 @@ const _renderInteractiveScene = ({ ); } - if ( - isElbowArrow(selectedElements[0]) && - appState.selectedLinearElement && - appState.selectedLinearElement.segmentMidPointHoveredCoords - ) { - renderElbowArrowMidPointHighlight(context, appState); - } else if ( - appState.selectedLinearElement && - appState.selectedLinearElement.hoverPointIndex >= 0 && - !( - isElbowArrow(selectedElements[0]) && - appState.selectedLinearElement.hoverPointIndex > 0 && - appState.selectedLinearElement.hoverPointIndex < - selectedElements[0].points.length - 1 - ) - ) { - renderLinearElementPointHighlight(context, appState, elementsMap); + // Arrows have a different highlight behavior when + // they are the only selected element + if (appState.selectedLinearElement) { + const editor = appState.selectedLinearElement; + const firstSelectedLinear = selectedElements.find( + (el) => el.id === editor.elementId, // Don't forget bound text elements! + ); + + if (editor.segmentMidPointHoveredCoords) { + renderElbowArrowMidPointHighlight(context, appState); + } else if ( + isElbowArrow(firstSelectedLinear) + ? editor.hoverPointIndex === 0 || + editor.hoverPointIndex === firstSelectedLinear.points.length - 1 + : editor.hoverPointIndex >= 0 + ) { + renderLinearElementPointHighlight(context, appState, elementsMap); + } } // Paint selected elements @@ -1073,7 +1074,7 @@ const _renderInteractiveScene = ({ const dashedLinePadding = (DEFAULT_TRANSFORM_HANDLE_SPACING * 2) / appState.zoom.value; context.fillStyle = oc.white; - const [x1, y1, x2, y2] = getCommonBounds(selectedElements); + const [x1, y1, x2, y2] = getCommonBounds(selectedElements, elementsMap); const initialLineDash = context.getLineDash(); context.setLineDash([2 / appState.zoom.value]); const lineWidth = context.lineWidth; diff --git a/packages/excalidraw/store.ts b/packages/excalidraw/store.ts index 8b0065884..1723d0aa1 100644 --- a/packages/excalidraw/store.ts +++ b/packages/excalidraw/store.ts @@ -2,10 +2,11 @@ import { getDefaultAppState } from "./appState"; import { AppStateChange, ElementsChange } from "./change"; import { ENV } from "./constants"; import { newElementWith } from "./element/mutateElement"; -import { deepCopyElement } from "./element/newElement"; import { Emitter } from "./emitter"; import { isShallowEqual } from "./utils"; +import { deepCopyElement } from "./element/duplicate"; + import type { OrderedExcalidrawElement } from "./element/types"; import type { AppState, ObservedAppState } from "./types"; import type { ValueOf } from "./utility-types"; diff --git a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap index f77eb8ddb..89629b93e 100644 --- a/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/contextmenu.test.tsx.snap @@ -2606,8 +2606,8 @@ exports[`contextMenu element > selecting 'Duplicate' in context menu duplicates "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 4, - "versionNonce": 238820263, + "version": 5, + "versionNonce": 400692809, "width": 20, "x": 0, "y": 10, diff --git a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap index d740e975c..3f523d005 100644 --- a/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/history.test.tsx.snap @@ -15172,9 +15172,11 @@ History { "selectedElementIds": { "id61": true, }, + "selectedLinearElementId": "id61", }, "inserted": { "selectedElementIds": {}, + "selectedLinearElementId": null, }, }, }, @@ -18946,7 +18948,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 4, "width": 100, "x": 10, "y": 10, @@ -18980,7 +18982,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 3, + "version": 4, "width": 100, "x": 110, "y": 110, @@ -19014,7 +19016,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 7, "width": 100, "x": 10, "y": 10, @@ -19048,7 +19050,7 @@ exports[`history > singleplayer undo/redo > should support duplication of groups "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 7, "width": 100, "x": 110, "y": 110, diff --git a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap index 90236a4dd..4001c3b17 100644 --- a/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/move.test.tsx.snap @@ -11,7 +11,7 @@ exports[`duplicate element on move when ALT is clicked > rectangle 5`] = ` "groupIds": [], "height": 50, "id": "id2", - "index": "a0", + "index": "Zz", "isDeleted": false, "link": null, "locked": false, @@ -26,8 +26,8 @@ exports[`duplicate element on move when ALT is clicked > rectangle 5`] = ` "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 5, - "versionNonce": 400692809, + "version": 6, + "versionNonce": 1604849351, "width": 30, "x": 30, "y": 20, @@ -45,7 +45,7 @@ exports[`duplicate element on move when ALT is clicked > rectangle 6`] = ` "groupIds": [], "height": 50, "id": "id0", - "index": "a1", + "index": "a0", "isDeleted": false, "link": null, "locked": false, @@ -60,7 +60,7 @@ exports[`duplicate element on move when ALT is clicked > rectangle 6`] = ` "strokeWidth": 2, "type": "rectangle", "updated": 1, - "version": 6, + "version": 5, "versionNonce": 23633383, "width": 30, "x": -10, diff --git a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap index 5d48ead6c..4e9c659d0 100644 --- a/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap +++ b/packages/excalidraw/tests/__snapshots__/regressionTests.test.tsx.snap @@ -2139,7 +2139,7 @@ History { "frameId": null, "groupIds": [], "height": 10, - "index": "a0", + "index": "Zz", "isDeleted": false, "link": null, "locked": false, @@ -2164,12 +2164,10 @@ History { "updated": Map { "id0" => Delta { "deleted": { - "index": "a1", "x": 20, "y": 20, }, "inserted": { - "index": "a0", "x": 10, "y": 10, }, @@ -10631,7 +10629,7 @@ History { "id7", ], "height": 10, - "index": "a0", + "index": "Zx", "isDeleted": false, "link": null, "locked": false, @@ -10664,7 +10662,7 @@ History { "id7", ], "height": 10, - "index": "a1", + "index": "Zy", "isDeleted": false, "link": null, "locked": false, @@ -10697,7 +10695,7 @@ History { "id7", ], "height": 10, - "index": "a2", + "index": "Zz", "isDeleted": false, "link": null, "locked": false, @@ -10722,36 +10720,30 @@ History { "updated": Map { "id0" => Delta { "deleted": { - "index": "a3", "x": 20, "y": 20, }, "inserted": { - "index": "a0", "x": 10, "y": 10, }, }, "id1" => Delta { "deleted": { - "index": "a4", "x": 40, "y": 20, }, "inserted": { - "index": "a1", "x": 30, "y": 10, }, }, "id2" => Delta { "deleted": { - "index": "a5", "x": 60, "y": 20, }, "inserted": { - "index": "a2", "x": 50, "y": 10, }, diff --git a/packages/excalidraw/tests/fractionalIndex.test.ts b/packages/excalidraw/tests/fractionalIndex.test.ts index dbd55bd92..e9eb576e7 100644 --- a/packages/excalidraw/tests/fractionalIndex.test.ts +++ b/packages/excalidraw/tests/fractionalIndex.test.ts @@ -1,7 +1,6 @@ /* eslint-disable no-lone-blocks */ import { generateKeyBetween } from "fractional-indexing"; -import { deepCopyElement } from "../element/newElement"; import { InvalidFractionalIndexError } from "../errors"; import { syncInvalidIndices, @@ -10,6 +9,8 @@ import { } from "../fractionalIndex"; import { arrayToMap } from "../utils"; +import { deepCopyElement } from "../element/duplicate"; + import { API } from "./helpers/api"; import type { ExcalidrawElement, FractionalIndex } from "../element/types"; diff --git a/packages/excalidraw/tests/regressionTests.test.tsx b/packages/excalidraw/tests/regressionTests.test.tsx index 8407f0766..42d726f1d 100644 --- a/packages/excalidraw/tests/regressionTests.test.tsx +++ b/packages/excalidraw/tests/regressionTests.test.tsx @@ -1184,3 +1184,7 @@ it( expect(API.getSelectedElements().length).toBe(1); }, ); + +// +// DEPRECATED: DO NOT ADD TESTS HERE +// From e1bb59fb8f115cd8e75fcaaeefa03a81b0fdc697 Mon Sep 17 00:00:00 2001 From: Mursaleen Nisar Date: Tue, 25 Mar 2025 00:14:00 +0530 Subject: [PATCH 46/51] chore: Use isDevEnv() and isTestEnv() (#9264) Signed-off-by: Mark Tolmacs Co-authored-by: Mark Tolmacs --- excalidraw-app/App.tsx | 3 ++- excalidraw-app/collab/Collab.tsx | 8 +++++--- excalidraw-app/components/AppMainMenu.tsx | 4 +++- packages/excalidraw/analytics.ts | 5 ++++- packages/excalidraw/change.ts | 15 ++++++++------- packages/excalidraw/charts.ts | 6 ++++-- packages/excalidraw/components/App.tsx | 6 +++--- .../excalidraw/components/Sidebar/Sidebar.tsx | 4 ++-- packages/excalidraw/data/reconcile.ts | 11 +++-------- packages/excalidraw/element/elbowArrow.ts | 4 ++-- packages/excalidraw/element/newElement.ts | 1 + packages/excalidraw/element/textWrapping.ts | 4 ++-- packages/excalidraw/i18n.ts | 4 +++- packages/excalidraw/scene/Scene.ts | 11 +++-------- packages/excalidraw/store.ts | 5 ++--- packages/excalidraw/utils.ts | 2 +- 16 files changed, 48 insertions(+), 45 deletions(-) diff --git a/excalidraw-app/App.tsx b/excalidraw-app/App.tsx index dc399a7d0..7091d4bc5 100644 --- a/excalidraw-app/App.tsx +++ b/excalidraw-app/App.tsx @@ -36,6 +36,7 @@ import { preventUnload, resolvablePromise, isRunningInIframe, + isDevEnv, } from "@excalidraw/excalidraw/utils"; import { GithubIcon, @@ -383,7 +384,7 @@ const ExcalidrawWrapper = () => { const [, forceRefresh] = useState(false); useEffect(() => { - if (import.meta.env.DEV) { + if (isDevEnv()) { const debugState = loadSavedDebugState(); if (debugState.enabled && !window.visualDebug) { diff --git a/excalidraw-app/collab/Collab.tsx b/excalidraw-app/collab/Collab.tsx index 0964a7365..be889e2c7 100644 --- a/excalidraw-app/collab/Collab.tsx +++ b/excalidraw-app/collab/Collab.tsx @@ -6,7 +6,7 @@ import { reconcileElements, } from "@excalidraw/excalidraw"; import { ErrorDialog } from "@excalidraw/excalidraw/components/ErrorDialog"; -import { APP_NAME, ENV, EVENT } from "@excalidraw/excalidraw/constants"; +import { APP_NAME, EVENT } from "@excalidraw/excalidraw/constants"; import { IDLE_THRESHOLD, ACTIVE_THRESHOLD, @@ -24,6 +24,8 @@ import { t } from "@excalidraw/excalidraw/i18n"; import { withBatchedUpdates } from "@excalidraw/excalidraw/reactUtils"; import { assertNever, + isDevEnv, + isTestEnv, preventUnload, resolvablePromise, throttleRAF, @@ -240,7 +242,7 @@ class Collab extends PureComponent { appJotaiStore.set(collabAPIAtom, collabAPI); - if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { + if (isTestEnv() || isDevEnv()) { window.collab = window.collab || ({} as Window["collab"]); Object.defineProperties(window, { collab: { @@ -1013,7 +1015,7 @@ declare global { } } -if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { +if (isTestEnv() || isDevEnv()) { window.collab = window.collab || ({} as Window["collab"]); } diff --git a/excalidraw-app/components/AppMainMenu.tsx b/excalidraw-app/components/AppMainMenu.tsx index 996d6912d..4bc6bb471 100644 --- a/excalidraw-app/components/AppMainMenu.tsx +++ b/excalidraw-app/components/AppMainMenu.tsx @@ -6,6 +6,8 @@ import { import { MainMenu } from "@excalidraw/excalidraw/index"; import React from "react"; +import { isDevEnv } from "@excalidraw/excalidraw/utils"; + import type { Theme } from "@excalidraw/excalidraw/element/types"; import { LanguageList } from "../app-language/LanguageList"; @@ -57,7 +59,7 @@ export const AppMainMenu: React.FC<{ > {isExcalidrawPlusSignedUser ? "Sign in" : "Sign up"} - {import.meta.env.DEV && ( + {isDevEnv() && ( { diff --git a/packages/excalidraw/analytics.ts b/packages/excalidraw/analytics.ts index c8ab15b62..edcd07b58 100644 --- a/packages/excalidraw/analytics.ts +++ b/packages/excalidraw/analytics.ts @@ -1,4 +1,7 @@ // place here categories that you want to track. We want to track just a + +import { isDevEnv } from "./utils"; + // small subset of categories at a given time. const ALLOWED_CATEGORIES_TO_TRACK = new Set(["command_palette", "export"]); @@ -21,7 +24,7 @@ export const trackEvent = ( return; } - if (import.meta.env.DEV) { + if (isDevEnv()) { // comment out to debug in dev return; } diff --git a/packages/excalidraw/change.ts b/packages/excalidraw/change.ts index 206f3dcc7..492b7f79e 100644 --- a/packages/excalidraw/change.ts +++ b/packages/excalidraw/change.ts @@ -1,4 +1,3 @@ -import { ENV } from "./constants"; import { BoundElement, BindableElement, @@ -25,7 +24,9 @@ import { arrayToMap, arrayToObject, assertNever, + isDevEnv, isShallowEqual, + isTestEnv, toBrandedType, } from "./utils"; @@ -514,7 +515,7 @@ export class AppStateChange implements Change { // shouldn't really happen, but just in case console.error(`Couldn't apply appstate change`, e); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw e; } @@ -552,7 +553,7 @@ export class AppStateChange implements Change { // if postprocessing fails it does not make sense to bubble up, but let's make sure we know about it console.error(`Couldn't postprocess appstate change deltas.`); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw e; } } finally { @@ -842,7 +843,7 @@ export class ElementsChange implements Change { change = new ElementsChange(added, removed, updated); } - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { ElementsChange.validate(change, "added", this.satisfiesAddition); ElementsChange.validate(change, "removed", this.satisfiesRemoval); ElementsChange.validate(change, "updated", this.satisfiesUpdate); @@ -1106,7 +1107,7 @@ export class ElementsChange implements Change { } catch (e) { console.error(`Couldn't apply elements change`, e); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw e; } @@ -1137,7 +1138,7 @@ export class ElementsChange implements Change { e, ); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw e; } } finally { @@ -1551,7 +1552,7 @@ export class ElementsChange implements Change { // if postprocessing fails, it does not make sense to bubble up, but let's make sure we know about it console.error(`Couldn't postprocess elements change deltas.`); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw e; } } finally { diff --git a/packages/excalidraw/charts.ts b/packages/excalidraw/charts.ts index e54c55f28..20fa8e87a 100644 --- a/packages/excalidraw/charts.ts +++ b/packages/excalidraw/charts.ts @@ -15,6 +15,8 @@ import { import { newElement, newLinearElement, newTextElement } from "./element"; import { randomId } from "./random"; +import { isDevEnv } from "./utils"; + import type { NonDeletedExcalidrawElement } from "./element/types"; export type ChartElements = readonly NonDeletedExcalidrawElement[]; @@ -373,7 +375,7 @@ const chartTypeBar = ( y, groupId, backgroundColor, - import.meta.env.DEV, + isDevEnv(), ), ]; }; @@ -455,7 +457,7 @@ const chartTypeLine = ( y, groupId, backgroundColor, - import.meta.env.DEV, + isDevEnv(), ), line, ...lines, diff --git a/packages/excalidraw/components/App.tsx b/packages/excalidraw/components/App.tsx index 8239493ba..af8c13d7b 100644 --- a/packages/excalidraw/components/App.tsx +++ b/packages/excalidraw/components/App.tsx @@ -85,7 +85,6 @@ import { DRAGGING_THRESHOLD, ELEMENT_SHIFT_TRANSLATE_AMOUNT, ELEMENT_TRANSLATE_AMOUNT, - ENV, EVENT, FRAME_STYLE, IMAGE_MIME_TYPES, @@ -258,6 +257,7 @@ import { getDateTime, isShallowEqual, arrayToMap, + isDevEnv, } from "../utils"; import { createSrcDoc, @@ -2434,7 +2434,7 @@ class App extends React.Component { this.excalidrawContainerValue.container = this.excalidrawContainerRef.current; - if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { + if (isTestEnv() || isDevEnv()) { const setState = this.setState.bind(this); Object.defineProperties(window.h, { state: { @@ -11060,7 +11060,7 @@ declare global { } export const createTestHook = () => { - if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { + if (isTestEnv() || isDevEnv()) { window.h = window.h || ({} as Window["h"]); Object.defineProperties(window.h, { diff --git a/packages/excalidraw/components/Sidebar/Sidebar.tsx b/packages/excalidraw/components/Sidebar/Sidebar.tsx index 8a008fd9f..a702e9330 100644 --- a/packages/excalidraw/components/Sidebar/Sidebar.tsx +++ b/packages/excalidraw/components/Sidebar/Sidebar.tsx @@ -14,7 +14,7 @@ import { useUIAppState } from "../../context/ui-appState"; import { atom, useSetAtom } from "../../editor-jotai"; import { useOutsideClick } from "../../hooks/useOutsideClick"; import { KEYS } from "../../keys"; -import { updateObject } from "../../utils"; +import { isDevEnv, updateObject } from "../../utils"; import { useDevice, useExcalidrawSetAppState } from "../App"; import { Island } from "../Island"; @@ -52,7 +52,7 @@ export const SidebarInner = forwardRef( }: SidebarProps & Omit, "onSelect">, ref: React.ForwardedRef, ) => { - if (import.meta.env.DEV && onDock && docked == null) { + if (isDevEnv() && onDock && docked == null) { console.warn( "Sidebar: `docked` must be set when `onDock` is supplied for the sidebar to be user-dockable. To hide this message, either pass `docked` or remove `onDock`", ); diff --git a/packages/excalidraw/data/reconcile.ts b/packages/excalidraw/data/reconcile.ts index ef644c3aa..06e4a560b 100644 --- a/packages/excalidraw/data/reconcile.ts +++ b/packages/excalidraw/data/reconcile.ts @@ -1,12 +1,11 @@ import throttle from "lodash.throttle"; -import { ENV } from "../constants"; import { orderByFractionalIndex, syncInvalidIndices, validateFractionalIndices, } from "../fractionalIndex"; -import { arrayToMap } from "../utils"; +import { arrayToMap, isDevEnv, isTestEnv } from "../utils"; import type { OrderedExcalidrawElement } from "../element/types"; import type { AppState } from "../types"; @@ -47,11 +46,7 @@ const validateIndicesThrottled = throttle( localElements: readonly OrderedExcalidrawElement[], remoteElements: readonly RemoteExcalidrawElement[], ) => { - if ( - import.meta.env.DEV || - import.meta.env.MODE === ENV.TEST || - window?.DEBUG_FRACTIONAL_INDICES - ) { + if (isDevEnv() || isTestEnv() || window?.DEBUG_FRACTIONAL_INDICES) { // create new instances due to the mutation const elements = syncInvalidIndices( orderedElements.map((x) => ({ ...x })), @@ -59,7 +54,7 @@ const validateIndicesThrottled = throttle( validateFractionalIndices(elements, { // throw in dev & test only, to remain functional on `DEBUG_FRACTIONAL_INDICES` - shouldThrow: import.meta.env.DEV || import.meta.env.MODE === ENV.TEST, + shouldThrow: isTestEnv() || isDevEnv(), includeBoundTextValidation: true, reconciliationContext: { localElements, diff --git a/packages/excalidraw/element/elbowArrow.ts b/packages/excalidraw/element/elbowArrow.ts index a8c22abcc..c72357eb6 100644 --- a/packages/excalidraw/element/elbowArrow.ts +++ b/packages/excalidraw/element/elbowArrow.ts @@ -16,7 +16,7 @@ import { import BinaryHeap from "../binaryheap"; import { getSizeFromPoints } from "../points"; import { aabbForElement, pointInsideBounds } from "../shapes"; -import { invariant, isAnyTrue, tupleToCoors } from "../utils"; +import { invariant, isAnyTrue, isDevEnv, tupleToCoors } from "../utils"; import { bindPointToSnapToElementOutline, @@ -248,7 +248,7 @@ const handleSegmentRenormalization = ( ); } - import.meta.env.DEV && + isDevEnv() && invariant( validateElbowPoints(nextPoints), "Invalid elbow points with fixed segments", diff --git a/packages/excalidraw/element/newElement.ts b/packages/excalidraw/element/newElement.ts index 8d0a9bbd8..67dbed021 100644 --- a/packages/excalidraw/element/newElement.ts +++ b/packages/excalidraw/element/newElement.ts @@ -10,6 +10,7 @@ import { } from "../constants"; import { getLineHeight } from "../fonts"; import { randomInteger, randomId } from "../random"; + import { getFontString, getUpdatedTimestamp } from "../utils"; import { getResizedElementAbsoluteCoords } from "./bounds"; diff --git a/packages/excalidraw/element/textWrapping.ts b/packages/excalidraw/element/textWrapping.ts index 5df7051c0..4585b52c3 100644 --- a/packages/excalidraw/element/textWrapping.ts +++ b/packages/excalidraw/element/textWrapping.ts @@ -1,4 +1,4 @@ -import { ENV } from "../constants"; +import { isDevEnv, isTestEnv } from "../utils"; import { charWidth, getLineWidth } from "./textMeasurements"; @@ -562,7 +562,7 @@ const isSingleCharacter = (maybeSingleCharacter: string) => { * Invariant for the word wrapping algorithm. */ const satisfiesWordInvariant = (word: string) => { - if (import.meta.env.MODE === ENV.TEST || import.meta.env.DEV) { + if (isTestEnv() || isDevEnv()) { if (/\s/.test(word)) { throw new Error("Word should not contain any whitespaces!"); } diff --git a/packages/excalidraw/i18n.ts b/packages/excalidraw/i18n.ts index 47bae5979..095b418dd 100644 --- a/packages/excalidraw/i18n.ts +++ b/packages/excalidraw/i18n.ts @@ -2,6 +2,8 @@ import { useAtomValue, editorJotaiStore, atom } from "./editor-jotai"; import fallbackLangData from "./locales/en.json"; import percentages from "./locales/percentages.json"; +import { isDevEnv } from "./utils"; + import type { NestedKeyOf } from "./utility-types"; const COMPLETION_THRESHOLD = 85; @@ -73,7 +75,7 @@ export const languages: Language[] = [ ]; const TEST_LANG_CODE = "__test__"; -if (import.meta.env.DEV) { +if (isDevEnv()) { languages.unshift( { code: TEST_LANG_CODE, label: "test language" }, { diff --git a/packages/excalidraw/scene/Scene.ts b/packages/excalidraw/scene/Scene.ts index 0eab8b80e..f990e45af 100644 --- a/packages/excalidraw/scene/Scene.ts +++ b/packages/excalidraw/scene/Scene.ts @@ -1,6 +1,5 @@ import throttle from "lodash.throttle"; -import { ENV } from "../constants"; import { isNonDeletedElement } from "../element"; import { isFrameLikeElement } from "../element/typeChecks"; import { @@ -10,7 +9,7 @@ import { } from "../fractionalIndex"; import { getElementsInGroup } from "../groups"; import { randomInteger } from "../random"; -import { arrayToMap } from "../utils"; +import { arrayToMap, isDevEnv, isTestEnv } from "../utils"; import { toBrandedType } from "../utils"; import { getSelectedElements } from "./selection"; @@ -57,14 +56,10 @@ const getNonDeletedElements = ( const validateIndicesThrottled = throttle( (elements: readonly ExcalidrawElement[]) => { - if ( - import.meta.env.DEV || - import.meta.env.MODE === ENV.TEST || - window?.DEBUG_FRACTIONAL_INDICES - ) { + if (isDevEnv() || isTestEnv() || window?.DEBUG_FRACTIONAL_INDICES) { validateFractionalIndices(elements, { // throw only in dev & test, to remain functional on `DEBUG_FRACTIONAL_INDICES` - shouldThrow: import.meta.env.DEV || import.meta.env.MODE === ENV.TEST, + shouldThrow: isDevEnv() || isTestEnv(), includeBoundTextValidation: true, }); } diff --git a/packages/excalidraw/store.ts b/packages/excalidraw/store.ts index 1723d0aa1..83d670d43 100644 --- a/packages/excalidraw/store.ts +++ b/packages/excalidraw/store.ts @@ -1,9 +1,8 @@ import { getDefaultAppState } from "./appState"; import { AppStateChange, ElementsChange } from "./change"; -import { ENV } from "./constants"; import { newElementWith } from "./element/mutateElement"; import { Emitter } from "./emitter"; -import { isShallowEqual } from "./utils"; +import { isDevEnv, isShallowEqual, isTestEnv } from "./utils"; import { deepCopyElement } from "./element/duplicate"; @@ -257,7 +256,7 @@ export class Store implements IStore { const message = `There can be at most three store actions scheduled at the same time, but there are "${this.scheduledActions.size}".`; console.error(message, this.scheduledActions.values()); - if (import.meta.env.DEV || import.meta.env.MODE === ENV.TEST) { + if (isTestEnv() || isDevEnv()) { throw new Error(message); } } diff --git a/packages/excalidraw/utils.ts b/packages/excalidraw/utils.ts index 84f6637f1..18b6f2a93 100644 --- a/packages/excalidraw/utils.ts +++ b/packages/excalidraw/utils.ts @@ -169,7 +169,7 @@ export const throttleRAF = ( }; const ret = (...args: T) => { - if (import.meta.env.MODE === "test") { + if (isTestEnv()) { fn(...args); return; } From 6c3a434f2a8dd92d6ccaefb1b393bc3f164164d5 Mon Sep 17 00:00:00 2001 From: Mubaraq Wahab <48601635+mubaraqwahab@users.noreply.github.com> Date: Tue, 25 Mar 2025 14:32:15 +0100 Subject: [PATCH 47/51] docs: Fix table rendering and broken links in Props page (#9293) * Fix table rendering and broken links --------- Co-authored-by: Marcel Mraz --- dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx index e25aedcf4..5c2a5501b 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/props/props.mdx @@ -3,7 +3,7 @@ All `props` are _optional_. | Name | Type | Default | Description | -| --- | --- | --- | --- | --- | --- | --- | --- | --- | +| --- | --- | --- | --- | | [`initialData`](/docs/@excalidraw/excalidraw/api/props/initialdata) | `object` | `null` | Promise | `null` | The initial data with which app loads. | | [`excalidrawAPI`](/docs/@excalidraw/excalidraw/api/props/excalidraw-api) | `function` | \_ | Callback triggered with the excalidraw api once rendered | | [`isCollaborating`](#iscollaborating) | `boolean` | \_ | This indicates if the app is in `collaboration` mode | @@ -13,7 +13,7 @@ All `props` are _optional_. | [`onScrollChange`](#onscrollchange) | `function` | \_ | This prop if passed gets triggered when scrolling the canvas. | | [`onPaste`](#onpaste) | `function` | \_ | Callback to be triggered if passed when something is pasted into the scene | | [`onLibraryChange`](#onlibrarychange) | `function` | \_ | The callback if supplied is triggered when the library is updated and receives the library items. | -| [`generateLinkForSelection`](#generateLinkForSelection) | `function` | \_ | Allows you to override `url` generation when linking to Excalidraw elements. | +| [`generateLinkForSelection`](#generatelinkforselection) | `function` | \_ | Allows you to override `url` generation when linking to Excalidraw elements. | | [`onLinkOpen`](#onlinkopen) | `function` | \_ | The callback if supplied is triggered when any link is opened. | | [`langCode`](#langcode) | `string` | `en` | Language code string to be used in Excalidraw | | [`renderTopRightUI`](/docs/@excalidraw/excalidraw/api/props/render-props#rendertoprightui) | `function` | \_ | Render function that renders custom UI in top right corner | @@ -29,7 +29,7 @@ All `props` are _optional_. | [`handleKeyboardGlobally`](#handlekeyboardglobally) | `boolean` | `false` | Indicates whether to bind the keyboard events to document. | | [`autoFocus`](#autofocus) | `boolean` | `false` | Indicates whether to focus the Excalidraw component on page load | | [`generateIdForFile`](#generateidforfile) | `function` | \_ | Allows you to override `id` generation for files added on canvas | -| [`validateEmbeddable`](#validateEmbeddable) | string[] | `boolean | RegExp | RegExp[] | ((link: string) => boolean | undefined)` | \_ | use for custom src url validation | +| [`validateEmbeddable`](#validateembeddable) | `string[]` \| `boolean` \| `RegExp` \| `RegExp[]` \| ((link: string) => boolean | undefined) | \_ | use for custom src url validation | | [`renderEmbeddable`](/docs/@excalidraw/excalidraw/api/props/render-props#renderEmbeddable) | `function` | \_ | Render function that can override the built-in `

= [a: P, b: P] & { + _brand: "excalimath__rectangle"; +}; + // // Polygon // @@ -120,11 +127,14 @@ export type PolarCoords = [ ]; /** - * Angles are in radians and centered on 0, 0. Zero radians on a 1 radius circle - * corresponds to (1, 0) cartesian coordinates (point), i.e. to the "right". + An ellipse is specified by its center, angle, and its major and minor axes + but for the sake of simplicity, we've used halfWidth and halfHeight instead + in replace of semi major and semi minor axes */ -export type SymmetricArc = { - radius: number; - startAngle: number; - endAngle: number; +export type Ellipse = { + center: Point; + halfWidth: number; + halfHeight: number; +} & { + _brand: "excalimath_ellipse"; }; diff --git a/packages/math/vector.ts b/packages/math/vector.ts index d7d51b14e..246722067 100644 --- a/packages/math/vector.ts +++ b/packages/math/vector.ts @@ -137,12 +137,9 @@ export function vectorMagnitude(v: Vector) { export const vectorNormalize = (v: Vector): Vector => { const m = vectorMagnitude(v); + if (m === 0) { + return vector(0, 0); + } + return vector(v[0] / m, v[1] / m); }; - -/** - * Project the first vector onto the second vector - */ -export const vectorProjection = (a: Vector, b: Vector) => { - return vectorScale(b, vectorDot(a, b) / vectorDot(b, b)); -}; diff --git a/packages/utils/test-utils.ts b/packages/utils/test-utils.ts new file mode 100644 index 000000000..1dfd14cac --- /dev/null +++ b/packages/utils/test-utils.ts @@ -0,0 +1,33 @@ +import { diffStringsUnified } from "jest-diff"; + +expect.extend({ + toCloselyEqualPoints(received, expected, precision) { + if (!Array.isArray(received) || !Array.isArray(expected)) { + throw new Error("expected and received are not point arrays"); + } + + const COMPARE = 1 / Math.pow(10, precision || 2); + const pass = expected.every( + (point, idx) => + Math.abs(received[idx]?.[0] - point[0]) < COMPARE && + Math.abs(received[idx]?.[1] - point[1]) < COMPARE, + ); + + if (!pass) { + return { + message: () => ` The provided array of points are not close enough. + +${diffStringsUnified( + JSON.stringify(expected, undefined, 2), + JSON.stringify(received, undefined, 2), +)}`, + pass: false, + }; + } + + return { + message: () => `expected ${received} to not be close to ${expected}`, + pass: true, + }; + }, +}); From 392118bf260529aba49371db78be4439ac2ede9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1rk=20Tolm=C3=A1cs?= Date: Fri, 28 Feb 2025 15:36:41 +0100 Subject: [PATCH 26/51] fix: Fix elbow arrow fixed binding on restore (#9197) --- packages/excalidraw/element/binding.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/excalidraw/element/binding.ts b/packages/excalidraw/element/binding.ts index 332a70fcd..2ac8b7c69 100644 --- a/packages/excalidraw/element/binding.ts +++ b/packages/excalidraw/element/binding.ts @@ -2206,9 +2206,13 @@ export const normalizeFixedPoint = ( ): T extends null ? null : FixedPoint => { // Do not allow a precise 0.5 for fixed point ratio // to avoid jumping arrow heading due to floating point imprecision - if (fixedPoint && (fixedPoint[0] === 0.5 || fixedPoint[1] === 0.5)) { + if ( + fixedPoint && + (Math.abs(fixedPoint[0] - 0.5) < 0.0001 || + Math.abs(fixedPoint[1] - 0.5) < 0.0001) + ) { return fixedPoint.map((ratio) => - ratio === 0.5 ? 0.5001 : ratio, + Math.abs(ratio - 0.5) < 0.0001 ? 0.5001 : ratio, ) as T extends null ? null : FixedPoint; } return fixedPoint as any as T extends null ? null : FixedPoint; From ecef5d12f4af4f70e240fc54fb626c16d005eee3 Mon Sep 17 00:00:00 2001 From: Marcel Mraz Date: Fri, 28 Feb 2025 16:49:09 +0100 Subject: [PATCH 27/51] =?UTF-8?q?chore:=20release=20@excalidraw/excalidraw?= =?UTF-8?q?@18.0.0=20=20=F0=9F=8E=89=20(#9127)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 - README.md | 10 +- .../@excalidraw/excalidraw/api/constants.mdx | 10 +- .../excalidraw/api/props/excalidraw-api.mdx | 15 +- .../excalidraw/api/utils/restore.mdx | 9 +- .../@excalidraw/excalidraw/development.mdx | 8 +- dev-docs/docs/@excalidraw/excalidraw/faq.mdx | 2 - .../@excalidraw/excalidraw/installation.mdx | 44 +- .../@excalidraw/excalidraw/integration.mdx | 63 +- dev-docs/docusaurus.config.js | 23 + dev-docs/package.json | 6 +- dev-docs/src/theme/ReactLiveScope/index.js | 7 + dev-docs/yarn.lock | 1380 ++++++++++++++++- examples/excalidraw/package.json | 13 - examples/excalidraw/tsconfig.json | 3 - .../with-script-in-browser/vite.config.mts | 11 - examples/excalidraw/yarn.lock | 313 ---- .../{excalidraw => }/with-nextjs/.gitignore | 0 .../{excalidraw => }/with-nextjs/README.md | 0 .../with-nextjs/next.config.js | 0 .../{excalidraw => }/with-nextjs/package.json | 3 +- .../with-nextjs/public/images/doremon.png | Bin .../with-nextjs/public/images/excalibot.png | Bin .../with-nextjs/public/images/pika.jpeg | Bin .../with-nextjs/public/images/rocket.jpeg | Bin .../with-nextjs/src/app/favicon.ico | Bin .../with-nextjs/src/app/layout.tsx | 0 .../with-nextjs/src/app/page.tsx | 0 .../with-nextjs/src/common.scss | 0 .../with-nextjs/src/excalidrawWrapper.tsx | 2 +- .../src/pages/excalidraw-in-pages.tsx | 0 .../with-nextjs/tsconfig.json | 0 .../{excalidraw => }/with-nextjs/vercel.json | 0 .../{excalidraw => }/with-nextjs/yarn.lock | 0 .../.codesandbox/Dockerfile | 5 + .../.codesandbox/tasks.json | 35 + .../with-script-in-browser/.gitignore | 0 .../components/CustomFooter.tsx | 3 +- .../components/ExampleApp.scss | 0 .../components/ExampleApp.tsx | 6 +- .../components/MobileFooter.tsx | 3 +- .../components/sidebar/ExampleSidebar.scss | 0 .../components/sidebar/ExampleSidebar.tsx | 2 +- .../with-script-in-browser/index.html | 7 +- .../with-script-in-browser/index.tsx | 2 +- .../initialData.tsx | 0 .../with-script-in-browser/package.json | 9 +- .../public/images/doremon.png | Bin .../public/images/excalibot.png | Bin .../public/images/pika.jpeg | Bin .../public/images/rocket.jpeg | Bin examples/with-script-in-browser/tsconfig.json | 9 + .../utils.ts | 3 +- .../with-script-in-browser/vercel.json | 0 .../with-script-in-browser/vite.config.mts | 19 + excalidraw-app/App.tsx | 62 +- excalidraw-app/CustomStats.tsx | 14 +- excalidraw-app/ExcalidrawPlusIframeExport.tsx | 8 +- excalidraw-app/app-language/LanguageList.tsx | 2 +- .../app-language/language-detector.ts | 2 +- excalidraw-app/collab/Collab.tsx | 47 +- excalidraw-app/collab/CollabError.tsx | 4 +- excalidraw-app/collab/Portal.tsx | 16 +- excalidraw-app/components/AI.tsx | 8 +- excalidraw-app/components/AppFooter.tsx | 2 +- excalidraw-app/components/AppMainMenu.tsx | 6 +- .../components/AppWelcomeScreen.tsx | 8 +- excalidraw-app/components/DebugCanvas.tsx | 10 +- excalidraw-app/components/EncryptedIcon.tsx | 6 +- .../components/ExportToExcalidrawPlus.tsx | 24 +- excalidraw-app/components/GitHubCorner.tsx | 4 +- .../components/TopErrorBoundary.tsx | 4 +- excalidraw-app/data/FileManager.ts | 16 +- excalidraw-app/data/LocalData.ts | 18 +- excalidraw-app/data/firebase.ts | 20 +- excalidraw-app/data/index.ts | 28 +- excalidraw-app/data/localStorage.ts | 8 +- excalidraw-app/global.d.ts | 3 + excalidraw-app/share/ShareDialog.tsx | 22 +- excalidraw-app/tests/LanguageList.test.tsx | 6 +- excalidraw-app/tests/MobileMenu.test.tsx | 4 +- excalidraw-app/tests/collab.test.tsx | 24 +- excalidraw-app/useHandleAppTheme.ts | 8 +- excalidraw-app/vite.config.mts | 30 +- package.json | 8 +- packages/excalidraw/CHANGELOG.md | 724 ++++++++- packages/excalidraw/README.md | 36 +- .../excalidraw/actions/actionAddToLibrary.ts | 8 +- packages/excalidraw/actions/actionAlign.tsx | 14 +- .../excalidraw/actions/actionBoundText.tsx | 8 +- packages/excalidraw/actions/actionCanvas.tsx | 26 +- .../excalidraw/actions/actionClipboard.tsx | 28 +- .../excalidraw/actions/actionCropEditor.tsx | 4 +- .../actions/actionDeleteSelected.tsx | 12 +- .../excalidraw/actions/actionDistribute.tsx | 6 +- .../actions/actionDuplicateSelection.tsx | 6 +- .../excalidraw/actions/actionElementLink.ts | 17 +- .../excalidraw/actions/actionElementLock.ts | 6 +- packages/excalidraw/actions/actionExport.tsx | 24 +- .../excalidraw/actions/actionFinalize.tsx | 8 +- .../excalidraw/actions/actionFlip.test.tsx | 2 +- packages/excalidraw/actions/actionFlip.ts | 6 +- packages/excalidraw/actions/actionFrame.ts | 16 +- packages/excalidraw/actions/actionGroup.tsx | 24 +- packages/excalidraw/actions/actionHistory.tsx | 8 +- .../excalidraw/actions/actionLinearEditor.tsx | 4 +- packages/excalidraw/actions/actionLink.tsx | 4 +- packages/excalidraw/actions/actionMenu.tsx | 8 +- .../excalidraw/actions/actionNavigate.tsx | 6 +- .../excalidraw/actions/actionProperties.tsx | 53 +- .../excalidraw/actions/actionSelectAll.ts | 4 +- packages/excalidraw/actions/actionStyles.ts | 8 +- .../actions/actionTextAutoResize.ts | 4 +- .../actions/actionToggleGridMode.tsx | 4 +- .../actions/actionToggleObjectsSnapMode.tsx | 4 +- .../actions/actionToggleSearchMenu.ts | 6 +- .../excalidraw/actions/actionToggleStats.tsx | 4 +- .../actions/actionToggleViewMode.tsx | 4 +- .../actions/actionToggleZenMode.tsx | 4 +- packages/excalidraw/actions/actionZindex.tsx | 10 +- packages/excalidraw/actions/types.ts | 4 +- packages/excalidraw/charts.ts | 4 +- packages/excalidraw/clients.ts | 2 +- packages/excalidraw/components/App.tsx | 74 +- .../components/ImageExportDialog.tsx | 2 +- packages/excalidraw/components/LayerUI.tsx | 9 +- .../excalidraw/components/PublishLibrary.tsx | 2 +- packages/excalidraw/components/SearchMenu.tsx | 4 +- .../components/Sidebar/Sidebar.scss | 2 +- .../excalidraw/components/Sidebar/Sidebar.tsx | 3 + .../excalidraw/components/Stats/Angle.tsx | 4 +- .../excalidraw/components/Stats/Dimension.tsx | 2 +- .../excalidraw/components/Stats/DragInput.tsx | 10 +- .../components/Stats/MultiAngle.tsx | 4 +- .../components/Stats/MultiDimension.tsx | 2 +- .../components/Stats/MultiPosition.tsx | 2 +- .../excalidraw/components/Stats/Position.tsx | 2 +- .../excalidraw/components/Stats/index.tsx | 4 +- .../components/Stats/stats.test.tsx | 4 +- packages/excalidraw/components/Stats/utils.ts | 4 +- .../components/TTDDialog/TTDDialog.tsx | 2 +- .../components/hyperlink/Hyperlink.tsx | 2 +- .../components/hyperlink/helpers.ts | 4 +- packages/excalidraw/constants.ts | 12 +- packages/excalidraw/css/theme.scss | 2 +- packages/excalidraw/css/variables.module.scss | 8 - packages/excalidraw/data/restore.ts | 4 +- packages/excalidraw/data/transform.test.ts | 2 +- packages/excalidraw/data/transform.ts | 2 +- packages/excalidraw/element/binding.ts | 6 +- packages/excalidraw/element/bounds.test.ts | 4 +- packages/excalidraw/element/bounds.ts | 4 +- packages/excalidraw/element/collision.ts | 15 +- packages/excalidraw/element/cropElement.ts | 2 +- packages/excalidraw/element/distance.ts | 6 +- .../excalidraw/element/elbowArrow.test.tsx | 4 +- packages/excalidraw/element/elbowArrow.ts | 2 +- packages/excalidraw/element/embeddable.ts | 4 +- packages/excalidraw/element/flowchart.ts | 2 +- packages/excalidraw/element/heading.ts | 4 +- .../excalidraw/element/linearElementEditor.ts | 4 +- packages/excalidraw/element/mutateElement.ts | 2 +- .../excalidraw/element/newElement.test.ts | 4 +- packages/excalidraw/element/newElement.ts | 2 +- packages/excalidraw/element/resizeElements.ts | 4 +- packages/excalidraw/element/resizeTest.ts | 4 +- .../excalidraw/element/textWysiwyg.test.tsx | 2 +- .../excalidraw/element/transformHandles.ts | 4 +- packages/excalidraw/element/types.ts | 2 +- packages/excalidraw/element/utils.ts | 4 +- .../excalidraw/fonts/ExcalidrawFontFace.ts | 4 +- packages/excalidraw/frame.ts | 7 +- .../excalidraw/hooks/useLibraryItemSvg.ts | 2 +- packages/excalidraw/index.tsx | 7 +- packages/excalidraw/package.json | 53 +- packages/excalidraw/points.ts | 6 +- .../excalidraw/renderer/interactiveScene.ts | 2 +- packages/excalidraw/renderer/renderElement.ts | 2 +- packages/excalidraw/renderer/renderSnaps.ts | 2 +- packages/excalidraw/scene/Shape.ts | 2 +- packages/excalidraw/scene/normalize.ts | 2 +- packages/excalidraw/scene/types.ts | 2 +- packages/excalidraw/shapes.tsx | 4 +- packages/excalidraw/snapping.ts | 4 +- packages/excalidraw/store.ts | 24 +- packages/excalidraw/tests/binding.test.tsx | 2 +- .../excalidraw/tests/cropElement.test.tsx | 2 + .../excalidraw/tests/data/restore.test.ts | 2 +- .../tests/fixtures/elementFixture.ts | 2 +- packages/excalidraw/tests/flip.test.tsx | 4 +- packages/excalidraw/tests/helpers/api.ts | 2 +- packages/excalidraw/tests/helpers/ui.ts | 4 +- packages/excalidraw/tests/history.test.tsx | 160 +- .../tests/linearElementEditor.test.tsx | 4 +- .../excalidraw/tests/packages/events.test.tsx | 4 +- packages/excalidraw/tests/resize.test.tsx | 4 +- .../excalidraw/tests/scene/export.test.ts | 4 +- packages/excalidraw/tsconfig.json | 17 +- packages/excalidraw/types.ts | 11 +- packages/excalidraw/utils.ts | 2 +- packages/excalidraw/visualdebug.ts | 6 +- packages/math/global.d.ts | 3 + packages/math/package.json | 16 +- packages/math/range.ts | 2 +- packages/math/tsconfig.json | 24 + packages/math/webpack.prod.config.js | 55 - packages/tsconfig.dev.json | 11 - packages/tsconfig.prod.json | 9 - packages/utils/bbox.ts | 4 +- packages/utils/collision.test.ts | 4 +- packages/utils/collision.ts | 4 +- packages/utils/export.test.ts | 6 +- packages/utils/export.ts | 18 +- packages/utils/geometry/geometry.test.ts | 9 +- packages/utils/geometry/shape.ts | 10 +- packages/utils/global.d.ts | 4 +- packages/utils/index.ts | 2 +- packages/utils/package.json | 34 +- packages/utils/tsconfig.json | 16 +- packages/utils/utils.unmocked.test.ts | 10 +- packages/utils/webpack.prod.config.js | 60 - packages/utils/withinBounds.test.ts | 4 +- packages/utils/withinBounds.ts | 14 +- scripts/buildExample.mjs | 36 - scripts/buildMath.js | 116 +- scripts/buildPackage.js | 168 +- scripts/buildUtils.js | 140 +- scripts/prerelease.js | 2 +- scripts/woff2/woff2-esbuild-plugins.js | 7 +- tsconfig.json | 16 +- vitest.config.mts | 30 + yarn.lock | 1251 ++------------- 232 files changed, 3412 insertions(+), 2851 deletions(-) delete mode 100644 examples/excalidraw/package.json delete mode 100644 examples/excalidraw/tsconfig.json delete mode 100644 examples/excalidraw/with-script-in-browser/vite.config.mts delete mode 100644 examples/excalidraw/yarn.lock rename examples/{excalidraw => }/with-nextjs/.gitignore (100%) rename examples/{excalidraw => }/with-nextjs/README.md (100%) rename examples/{excalidraw => }/with-nextjs/next.config.js (100%) rename examples/{excalidraw => }/with-nextjs/package.json (84%) rename examples/{excalidraw => }/with-nextjs/public/images/doremon.png (100%) rename examples/{excalidraw => }/with-nextjs/public/images/excalibot.png (100%) rename examples/{excalidraw => }/with-nextjs/public/images/pika.jpeg (100%) rename examples/{excalidraw => }/with-nextjs/public/images/rocket.jpeg (100%) rename examples/{excalidraw => }/with-nextjs/src/app/favicon.ico (100%) rename examples/{excalidraw => }/with-nextjs/src/app/layout.tsx (100%) rename examples/{excalidraw => }/with-nextjs/src/app/page.tsx (100%) rename examples/{excalidraw => }/with-nextjs/src/common.scss (100%) rename examples/{excalidraw => }/with-nextjs/src/excalidrawWrapper.tsx (87%) rename examples/{excalidraw => }/with-nextjs/src/pages/excalidraw-in-pages.tsx (100%) rename examples/{excalidraw => }/with-nextjs/tsconfig.json (100%) rename examples/{excalidraw => }/with-nextjs/vercel.json (100%) rename examples/{excalidraw => }/with-nextjs/yarn.lock (100%) create mode 100644 examples/with-script-in-browser/.codesandbox/Dockerfile create mode 100644 examples/with-script-in-browser/.codesandbox/tasks.json rename examples/{excalidraw => }/with-script-in-browser/.gitignore (100%) rename examples/{excalidraw => with-script-in-browser}/components/CustomFooter.tsx (98%) rename examples/{excalidraw => with-script-in-browser}/components/ExampleApp.scss (100%) rename examples/{excalidraw => with-script-in-browser}/components/ExampleApp.tsx (99%) rename examples/{excalidraw => with-script-in-browser}/components/MobileFooter.tsx (94%) rename examples/{excalidraw => with-script-in-browser}/components/sidebar/ExampleSidebar.scss (100%) rename examples/{excalidraw => with-script-in-browser}/components/sidebar/ExampleSidebar.tsx (94%) rename examples/{excalidraw => }/with-script-in-browser/index.html (74%) rename examples/{excalidraw => }/with-script-in-browser/index.tsx (93%) rename examples/{excalidraw => with-script-in-browser}/initialData.tsx (100%) rename examples/{excalidraw => }/with-script-in-browser/package.json (50%) rename examples/{excalidraw => }/with-script-in-browser/public/images/doremon.png (100%) rename examples/{excalidraw => }/with-script-in-browser/public/images/excalibot.png (100%) rename examples/{excalidraw => }/with-script-in-browser/public/images/pika.jpeg (100%) rename examples/{excalidraw => }/with-script-in-browser/public/images/rocket.jpeg (100%) create mode 100644 examples/with-script-in-browser/tsconfig.json rename examples/{excalidraw => with-script-in-browser}/utils.ts (97%) rename examples/{excalidraw => }/with-script-in-browser/vercel.json (100%) create mode 100644 examples/with-script-in-browser/vite.config.mts create mode 100644 packages/math/global.d.ts create mode 100644 packages/math/tsconfig.json delete mode 100644 packages/math/webpack.prod.config.js delete mode 100644 packages/tsconfig.dev.json delete mode 100644 packages/tsconfig.prod.json delete mode 100644 packages/utils/webpack.prod.config.js delete mode 100644 scripts/buildExample.mjs diff --git a/.gitignore b/.gitignore index 81b63339f..6f9407fad 100644 --- a/.gitignore +++ b/.gitignore @@ -25,5 +25,4 @@ packages/excalidraw/types coverage dev-dist html -examples/**/bundle.* meta*.json \ No newline at end of file diff --git a/README.md b/README.md index 3c7265a80..9458779ce 100644 --- a/README.md +++ b/README.md @@ -87,13 +87,11 @@ We'll be adding these features as drop-in plugins for the npm package in the fut **Note:** following instructions are for installing the Excalidraw [npm package](https://www.npmjs.com/package/@excalidraw/excalidraw) when integrating Excalidraw into your own app. To run the repository locally for development, please refer to our [Development Guide](https://docs.excalidraw.com/docs/introduction/development). -``` +Use `npm` or `yarn` to install the package. + +```bash npm install react react-dom @excalidraw/excalidraw -``` - -or via yarn - -``` +# or yarn add react react-dom @excalidraw/excalidraw ``` diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/constants.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/constants.mdx index 411cbb442..36fbfa758 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/constants.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/constants.mdx @@ -8,15 +8,15 @@ import { FONT_FAMILY } from "@excalidraw/excalidraw"; ``` -`FONT_FAMILY` contains all the font families used in `Excalidraw` as explained below +`FONT_FAMILY` contains all the font families used in `Excalidraw`. The default families are the following: | Font Family | Description | | ----------- | ---------------------- | -| `Virgil` | The `Hand-drawn` font | -| `Helvetica` | The `Normal` Font | -| `Cascadia` | The `Code` Font | +| `Excalifont` | The `Hand-drawn` font | +| `Nunito` | The `Normal` Font | +| `Comic Shanns` | The `Code` Font | -Defaults to `FONT_FAMILY.Virgil` unless passed in `initialData.appState.currentItemFontFamily`. +Pre-selected family is `FONT_FAMILY.Excalifont`, unless it's overriden with `initialData.appState.currentItemFontFamily`. ### THEME diff --git a/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx b/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx index f68b4bd11..b7a3bab5f 100644 --- a/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx +++ b/dev-docs/docs/@excalidraw/excalidraw/api/props/excalidraw-api.mdx @@ -65,7 +65,7 @@ You can use this function to update the scene with the sceneData. It accepts the | `elements` | [`ImportedDataState["elements"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L38) | The `elements` to be updated in the scene | | `appState` | [`ImportedDataState["appState"]`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/data/types.ts#L39) | The `appState` to be updated in the scene. | | `collaborators` | MapCollaborator> | The list of collaborators to be updated in the scene. | -| `commitToStore` | `boolean` | Implies if the change should be captured and commited to the `store`. Commited changes are emmitted and listened to by other components, such as `History` for undo / redo purposes. Defaults to `false`. | +| `captureUpdate` | [`CaptureUpdateAction`](https://github.com/excalidraw/excalidraw/blob/master/packages/excalidraw/store.ts#L40) | Controls which updates should be captured by the `Store`. Captured updates are emmitted and listened to by other components, such as `History` for undo / redo purposes. | ```jsx live function App() { @@ -105,6 +105,7 @@ function App() { appState: { viewBackgroundColor: "#edf2ff", }, + captureUpdate: CaptureUpdateAction.IMMEDIATELY, }; excalidrawAPI.updateScene(sceneData); }; @@ -121,6 +122,18 @@ function App() { } ``` +#### captureUpdate + +You can use the `captureUpdate` to influence undo / redo behaviour. + +> **NOTE**: Some updates are not observed by the store / history - i.e. updates to `collaborators` object or parts of `AppState` which are not observed (not `ObservedAppState`). Such updates will never make it to the undo / redo stacks, regardless of the passed `captureUpdate` value. + +| | `captureUpdate` value | Notes | +| --- | --- | --- | +| _Immediately undoable_ | `CaptureUpdateAction.IMMEDIATELY` | Use for updates which should be captured. Should be used for most of the local updates. These updates will _immediately_ make it to the local undo / redo stacks. | +| _Eventually undoable_ | `CaptureUpdateAction.EVENTUALLY` | Use for updates which should not be captured immediately - likely exceptions which are part of some async multi-step process. Otherwise, all such updates would end up being captured with the next `CaptureUpdateAction.IMMEDIATELY` - triggered either by the next `updateScene` or internally by the editor. These updates will _eventually_ make it to the local undo / redo stacks. | +| _Never undoable_ | `CaptureUpdateAction.NEVER` | Use for updates which should never be recorded, such as remote updates or scene initialization. These updates will _never_ make it to the local undo / redo stacks. | + ### updateLibrary

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 z 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