Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f68f4cb9e0 | ||
|
|
71fb573750 | ||
|
|
7562d9b533 |
@@ -19,6 +19,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@dwelle/tunnel-rat": "0.1.1",
|
||||||
"@sentry/browser": "6.2.5",
|
"@sentry/browser": "6.2.5",
|
||||||
"@sentry/integrations": "6.2.5",
|
"@sentry/integrations": "6.2.5",
|
||||||
"@testing-library/jest-dom": "5.16.2",
|
"@testing-library/jest-dom": "5.16.2",
|
||||||
|
|||||||
+17
-12
@@ -40,17 +40,12 @@ import { actionToggleStats } from "../actions/actionToggleStats";
|
|||||||
import Footer from "./footer/Footer";
|
import Footer from "./footer/Footer";
|
||||||
import { hostSidebarCountersAtom } from "./Sidebar/Sidebar";
|
import { hostSidebarCountersAtom } from "./Sidebar/Sidebar";
|
||||||
import { jotaiScope } from "../jotai";
|
import { jotaiScope } from "../jotai";
|
||||||
import { useAtom } from "jotai";
|
import { Provider, useAtom } from "jotai";
|
||||||
import MainMenu from "./main-menu/MainMenu";
|
import MainMenu from "./main-menu/MainMenu";
|
||||||
import { ActiveConfirmDialog } from "./ActiveConfirmDialog";
|
import { ActiveConfirmDialog } from "./ActiveConfirmDialog";
|
||||||
import { HandButton } from "./HandButton";
|
import { HandButton } from "./HandButton";
|
||||||
import { isHandToolActive } from "../appState";
|
import { isHandToolActive } from "../appState";
|
||||||
import {
|
import { TunnelsContext, useInitializeTunnels } from "./context/tunnels";
|
||||||
mainMenuTunnel,
|
|
||||||
welcomeScreenMenuHintTunnel,
|
|
||||||
welcomeScreenToolbarHintTunnel,
|
|
||||||
welcomeScreenCenterTunnel,
|
|
||||||
} from "./tunnels";
|
|
||||||
|
|
||||||
interface LayerUIProps {
|
interface LayerUIProps {
|
||||||
actionManager: ActionManager;
|
actionManager: ActionManager;
|
||||||
@@ -130,6 +125,8 @@ const LayerUI = ({
|
|||||||
}: LayerUIProps) => {
|
}: LayerUIProps) => {
|
||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
|
|
||||||
|
const tunnels = useInitializeTunnels();
|
||||||
|
|
||||||
const renderJSONExportDialog = () => {
|
const renderJSONExportDialog = () => {
|
||||||
if (!UIOptions.canvasActions.export) {
|
if (!UIOptions.canvasActions.export) {
|
||||||
return null;
|
return null;
|
||||||
@@ -201,8 +198,8 @@ const LayerUI = ({
|
|||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
{/* wrapping to Fragment stops React from occasionally complaining
|
{/* wrapping to Fragment stops React from occasionally complaining
|
||||||
about identical Keys */}
|
about identical Keys */}
|
||||||
<mainMenuTunnel.Out />
|
<tunnels.mainMenuTunnel.Out />
|
||||||
{renderWelcomeScreen && <welcomeScreenMenuHintTunnel.Out />}
|
{renderWelcomeScreen && <tunnels.welcomeScreenMenuHintTunnel.Out />}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -254,7 +251,7 @@ const LayerUI = ({
|
|||||||
{(heading: React.ReactNode) => (
|
{(heading: React.ReactNode) => (
|
||||||
<div style={{ position: "relative" }}>
|
<div style={{ position: "relative" }}>
|
||||||
{renderWelcomeScreen && (
|
{renderWelcomeScreen && (
|
||||||
<welcomeScreenToolbarHintTunnel.Out />
|
<tunnels.welcomeScreenToolbarHintTunnel.Out />
|
||||||
)}
|
)}
|
||||||
<Stack.Col gap={4} align="start">
|
<Stack.Col gap={4} align="start">
|
||||||
<Stack.Row
|
<Stack.Row
|
||||||
@@ -354,7 +351,7 @@ const LayerUI = ({
|
|||||||
|
|
||||||
const [hostSidebarCounters] = useAtom(hostSidebarCountersAtom, jotaiScope);
|
const [hostSidebarCounters] = useAtom(hostSidebarCountersAtom, jotaiScope);
|
||||||
|
|
||||||
return (
|
const layerUIJSX = (
|
||||||
<>
|
<>
|
||||||
{/* ------------------------- tunneled UI ---------------------------- */}
|
{/* ------------------------- tunneled UI ---------------------------- */}
|
||||||
{/* make sure we render host app components first so that we can detect
|
{/* make sure we render host app components first so that we can detect
|
||||||
@@ -434,7 +431,7 @@ const LayerUI = ({
|
|||||||
: {}
|
: {}
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{renderWelcomeScreen && <welcomeScreenCenterTunnel.Out />}
|
{renderWelcomeScreen && <tunnels.welcomeScreenCenterTunnel.Out />}
|
||||||
{renderFixedSideContainer()}
|
{renderFixedSideContainer()}
|
||||||
<Footer
|
<Footer
|
||||||
appState={appState}
|
appState={appState}
|
||||||
@@ -471,6 +468,14 @@ const LayerUI = ({
|
|||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Provider scope={tunnels.jotaiScope}>
|
||||||
|
<TunnelsContext.Provider value={tunnels}>
|
||||||
|
{layerUIJSX}
|
||||||
|
</TunnelsContext.Provider>
|
||||||
|
</Provider>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const stripIrrelevantAppStateProps = (
|
const stripIrrelevantAppStateProps = (
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { Stats } from "./Stats";
|
|||||||
import { actionToggleStats } from "../actions";
|
import { actionToggleStats } from "../actions";
|
||||||
import { HandButton } from "./HandButton";
|
import { HandButton } from "./HandButton";
|
||||||
import { isHandToolActive } from "../appState";
|
import { isHandToolActive } from "../appState";
|
||||||
import { mainMenuTunnel, welcomeScreenCenterTunnel } from "./tunnels";
|
import { useTunnels } from "./context/tunnels";
|
||||||
|
|
||||||
type MobileMenuProps = {
|
type MobileMenuProps = {
|
||||||
appState: AppState;
|
appState: AppState;
|
||||||
@@ -58,6 +58,7 @@ export const MobileMenu = ({
|
|||||||
renderSidebars,
|
renderSidebars,
|
||||||
device,
|
device,
|
||||||
}: MobileMenuProps) => {
|
}: MobileMenuProps) => {
|
||||||
|
const { welcomeScreenCenterTunnel, mainMenuTunnel } = useTunnels();
|
||||||
const renderToolbar = () => {
|
const renderToolbar = () => {
|
||||||
return (
|
return (
|
||||||
<FixedSideContainer side="top" className="App-top-bar">
|
<FixedSideContainer side="top" className="App-top-bar">
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
import React from "react";
|
||||||
|
import tunnel from "@dwelle/tunnel-rat";
|
||||||
|
|
||||||
|
type Tunnel = ReturnType<typeof tunnel>;
|
||||||
|
|
||||||
|
type TunnelsContextValue = {
|
||||||
|
mainMenuTunnel: Tunnel;
|
||||||
|
welcomeScreenMenuHintTunnel: Tunnel;
|
||||||
|
welcomeScreenToolbarHintTunnel: Tunnel;
|
||||||
|
welcomeScreenHelpHintTunnel: Tunnel;
|
||||||
|
welcomeScreenCenterTunnel: Tunnel;
|
||||||
|
footerCenterTunnel: Tunnel;
|
||||||
|
jotaiScope: symbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const TunnelsContext = React.createContext<TunnelsContextValue>(null!);
|
||||||
|
|
||||||
|
export const useTunnels = () => React.useContext(TunnelsContext);
|
||||||
|
|
||||||
|
export const useInitializeTunnels = () => {
|
||||||
|
return React.useMemo((): TunnelsContextValue => {
|
||||||
|
return {
|
||||||
|
mainMenuTunnel: tunnel(),
|
||||||
|
welcomeScreenMenuHintTunnel: tunnel(),
|
||||||
|
welcomeScreenToolbarHintTunnel: tunnel(),
|
||||||
|
welcomeScreenHelpHintTunnel: tunnel(),
|
||||||
|
welcomeScreenCenterTunnel: tunnel(),
|
||||||
|
footerCenterTunnel: tunnel(),
|
||||||
|
jotaiScope: Symbol(),
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
};
|
||||||
@@ -9,10 +9,10 @@ import {
|
|||||||
ZoomActions,
|
ZoomActions,
|
||||||
} from "../Actions";
|
} from "../Actions";
|
||||||
import { useDevice } from "../App";
|
import { useDevice } from "../App";
|
||||||
|
import { useTunnels } from "../context/tunnels";
|
||||||
import { HelpButton } from "../HelpButton";
|
import { HelpButton } from "../HelpButton";
|
||||||
import { Section } from "../Section";
|
import { Section } from "../Section";
|
||||||
import Stack from "../Stack";
|
import Stack from "../Stack";
|
||||||
import { footerCenterTunnel, welcomeScreenHelpHintTunnel } from "../tunnels";
|
|
||||||
|
|
||||||
const Footer = ({
|
const Footer = ({
|
||||||
appState,
|
appState,
|
||||||
@@ -25,6 +25,8 @@ const Footer = ({
|
|||||||
showExitZenModeBtn: boolean;
|
showExitZenModeBtn: boolean;
|
||||||
renderWelcomeScreen: boolean;
|
renderWelcomeScreen: boolean;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { footerCenterTunnel, welcomeScreenHelpHintTunnel } = useTunnels();
|
||||||
|
|
||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
const showFinalize =
|
const showFinalize =
|
||||||
!appState.viewModeEnabled && appState.multiElement && device.isTouchScreen;
|
!appState.viewModeEnabled && appState.multiElement && device.isTouchScreen;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useExcalidrawAppState } from "../App";
|
import { useExcalidrawAppState } from "../App";
|
||||||
import { footerCenterTunnel } from "../tunnels";
|
import { useTunnels } from "../context/tunnels";
|
||||||
import "./FooterCenter.scss";
|
import "./FooterCenter.scss";
|
||||||
|
|
||||||
const FooterCenter = ({ children }: { children?: React.ReactNode }) => {
|
const FooterCenter = ({ children }: { children?: React.ReactNode }) => {
|
||||||
|
const { footerCenterTunnel } = useTunnels();
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
return (
|
return (
|
||||||
<footerCenterTunnel.In>
|
<footerCenterTunnel.In>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { atom, useAtom } from "jotai";
|
import { atom, useAtom } from "jotai";
|
||||||
import React, { useLayoutEffect } from "react";
|
import React, { useLayoutEffect } from "react";
|
||||||
|
import { useTunnels } from "../context/tunnels";
|
||||||
|
|
||||||
export const withInternalFallback = <P,>(
|
export const withInternalFallback = <P,>(
|
||||||
componentName: string,
|
componentName: string,
|
||||||
@@ -17,7 +18,8 @@ export const withInternalFallback = <P,>(
|
|||||||
__fallback?: boolean;
|
__fallback?: boolean;
|
||||||
}
|
}
|
||||||
> = (props) => {
|
> = (props) => {
|
||||||
const [counter, setCounter] = useAtom(counterAtom);
|
const { jotaiScope } = useTunnels();
|
||||||
|
const [counter, setCounter] = useAtom(counterAtom, jotaiScope);
|
||||||
|
|
||||||
useLayoutEffect(() => {
|
useLayoutEffect(() => {
|
||||||
setCounter((counter) => counter + 1);
|
setCounter((counter) => counter + 1);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { t } from "../../i18n";
|
|||||||
import { HamburgerMenuIcon } from "../icons";
|
import { HamburgerMenuIcon } from "../icons";
|
||||||
import { withInternalFallback } from "../hoc/withInternalFallback";
|
import { withInternalFallback } from "../hoc/withInternalFallback";
|
||||||
import { composeEventHandlers } from "../../utils";
|
import { composeEventHandlers } from "../../utils";
|
||||||
import { mainMenuTunnel } from "../tunnels";
|
import { useTunnels } from "../context/tunnels";
|
||||||
|
|
||||||
const MainMenu = Object.assign(
|
const MainMenu = Object.assign(
|
||||||
withInternalFallback(
|
withInternalFallback(
|
||||||
@@ -28,6 +28,7 @@ const MainMenu = Object.assign(
|
|||||||
*/
|
*/
|
||||||
onSelect?: (event: Event) => void;
|
onSelect?: (event: Event) => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { mainMenuTunnel } = useTunnels();
|
||||||
const device = useDevice();
|
const device = useDevice();
|
||||||
const appState = useExcalidrawAppState();
|
const appState = useExcalidrawAppState();
|
||||||
const setAppState = useExcalidrawSetAppState();
|
const setAppState = useExcalidrawSetAppState();
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
import tunnel from "tunnel-rat";
|
|
||||||
|
|
||||||
export const mainMenuTunnel = tunnel();
|
|
||||||
export const welcomeScreenMenuHintTunnel = tunnel();
|
|
||||||
export const welcomeScreenToolbarHintTunnel = tunnel();
|
|
||||||
export const welcomeScreenHelpHintTunnel = tunnel();
|
|
||||||
export const welcomeScreenCenterTunnel = tunnel();
|
|
||||||
export const footerCenterTunnel = tunnel();
|
|
||||||
@@ -6,8 +6,8 @@ import {
|
|||||||
useExcalidrawActionManager,
|
useExcalidrawActionManager,
|
||||||
useExcalidrawAppState,
|
useExcalidrawAppState,
|
||||||
} from "../App";
|
} from "../App";
|
||||||
|
import { useTunnels } from "../context/tunnels";
|
||||||
import { ExcalLogo, HelpIcon, LoadIcon, usersIcon } from "../icons";
|
import { ExcalLogo, HelpIcon, LoadIcon, usersIcon } from "../icons";
|
||||||
import { welcomeScreenCenterTunnel } from "../tunnels";
|
|
||||||
|
|
||||||
const WelcomeScreenMenuItemContent = ({
|
const WelcomeScreenMenuItemContent = ({
|
||||||
icon,
|
icon,
|
||||||
@@ -89,6 +89,7 @@ const WelcomeScreenMenuItemLink = ({
|
|||||||
WelcomeScreenMenuItemLink.displayName = "WelcomeScreenMenuItemLink";
|
WelcomeScreenMenuItemLink.displayName = "WelcomeScreenMenuItemLink";
|
||||||
|
|
||||||
const Center = ({ children }: { children?: React.ReactNode }) => {
|
const Center = ({ children }: { children?: React.ReactNode }) => {
|
||||||
|
const { welcomeScreenCenterTunnel } = useTunnels();
|
||||||
return (
|
return (
|
||||||
<welcomeScreenCenterTunnel.In>
|
<welcomeScreenCenterTunnel.In>
|
||||||
<div className="welcome-screen-center">
|
<div className="welcome-screen-center">
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
import { t } from "../../i18n";
|
import { t } from "../../i18n";
|
||||||
|
import { useTunnels } from "../context/tunnels";
|
||||||
import {
|
import {
|
||||||
WelcomeScreenHelpArrow,
|
WelcomeScreenHelpArrow,
|
||||||
WelcomeScreenMenuArrow,
|
WelcomeScreenMenuArrow,
|
||||||
WelcomeScreenTopToolbarArrow,
|
WelcomeScreenTopToolbarArrow,
|
||||||
} from "../icons";
|
} from "../icons";
|
||||||
import {
|
|
||||||
welcomeScreenMenuHintTunnel,
|
|
||||||
welcomeScreenToolbarHintTunnel,
|
|
||||||
welcomeScreenHelpHintTunnel,
|
|
||||||
} from "../tunnels";
|
|
||||||
|
|
||||||
const MenuHint = ({ children }: { children?: React.ReactNode }) => {
|
const MenuHint = ({ children }: { children?: React.ReactNode }) => {
|
||||||
|
const { welcomeScreenMenuHintTunnel } = useTunnels();
|
||||||
return (
|
return (
|
||||||
<welcomeScreenMenuHintTunnel.In>
|
<welcomeScreenMenuHintTunnel.In>
|
||||||
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--menu">
|
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--menu">
|
||||||
@@ -25,6 +22,7 @@ const MenuHint = ({ children }: { children?: React.ReactNode }) => {
|
|||||||
MenuHint.displayName = "MenuHint";
|
MenuHint.displayName = "MenuHint";
|
||||||
|
|
||||||
const ToolbarHint = ({ children }: { children?: React.ReactNode }) => {
|
const ToolbarHint = ({ children }: { children?: React.ReactNode }) => {
|
||||||
|
const { welcomeScreenToolbarHintTunnel } = useTunnels();
|
||||||
return (
|
return (
|
||||||
<welcomeScreenToolbarHintTunnel.In>
|
<welcomeScreenToolbarHintTunnel.In>
|
||||||
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--toolbar">
|
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--toolbar">
|
||||||
@@ -39,6 +37,7 @@ const ToolbarHint = ({ children }: { children?: React.ReactNode }) => {
|
|||||||
ToolbarHint.displayName = "ToolbarHint";
|
ToolbarHint.displayName = "ToolbarHint";
|
||||||
|
|
||||||
const HelpHint = ({ children }: { children?: React.ReactNode }) => {
|
const HelpHint = ({ children }: { children?: React.ReactNode }) => {
|
||||||
|
const { welcomeScreenHelpHintTunnel } = useTunnels();
|
||||||
return (
|
return (
|
||||||
<welcomeScreenHelpHintTunnel.In>
|
<welcomeScreenHelpHintTunnel.In>
|
||||||
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--help">
|
<div className="virgil welcome-screen-decor welcome-screen-decor-hint welcome-screen-decor-hint--help">
|
||||||
|
|||||||
@@ -61,30 +61,29 @@ export const redrawTextBoundingBox = (
|
|||||||
if (!isArrowElement(container)) {
|
if (!isArrowElement(container)) {
|
||||||
const containerDims = getContainerDims(container);
|
const containerDims = getContainerDims(container);
|
||||||
let nextHeight = containerDims.height;
|
let nextHeight = containerDims.height;
|
||||||
const boundTextElementPadding = getBoundTextElementOffset(textElement);
|
|
||||||
if (textElement.verticalAlign === VERTICAL_ALIGN.TOP) {
|
if (textElement.verticalAlign === VERTICAL_ALIGN.TOP) {
|
||||||
coordY = container.y + boundTextElementPadding;
|
coordY = container.y;
|
||||||
} else if (textElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
} else if (textElement.verticalAlign === VERTICAL_ALIGN.BOTTOM) {
|
||||||
coordY =
|
coordY =
|
||||||
container.y +
|
container.y +
|
||||||
containerDims.height -
|
containerDims.height -
|
||||||
metrics.height -
|
metrics.height -
|
||||||
boundTextElementPadding;
|
BOUND_TEXT_PADDING;
|
||||||
} else {
|
} else {
|
||||||
coordY = container.y + containerDims.height / 2 - metrics.height / 2;
|
coordY = container.y + containerDims.height / 2 - metrics.height / 2;
|
||||||
if (metrics.height > getMaxContainerHeight(container)) {
|
if (metrics.height > getMaxContainerHeight(container)) {
|
||||||
nextHeight = metrics.height + boundTextElementPadding * 2;
|
nextHeight = metrics.height + BOUND_TEXT_PADDING * 2;
|
||||||
coordY = container.y + nextHeight / 2 - metrics.height / 2;
|
coordY = container.y + nextHeight / 2 - metrics.height / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (textElement.textAlign === TEXT_ALIGN.LEFT) {
|
if (textElement.textAlign === TEXT_ALIGN.LEFT) {
|
||||||
coordX = container.x + boundTextElementPadding;
|
coordX = container.x + BOUND_TEXT_PADDING;
|
||||||
} else if (textElement.textAlign === TEXT_ALIGN.RIGHT) {
|
} else if (textElement.textAlign === TEXT_ALIGN.RIGHT) {
|
||||||
coordX =
|
coordX =
|
||||||
container.x +
|
container.x +
|
||||||
containerDims.width -
|
containerDims.width -
|
||||||
metrics.width -
|
metrics.width -
|
||||||
boundTextElementPadding;
|
BOUND_TEXT_PADDING;
|
||||||
} else {
|
} else {
|
||||||
coordX = container.x + containerDims.width / 2 - metrics.width / 2;
|
coordX = container.x + containerDims.width / 2 - metrics.width / 2;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1165,5 +1165,128 @@ describe("textWysiwyg", () => {
|
|||||||
).toEqual(36);
|
).toEqual(36);
|
||||||
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
|
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("should align correctly", () => {
|
||||||
|
let editor: HTMLTextAreaElement;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
Keyboard.keyPress(KEYS.ENTER);
|
||||||
|
editor = document.querySelector(
|
||||||
|
".excalidraw-textEditorContainer > textarea",
|
||||||
|
) as HTMLTextAreaElement;
|
||||||
|
await new Promise((r) => setTimeout(r, 0));
|
||||||
|
fireEvent.change(editor, { target: { value: "Hello" } });
|
||||||
|
editor.blur();
|
||||||
|
mouse.select(rectangle);
|
||||||
|
Keyboard.keyPress(KEYS.ENTER);
|
||||||
|
editor = document.querySelector(
|
||||||
|
".excalidraw-textEditorContainer > textarea",
|
||||||
|
) as HTMLTextAreaElement;
|
||||||
|
editor.select();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when top left", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
15,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when top center", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Center"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
94.5,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when top right", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Right"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align top"));
|
||||||
|
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
174,
|
||||||
|
20,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when center left", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
15,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when center center", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Center"));
|
||||||
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
|
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
-25,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when center right", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Right"));
|
||||||
|
fireEvent.click(screen.getByTitle("Center vertically"));
|
||||||
|
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
174,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when bottom left", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Left"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
|
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
15,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when bottom center", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Center"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
94.5,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("when bottom right", async () => {
|
||||||
|
fireEvent.click(screen.getByTitle("Right"));
|
||||||
|
fireEvent.click(screen.getByTitle("Align bottom"));
|
||||||
|
expect([h.elements[1].x, h.elements[1].y]).toMatchInlineSnapshot(`
|
||||||
|
Array [
|
||||||
|
174,
|
||||||
|
25,
|
||||||
|
]
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ The change should be grouped under one of the below section and must contain PR
|
|||||||
Please add the latest change on the top under the correct section.
|
Please add the latest change on the top under the correct section.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
## Unreleased
|
## 0.14.2 (2023-02-01)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
@@ -22,6 +22,42 @@ Please add the latest change on the top under the correct section.
|
|||||||
|
|
||||||
- declare css variable for font in excalidraw so its available in host [#6160](https://github.com/excalidraw/excalidraw/pull/6160)
|
- declare css variable for font in excalidraw so its available in host [#6160](https://github.com/excalidraw/excalidraw/pull/6160)
|
||||||
|
|
||||||
|
## Excalidraw Library
|
||||||
|
|
||||||
|
**_This section lists the updates made to the excalidraw library and will not affect the integration._**
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Add hand/panning tool [#6141](https://github.com/excalidraw/excalidraw/pull/6141)
|
||||||
|
|
||||||
|
- Show copy-as-png export button on firefox and show steps how to enable it [#6125](https://github.com/excalidraw/excalidraw/pull/6125)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
- Horizontal padding when aligning bound text containers [#6180](https://github.com/excalidraw/excalidraw/pull/6180)
|
||||||
|
|
||||||
|
- Make tunnels work in multi-instance scenarios [#6178](https://github.com/excalidraw/excalidraw/pull/6178)
|
||||||
|
|
||||||
|
- Add 1px width to the container to calculate more accurately [#6174](https://github.com/excalidraw/excalidraw/pull/6174)
|
||||||
|
|
||||||
|
- Quick typo fix [#6167](https://github.com/excalidraw/excalidraw/pull/6167)
|
||||||
|
|
||||||
|
- Set the width correctly using measureText in editor [#6162](https://github.com/excalidraw/excalidraw/pull/6162)
|
||||||
|
|
||||||
|
- :bug: broken emojis when wrap text [#6153](https://github.com/excalidraw/excalidraw/pull/6153)
|
||||||
|
|
||||||
|
- Button background and svg sizes [#6155](https://github.com/excalidraw/excalidraw/pull/6155)
|
||||||
|
|
||||||
|
### Styles
|
||||||
|
|
||||||
|
- Change in ExportButton style [#6147](https://github.com/excalidraw/excalidraw/pull/6147) (#6148)
|
||||||
|
|
||||||
|
### Build
|
||||||
|
|
||||||
|
- Temporarily disable pre-commit [#6132](https://github.com/excalidraw/excalidraw/pull/6132)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 0.14.1 (2023-01-16)
|
## 0.14.1 (2023-01-16)
|
||||||
|
|
||||||
### Fixes
|
### Fixes
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@excalidraw/excalidraw",
|
"name": "@excalidraw/excalidraw",
|
||||||
"version": "0.14.1",
|
"version": "0.14.2",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
"types": "types/packages/excalidraw/index.d.ts",
|
"types": "types/packages/excalidraw/index.d.ts",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -1437,6 +1437,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36"
|
resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36"
|
||||||
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
|
integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg==
|
||||||
|
|
||||||
|
"@dwelle/tunnel-rat@0.1.1":
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@dwelle/tunnel-rat/-/tunnel-rat-0.1.1.tgz#0a0b235f8fc22ff1cf47ed102f4cc612eb51bc71"
|
||||||
|
integrity sha512-jb5/ZsT/af1J7tnbBXp7KO1xEyw61lWSDqJ+Bqdc6JlL3vbAvsifNhe+/mRFs6aSBCRaDqp5f2pJDHtA3MUZLw==
|
||||||
|
dependencies:
|
||||||
|
zustand "^4.3.2"
|
||||||
|
|
||||||
"@eslint/eslintrc@^0.4.3":
|
"@eslint/eslintrc@^0.4.3":
|
||||||
version "0.4.3"
|
version "0.4.3"
|
||||||
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
|
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.3.tgz#9e42981ef035beb3dd49add17acb96e8ff6f394c"
|
||||||
@@ -11028,7 +11035,7 @@ yocto-queue@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
|
||||||
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
|
||||||
|
|
||||||
zustand@^4.1.0:
|
zustand@^4.1.0, zustand@^4.3.2:
|
||||||
version "4.3.2"
|
version "4.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.2.tgz#bb121fcad84c5a569e94bd1a2695e1a93ba85d39"
|
resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.3.2.tgz#bb121fcad84c5a569e94bd1a2695e1a93ba85d39"
|
||||||
integrity sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==
|
integrity sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw==
|
||||||
|
|||||||
Reference in New Issue
Block a user