Merge branch 'master' into ryan-di/shape-switch

This commit is contained in:
dwelle 2025-04-30 12:30:13 +02:00
commit 86281329b5
13 changed files with 107 additions and 129 deletions

View file

@ -32,6 +32,12 @@
"name": "jotai", "name": "jotai",
"message": "Do not import from \"jotai\" directly. Use our app-specific modules (\"editor-jotai\" or \"app-jotai\")." "message": "Do not import from \"jotai\" directly. Use our app-specific modules (\"editor-jotai\" or \"app-jotai\")."
} }
],
"react/jsx-no-target-blank": [
"error",
{
"allowReferrer": true
}
] ]
} }
} }

View file

@ -73,7 +73,7 @@ export const AIComponents = ({
</br> </br>
<div>You can also try <a href="${ <div>You can also try <a href="${
import.meta.env.VITE_APP_PLUS_LP import.meta.env.VITE_APP_PLUS_LP
}/plus?utm_source=excalidraw&utm_medium=app&utm_content=d2c" target="_blank" rel="noreferrer noopener">Excalidraw+</a> to get more requests.</div> }/plus?utm_source=excalidraw&utm_medium=app&utm_content=d2c" target="_blank" rel="noopener">Excalidraw+</a> to get more requests.</div>
</div> </div>
</body> </body>
</html>`, </html>`,

View file

@ -10,7 +10,7 @@ export const EncryptedIcon = () => {
className="encrypted-icon tooltip" className="encrypted-icon tooltip"
href="https://plus.excalidraw.com/blog/end-to-end-encryption" href="https://plus.excalidraw.com/blog/end-to-end-encryption"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener"
aria-label={t("encrypted.link")} aria-label={t("encrypted.link")}
> >
<Tooltip label={t("encrypted.tooltip")} long={true}> <Tooltip label={t("encrypted.tooltip")} long={true}>

View file

@ -10,7 +10,7 @@ export const ExcalidrawPlusAppLink = () => {
import.meta.env.VITE_APP_PLUS_APP import.meta.env.VITE_APP_PLUS_APP
}?utm_source=excalidraw&utm_medium=app&utm_content=signedInUserRedirectButton#excalidraw-redirect`} }?utm_source=excalidraw&utm_medium=app&utm_content=signedInUserRedirectButton#excalidraw-redirect`}
target="_blank" target="_blank"
rel="noreferrer" rel="noopener"
className="plus-button" className="plus-button"
> >
Go to Excalidraw+ Go to Excalidraw+

View file

@ -198,7 +198,7 @@ exports[`Test MobileMenu > should initialize with welcome screen and hide once u
<a <a
class="welcome-screen-menu-item " class="welcome-screen-menu-item "
href="undefined/plus?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenGuest" href="undefined/plus?utm_source=excalidraw&utm_medium=app&utm_content=welcomeScreenGuest"
rel="noreferrer" rel="noopener"
target="_blank" target="_blank"
> >
<div <div

View file

@ -276,15 +276,6 @@ const getBindingStrategyForDraggingArrowEndpoints = (
zoom, zoom,
) )
: null // If binding is disabled and start is dragged, break all binds : null // If binding is disabled and start is dragged, break all binds
: !isElbowArrow(selectedElement)
? // We have to update the focus and gap of the binding, so let's rebind
getElligibleElementForBindingElement(
selectedElement,
"start",
elementsMap,
elements,
zoom,
)
: "keep"; : "keep";
const end = endDragged const end = endDragged
? isBindingEnabled ? isBindingEnabled
@ -296,15 +287,6 @@ const getBindingStrategyForDraggingArrowEndpoints = (
zoom, zoom,
) )
: null // If binding is disabled and end is dragged, break all binds : null // If binding is disabled and end is dragged, break all binds
: !isElbowArrow(selectedElement)
? // We have to update the focus and gap of the binding, so let's rebind
getElligibleElementForBindingElement(
selectedElement,
"end",
elementsMap,
elements,
zoom,
)
: "keep"; : "keep";
return [start, end]; return [start, end];

View file

@ -129,7 +129,6 @@ export class AnimatedTrail implements Trail {
} }
private update() { private update() {
this.pastTrails = [];
this.start(); this.start();
if (this.trailAnimation) { if (this.trailAnimation) {
this.trailAnimation.setAttribute("begin", "indefinite"); this.trailAnimation.setAttribute("begin", "indefinite");

View file

@ -21,7 +21,7 @@ const Header = () => (
className="HelpDialog__btn" className="HelpDialog__btn"
href="https://docs.excalidraw.com" href="https://docs.excalidraw.com"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener"
> >
<div className="HelpDialog__link-icon">{ExternalLinkIcon}</div> <div className="HelpDialog__link-icon">{ExternalLinkIcon}</div>
{t("helpDialog.documentation")} {t("helpDialog.documentation")}
@ -30,7 +30,7 @@ const Header = () => (
className="HelpDialog__btn" className="HelpDialog__btn"
href="https://plus.excalidraw.com/blog" href="https://plus.excalidraw.com/blog"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener"
> >
<div className="HelpDialog__link-icon">{ExternalLinkIcon}</div> <div className="HelpDialog__link-icon">{ExternalLinkIcon}</div>
{t("helpDialog.blog")} {t("helpDialog.blog")}

View file

@ -389,7 +389,7 @@ const PublishLibrary = ({
<a <a
href="https://libraries.excalidraw.com" href="https://libraries.excalidraw.com"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener"
> >
{el} {el}
</a> </a>

View file

@ -16,7 +16,7 @@ const DropdownMenuItemLink = ({
onSelect, onSelect,
className = "", className = "",
selected, selected,
rel = "noreferrer", rel = "noopener",
...rest ...rest
}: { }: {
href: string; href: string;
@ -31,11 +31,12 @@ const DropdownMenuItemLink = ({
const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect); const handleClick = useHandleDropdownMenuItemClick(rest.onClick, onSelect);
return ( return (
// eslint-disable-next-line react/jsx-no-target-blank
<a <a
{...rest} {...rest}
href={href} href={href}
target="_blank" target="_blank"
rel="noreferrer" rel={rel || "noopener"}
className={getDropdownMenuItemClassName(className, selected)} className={getDropdownMenuItemClassName(className, selected)}
title={rest.title ?? rest["aria-label"]} title={rest.title ?? rest["aria-label"]}
onClick={handleClick} onClick={handleClick}

View file

@ -78,7 +78,7 @@ const WelcomeScreenMenuItemLink = ({
className={`welcome-screen-menu-item ${className}`} className={`welcome-screen-menu-item ${className}`}
href={href} href={href}
target="_blank" target="_blank"
rel="noreferrer" rel="noopener"
> >
<WelcomeScreenMenuItemContent icon={icon} shortcut={shortcut}> <WelcomeScreenMenuItemContent icon={icon} shortcut={shortcut}>
{children} {children}

View file

@ -21,7 +21,7 @@ exports[`<Excalidraw/> > <MainMenu/> > should render main menu with host menu it
<a <a
class="dropdown-menu-item dropdown-menu-item-base" class="dropdown-menu-item dropdown-menu-item-base"
href="blog.excalidaw.com" href="blog.excalidaw.com"
rel="noreferrer" rel="noopener"
target="_blank" target="_blank"
> >
<div <div
@ -392,7 +392,7 @@ exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should rende
aria-label="GitHub" aria-label="GitHub"
class="dropdown-menu-item dropdown-menu-item-base" class="dropdown-menu-item dropdown-menu-item-base"
href="https://github.com/excalidraw/excalidraw" href="https://github.com/excalidraw/excalidraw"
rel="noreferrer" rel="noopener"
target="_blank" target="_blank"
title="GitHub" title="GitHub"
> >
@ -426,7 +426,7 @@ exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should rende
aria-label="X" aria-label="X"
class="dropdown-menu-item dropdown-menu-item-base" class="dropdown-menu-item dropdown-menu-item-base"
href="https://x.com/excalidraw" href="https://x.com/excalidraw"
rel="noreferrer" rel="noopener"
target="_blank" target="_blank"
title="X" title="X"
> >
@ -472,7 +472,7 @@ exports[`<Excalidraw/> > Test UIOptions prop > Test canvasActions > should rende
aria-label="Discord" aria-label="Discord"
class="dropdown-menu-item dropdown-menu-item-base" class="dropdown-menu-item dropdown-menu-item-base"
href="https://discord.gg/UexuTaE" href="https://discord.gg/UexuTaE"
rel="noreferrer" rel="noopener"
target="_blank" target="_blank"
title="Discord" title="Discord"
> >

View file

@ -171,7 +171,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 19, "version": 9,
"width": 100, "width": 100,
"x": 100, "x": 100,
"y": -50, "y": -50,
@ -198,7 +198,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"fillStyle": "solid", "fillStyle": "solid",
"frameId": null, "frameId": null,
"groupIds": [], "groupIds": [],
"height": "102.35417", "height": "102.45605",
"id": "id172", "id": "id172",
"index": "a2", "index": "a2",
"isDeleted": false, "isDeleted": false,
@ -212,8 +212,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
0, 0,
], ],
[ [
"101.77517", "102.80179",
"102.35417", "102.45605",
], ],
], ],
"roughness": 1, "roughness": 1,
@ -227,9 +227,9 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "arrow", "type": "arrow",
"updated": 1, "updated": 1,
"version": 40, "version": 37,
"width": "101.77517", "width": "102.80179",
"x": "0.70711", "x": "-0.42182",
"y": 0, "y": 0,
} }
`; `;
@ -264,7 +264,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 6, "version": 14,
"width": 50, "width": 50,
"x": 100, "x": 100,
"y": 100, "y": 100,
@ -291,22 +291,39 @@ History {
"added": Map {}, "added": Map {},
"removed": Map {}, "removed": Map {},
"updated": Map { "updated": Map {
"id171" => Delta {
"deleted": {
"boundElements": [],
},
"inserted": {
"boundElements": [
{
"id": "id172",
"type": "arrow",
},
],
},
},
"id172" => Delta { "id172" => Delta {
"deleted": { "deleted": {
"endBinding": { "endBinding": {
"elementId": "id171", "elementId": "id175",
"focus": "0.00990", "fixedPoint": [
"0.50000",
1,
],
"focus": 0,
"gap": 1, "gap": 1,
}, },
"height": "0.98586", "height": "70.45017",
"points": [ "points": [
[ [
0, 0,
0, 0,
], ],
[ [
"98.58579", "100.70774",
"-0.98586", "70.45017",
], ],
], ],
"startBinding": { "startBinding": {
@ -321,7 +338,7 @@ History {
"focus": "-0.02000", "focus": "-0.02000",
"gap": 1, "gap": 1,
}, },
"height": "0.00000", "height": "0.09250",
"points": [ "points": [
[ [
0, 0,
@ -329,7 +346,7 @@ History {
], ],
[ [
"98.58579", "98.58579",
"0.00000", "0.09250",
], ],
], ],
"startBinding": { "startBinding": {
@ -339,6 +356,19 @@ History {
}, },
}, },
}, },
"id175" => Delta {
"deleted": {
"boundElements": [
{
"id": "id172",
"type": "arrow",
},
],
},
"inserted": {
"boundElements": [],
},
},
}, },
}, },
}, },
@ -366,59 +396,32 @@ History {
], ],
}, },
}, },
"id171" => Delta {
"deleted": {
"boundElements": [],
},
"inserted": {
"boundElements": [
{
"id": "id172",
"type": "arrow",
},
],
},
},
"id172" => Delta { "id172" => Delta {
"deleted": { "deleted": {
"endBinding": { "height": "102.45584",
"elementId": "id175",
"fixedPoint": [
"0.50000",
1,
],
"focus": 0,
"gap": 1,
},
"height": "102.35417",
"points": [ "points": [
[ [
0, 0,
0, 0,
], ],
[ [
"101.77517", "102.79971",
"102.35417", "102.45584",
], ],
], ],
"startBinding": null, "startBinding": null,
"y": 0, "y": 0,
}, },
"inserted": { "inserted": {
"endBinding": { "height": "70.33521",
"elementId": "id171",
"focus": "0.00990",
"gap": 1,
},
"height": "0.98586",
"points": [ "points": [
[ [
0, 0,
0, 0,
], ],
[ [
"98.58579", "100.78887",
"-0.98586", "70.33521",
], ],
], ],
"startBinding": { "startBinding": {
@ -426,20 +429,7 @@ History {
"focus": "0.02970", "focus": "0.02970",
"gap": 1, "gap": 1,
}, },
"y": "0.99364", "y": "35.20327",
},
},
"id175" => Delta {
"deleted": {
"boundElements": [
{
"id": "id172",
"type": "arrow",
},
],
},
"inserted": {
"boundElements": [],
}, },
}, },
}, },
@ -739,7 +729,7 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "rectangle", "type": "rectangle",
"updated": 1, "updated": 1,
"version": 9, "version": 19,
"width": 100, "width": 100,
"x": 150, "x": 150,
"y": -50, "y": -50,
@ -819,8 +809,8 @@ exports[`history > multiplayer undo/redo > conflicts in arrows and their bindabl
"strokeWidth": 2, "strokeWidth": 2,
"type": "arrow", "type": "arrow",
"updated": 1, "updated": 1,
"version": 30, "version": 33,
"width": 0, "width": 100,
"x": "149.29289", "x": "149.29289",
"y": 0, "y": 0,
} }
@ -846,20 +836,22 @@ History {
"added": Map {}, "added": Map {},
"removed": Map {}, "removed": Map {},
"updated": Map { "updated": Map {
"id167" => Delta { "id166" => Delta {
"deleted": { "deleted": {
"points": [ "boundElements": [],
[
0,
0,
],
[
0,
0,
],
],
}, },
"inserted": { "inserted": {
"boundElements": [
{
"id": "id167",
"type": "arrow",
},
],
},
},
"id167" => Delta {
"deleted": {
"endBinding": null,
"points": [ "points": [
[ [
0, 0,
@ -871,6 +863,23 @@ History {
], ],
], ],
}, },
"inserted": {
"endBinding": {
"elementId": "id166",
"focus": -0,
"gap": 1,
},
"points": [
[
0,
0,
],
[
0,
0,
],
],
},
}, },
}, },
}, },
@ -899,22 +908,8 @@ History {
], ],
}, },
}, },
"id166" => Delta {
"deleted": {
"boundElements": [],
},
"inserted": {
"boundElements": [
{
"id": "id167",
"type": "arrow",
},
],
},
},
"id167" => Delta { "id167" => Delta {
"deleted": { "deleted": {
"endBinding": null,
"points": [ "points": [
[ [
0, 0,
@ -928,18 +923,13 @@ History {
"startBinding": null, "startBinding": null,
}, },
"inserted": { "inserted": {
"endBinding": {
"elementId": "id166",
"focus": -0,
"gap": 1,
},
"points": [ "points": [
[ [
0, 0,
0, 0,
], ],
[ [
0, 100,
0, 0,
], ],
], ],