feat: Export THEME from the package (#4055)

* Use Theme type everywhere
* Rename Appearance type to Theme for consistency
* Reorder headers in readme
The host don't need to pass hardcoded strings any more and instead can use the exported constant
This commit is contained in:
Aakansha Doshi 2021-10-14 14:15:57 +05:30 committed by GitHub
parent be2da9539e
commit 463857ad9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 582 additions and 559 deletions

View File

@ -4,7 +4,7 @@ import { ColorPicker } from "../components/ColorPicker";
import { trash, zoomIn, zoomOut } from "../components/icons";
import { ToolButton } from "../components/ToolButton";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { ZOOM_STEP } from "../constants";
import { THEME, ZOOM_STEP } from "../constants";
import { getCommonBounds, getNonDeletedElements } from "../element";
import { newElementWith } from "../element/mutateElement";
import { ExcalidrawElement } from "../element/types";
@ -279,7 +279,8 @@ export const actionToggleTheme = register({
return {
appState: {
...appState,
theme: value || (appState.theme === "light" ? "dark" : "light"),
theme:
value || (appState.theme === THEME.LIGHT ? THEME.DARK : THEME.LIGHT),
},
commitToHistory: false,
};

View File

@ -5,7 +5,7 @@ import { ProjectName } from "../components/ProjectName";
import { ToolButton } from "../components/ToolButton";
import "../components/ToolIcon.scss";
import { Tooltip } from "../components/Tooltip";
import { DarkModeToggle, Appearence } from "../components/DarkModeToggle";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { loadFromJSON, saveAsJSON } from "../data";
import { resaveAsImageWithScene } from "../data/resave";
import { t } from "../i18n";
@ -14,12 +14,13 @@ import { KEYS } from "../keys";
import { register } from "./register";
import { CheckboxItem } from "../components/CheckboxItem";
import { getExportSize } from "../scene/export";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES } from "../constants";
import { DEFAULT_EXPORT_PADDING, EXPORT_SCALES, THEME } from "../constants";
import { getSelectedElements, isSomeElementSelected } from "../scene";
import { getNonDeletedElements } from "../element";
import { ActiveFile } from "../components/ActiveFile";
import { isImageFileHandle } from "../data/blob";
import { nativeFileSystemSupported } from "../data/filesystem";
import { Theme } from "../element/types";
export const actionChangeProjectName = register({
name: "changeProjectName",
@ -256,9 +257,9 @@ export const actionExportWithDarkMode = register({
}}
>
<DarkModeToggle
value={appState.exportWithDarkMode ? "dark" : "light"}
onChange={(theme: Appearence) => {
updateData(theme === "dark");
value={appState.exportWithDarkMode ? THEME.DARK : THEME.LIGHT}
onChange={(theme: Theme) => {
updateData(theme === THEME.DARK);
}}
title={t("labels.toggleExportColorScheme")}
/>

View File

@ -4,6 +4,7 @@ import {
DEFAULT_FONT_SIZE,
DEFAULT_TEXT_ALIGN,
EXPORT_SCALES,
THEME,
} from "./constants";
import { t } from "./i18n";
import { AppState, NormalizedZoomValue } from "./types";
@ -18,7 +19,7 @@ export const getDefaultAppState = (): Omit<
"offsetTop" | "offsetLeft" | "width" | "height"
> => {
return {
theme: "light",
theme: THEME.LIGHT,
collaborators: new Map(),
currentChartType: "bar",
currentItemBackgroundColor: "transparent",

View File

@ -60,6 +60,7 @@ import {
SCROLL_TIMEOUT,
TAP_TWICE_TIMEOUT,
TEXT_TO_CENTER_SNAP_THRESHOLD,
THEME,
TOUCH_CTX_MENU_TIMEOUT,
URL_HASH_KEYS,
URL_QUERY_KEYS,
@ -513,7 +514,7 @@ class App extends React.Component<AppProps, AppState> {
let viewModeEnabled = actionResult?.appState?.viewModeEnabled || false;
let zenModeEnabled = actionResult?.appState?.zenModeEnabled || false;
let gridSize = actionResult?.appState?.gridSize || null;
let theme = actionResult?.appState?.theme || "light";
let theme = actionResult?.appState?.theme || THEME.LIGHT;
let name = actionResult?.appState?.name ?? this.state.name;
if (typeof this.props.viewModeEnabled !== "undefined") {
viewModeEnabled = this.props.viewModeEnabled;

View File

@ -3,14 +3,14 @@ import "./ToolIcon.scss";
import React from "react";
import { t } from "../i18n";
import { ToolButton } from "./ToolButton";
export type Appearence = "light" | "dark";
import { THEME } from "../constants";
import { Theme } from "../element/types";
// We chose to use only explicit toggle and not a third option for system value,
// but this could be added in the future.
export const DarkModeToggle = (props: {
value: Appearence;
onChange: (value: Appearence) => void;
value: Theme;
onChange: (value: Theme) => void;
title?: string;
}) => {
const title =
@ -20,10 +20,12 @@ export const DarkModeToggle = (props: {
return (
<ToolButton
type="icon"
icon={props.value === "light" ? ICONS.MOON : ICONS.SUN}
icon={props.value === THEME.LIGHT ? ICONS.MOON : ICONS.SUN}
title={title}
aria-label={title}
onClick={() => props.onChange(props.value === "dark" ? "light" : "dark")}
onClick={() =>
props.onChange(props.value === THEME.DARK ? THEME.LIGHT : THEME.DARK)
}
data-testid="toggle-dark-mode"
/>
);

View File

@ -6,6 +6,7 @@ import clsx from "clsx";
import { KEYS } from "../keys";
import { useExcalidrawContainer, useIsMobile } from "./App";
import { AppState } from "../types";
import { THEME } from "../constants";
export const Modal = (props: {
className?: string;
@ -15,7 +16,7 @@ export const Modal = (props: {
labelledBy: string;
theme?: AppState["theme"];
}) => {
const { theme = "light" } = props;
const { theme = THEME.LIGHT } = props;
const modalRoot = useBodyRoot(theme);
if (!modalRoot) {

View File

@ -10,13 +10,15 @@ import React from "react";
import oc from "open-color";
import clsx from "clsx";
import { Theme } from "../element/types";
import { THEME } from "../constants";
const activeElementColor = (theme: "light" | "dark") =>
theme === "light" ? oc.orange[4] : oc.orange[9];
const iconFillColor = (theme: "light" | "dark") =>
theme === "light" ? oc.black : oc.gray[4];
const handlerColor = (theme: "light" | "dark") =>
theme === "light" ? oc.white : "#1e1e1e";
const activeElementColor = (theme: Theme) =>
theme === THEME.LIGHT ? oc.orange[4] : oc.orange[9];
const iconFillColor = (theme: Theme) =>
theme === THEME.LIGHT ? oc.black : oc.gray[4];
const handlerColor = (theme: Theme) =>
theme === THEME.LIGHT ? oc.white : "#1e1e1e";
type Opts = {
width?: number;
@ -175,88 +177,84 @@ export const resetZoom = createIcon(
{ width: 1024 },
);
export const BringForwardIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M22 9.556C22 8.696 21.303 8 20.444 8H16v8H8v4.444C8 21.304 8.697 22 9.556 22h10.888c.86 0 1.556-.697 1.556-1.556V9.556z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path
d="M16 3.556C16 2.696 15.303 2 14.444 2H3.556C2.696 2 2 2.697 2 3.556v10.888C2 15.304 2.697 16 3.556 16h10.888c.86 0 1.556-.697 1.556-1.556V3.556z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const BringForwardIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M22 9.556C22 8.696 21.303 8 20.444 8H16v8H8v4.444C8 21.304 8.697 22 9.556 22h10.888c.86 0 1.556-.697 1.556-1.556V9.556z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path
d="M16 3.556C16 2.696 15.303 2 14.444 2H3.556C2.696 2 2 2.697 2 3.556v10.888C2 15.304 2.697 16 3.556 16h10.888c.86 0 1.556-.697 1.556-1.556V3.556z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
export const SendBackwardIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M16 3.556C16 2.696 15.303 2 14.444 2H3.556C2.696 2 2 2.697 2 3.556v10.888C2 15.304 2.697 16 3.556 16h10.888c.86 0 1.556-.697 1.556-1.556V3.556z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M22 9.556C22 8.696 21.303 8 20.444 8H9.556C8.696 8 8 8.697 8 9.556v10.888C8 21.304 8.697 22 9.556 22h10.888c.86 0 1.556-.697 1.556-1.556V9.556z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const SendBackwardIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M16 3.556C16 2.696 15.303 2 14.444 2H3.556C2.696 2 2 2.697 2 3.556v10.888C2 15.304 2.697 16 3.556 16h10.888c.86 0 1.556-.697 1.556-1.556V3.556z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M22 9.556C22 8.696 21.303 8 20.444 8H9.556C8.696 8 8 8.697 8 9.556v10.888C8 21.304 8.697 22 9.556 22h10.888c.86 0 1.556-.697 1.556-1.556V9.556z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
export const BringToFrontIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M13 21a1 1 0 001 1h7a1 1 0 001-1v-7a1 1 0 00-1-1h-3v5h-5v3zM11 3a1 1 0 00-1-1H3a1 1 0 00-1 1v7a1 1 0 001 1h3V6h5V3z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path
d="M18 7.333C18 6.597 17.403 6 16.667 6H7.333C6.597 6 6 6.597 6 7.333v9.334C6 17.403 6.597 18 7.333 18h9.334c.736 0 1.333-.597 1.333-1.333V7.333z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const BringToFrontIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M13 21a1 1 0 001 1h7a1 1 0 001-1v-7a1 1 0 00-1-1h-3v5h-5v3zM11 3a1 1 0 00-1-1H3a1 1 0 00-1 1v7a1 1 0 001 1h3V6h5V3z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path
d="M18 7.333C18 6.597 17.403 6 16.667 6H7.333C6.597 6 6 6.597 6 7.333v9.334C6 17.403 6.597 18 7.333 18h9.334c.736 0 1.333-.597 1.333-1.333V7.333z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
export const SendToBackIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M18 7.333C18 6.597 17.403 6 16.667 6H7.333C6.597 6 6 6.597 6 7.333v9.334C6 17.403 6.597 18 7.333 18h9.334c.736 0 1.333-.597 1.333-1.333V7.333z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M11 3a1 1 0 00-1-1H3a1 1 0 00-1 1v7a1 1 0 001 1h8V3zM22 14a1 1 0 00-1-1h-7a1 1 0 00-1 1v7a1 1 0 001 1h8v-8z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const SendToBackIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M18 7.333C18 6.597 17.403 6 16.667 6H7.333C6.597 6 6 6.597 6 7.333v9.334C6 17.403 6.597 18 7.333 18h9.334c.736 0 1.333-.597 1.333-1.333V7.333z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M11 3a1 1 0 00-1-1H3a1 1 0 00-1 1v7a1 1 0 001 1h8V3zM22 14a1 1 0 00-1-1h-7a1 1 0 00-1 1v7a1 1 0 001 1h8v-8z"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
//
@ -265,96 +263,92 @@ export const SendToBackIcon = React.memo(
// first one the user sees. Horizontal align icons should not be flipped since
// that would make them lie about their function.
//
export const AlignTopIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M 2,5 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="M 6,7 C 5.446,7 5,7.446 5,8 v 9.999992 c 0,0.554 0.446,1 1,1 h 3.0000001 c 0.554,0 0.9999999,-0.446 0.9999999,-1 V 8 C 10,7.446 9.5540001,7 9.0000001,7 Z m 9,0 c -0.554,0 -1,0.446 -1,1 v 5.999992 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 V 8 C 19,7.446 18.554,7 18,7 Z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const AlignTopIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M 2,5 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="M 6,7 C 5.446,7 5,7.446 5,8 v 9.999992 c 0,0.554 0.446,1 1,1 h 3.0000001 c 0.554,0 0.9999999,-0.446 0.9999999,-1 V 8 C 10,7.446 9.5540001,7 9.0000001,7 Z m 9,0 c -0.554,0 -1,0.446 -1,1 v 5.999992 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 V 8 C 19,7.446 18.554,7 18,7 Z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
export const AlignBottomIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M 2,19 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 6,16.999992 c -0.554,0 -1,-0.446 -1,-1 V 6 C 5,5.446 5.446,5 6,5 H 9.0000001 C 9.5540001,5 10,5.446 10,6 v 9.999992 c 0,0.554 -0.4459999,1 -0.9999999,1 z m 9,0 c -0.554,0 -1,-0.446 -1,-1 V 10 c 0,-0.554 0.446,-1 1,-1 h 3 c 0.554,0 1,0.446 1,1 v 5.999992 c 0,0.554 -0.446,1 -1,1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
export const AlignBottomIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M 2,19 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 6,16.999992 c -0.554,0 -1,-0.446 -1,-1 V 6 C 5,5.446 5.446,5 6,5 H 9.0000001 C 9.5540001,5 10,5.446 10,6 v 9.999992 c 0,0.554 -0.4459999,1 -0.9999999,1 z m 9,0 c -0.554,0 -1,-0.446 -1,-1 V 10 c 0,-0.554 0.446,-1 1,-1 h 3 c 0.554,0 1,0.446 1,1 v 5.999992 c 0,0.554 -0.446,1 -1,1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24, mirror: true },
),
);
export const AlignLeftIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M 5,2 V 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 7.000004,5.999996 c 0,-0.554 0.446,-1 1,-1 h 9.999992 c 0.554,0 1,0.446 1,1 v 3.0000001 c 0,0.554 -0.446,0.9999999 -1,0.9999999 H 8.000004 c -0.554,0 -1,-0.4459999 -1,-0.9999999 z m 0,9 c 0,-0.554 0.446,-1 1,-1 h 5.999992 c 0.554,0 1,0.446 1,1 v 3 c 0,0.554 -0.446,1 -1,1 H 8.000004 c -0.554,0 -1,-0.446 -1,-1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24 },
),
export const AlignLeftIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M 5,2 V 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 7.000004,5.999996 c 0,-0.554 0.446,-1 1,-1 h 9.999992 c 0.554,0 1,0.446 1,1 v 3.0000001 c 0,0.554 -0.446,0.9999999 -1,0.9999999 H 8.000004 c -0.554,0 -1,-0.4459999 -1,-0.9999999 z m 0,9 c 0,-0.554 0.446,-1 1,-1 h 5.999992 c 0.554,0 1,0.446 1,1 v 3 c 0,0.554 -0.446,1 -1,1 H 8.000004 c -0.554,0 -1,-0.446 -1,-1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24 },
),
);
export const AlignRightIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="M 19,2 V 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 16.999996,5.999996 c 0,-0.554 -0.446,-1 -1,-1 H 6.000004 c -0.554,0 -1,0.446 -1,1 v 3.0000001 c 0,0.554 0.446,0.9999999 1,0.9999999 h 9.999992 c 0.554,0 1,-0.4459999 1,-0.9999999 z m 0,9 c 0,-0.554 -0.446,-1 -1,-1 h -5.999992 c -0.554,0 -1,0.446 -1,1 v 3 c 0,0.554 0.446,1 1,1 h 5.999992 c 0.554,0 1,-0.446 1,-1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24 },
),
export const AlignRightIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M 19,2 V 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeLinecap="round"
/>
<path
d="m 16.999996,5.999996 c 0,-0.554 -0.446,-1 -1,-1 H 6.000004 c -0.554,0 -1,0.446 -1,1 v 3.0000001 c 0,0.554 0.446,0.9999999 1,0.9999999 h 9.999992 c 0.554,0 1,-0.4459999 1,-0.9999999 z m 0,9 c 0,-0.554 -0.446,-1 -1,-1 h -5.999992 c -0.554,0 -1,0.446 -1,1 v 3 c 0,0.554 0.446,1 1,1 h 5.999992 c 0.554,0 1,-0.446 1,-1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
</>,
{ width: 24 },
),
);
export const DistributeHorizontallyIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
@ -375,7 +369,7 @@ export const DistributeHorizontallyIcon = React.memo(
);
export const DistributeVerticallyIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
@ -396,31 +390,30 @@ export const DistributeVerticallyIcon = React.memo(
),
);
export const CenterVerticallyIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
d="m 5.000004,16.999996 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 v -10 c 0,-0.554 -0.446,-1 -1,-1 h -3 c -0.554,0 -1,0.446 -1,1 z m 9,-2 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 v -6 c 0,-0.554 -0.446,-1 -1,-1 h -3 c -0.554,0 -1,0.446 -1,1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M 2,12 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeDasharray="1, 2.8"
strokeLinecap="round"
/>
</>,
{ width: 24, mirror: true },
),
export const CenterVerticallyIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="m 5.000004,16.999996 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 v -10 c 0,-0.554 -0.446,-1 -1,-1 h -3 c -0.554,0 -1,0.446 -1,1 z m 9,-2 c 0,0.554 0.446,1 1,1 h 3 c 0.554,0 1,-0.446 1,-1 v -6 c 0,-0.554 -0.446,-1 -1,-1 h -3 c -0.554,0 -1,0.446 -1,1 z"
fill={activeElementColor(theme)}
stroke={activeElementColor(theme)}
strokeWidth="2"
/>
<path
d="M 2,12 H 22"
fill={iconFillColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="2"
strokeDasharray="1, 2.8"
strokeLinecap="round"
/>
</>,
{ width: 24, mirror: true },
),
);
export const CenterHorizontallyIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
@ -482,7 +475,7 @@ export const file = createIcon(
{ width: 384, height: 512 },
);
export const GroupIcon = React.memo(({ theme }: { theme: "light" | "dark" }) =>
export const GroupIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path d="M25 26H111V111H25" fill={iconFillColor(theme)} />
@ -512,73 +505,69 @@ export const GroupIcon = React.memo(({ theme }: { theme: "light" | "dark" }) =>
),
);
export const UngroupIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path d="M25 26H111V111H25" fill={iconFillColor(theme)} />
<path
d="M25 111C25 80.2068 25 49.4135 25 26M25 26C48.6174 26 72.2348 26 111 26H25ZM25 26C53.3671 26 81.7343 26 111 26H25ZM111 26C111 52.303 111 78.606 111 111V26ZM111 26C111 51.2947 111 76.5893 111 111V26ZM111 111C87.0792 111 63.1585 111 25 111H111ZM111 111C87.4646 111 63.9293 111 25 111H111ZM25 111C25 81.1514 25 51.3028 25 26V111Z"
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path d="M100 100H160V160H100" fill={iconFillColor(theme)} />
<path
d="M100 160C100 144.106 100 128.211 100 100M100 100C117.706 100 135.412 100 160 100H100ZM100 100C114.214 100 128.428 100 160 100H100ZM160 100C160 120.184 160 140.369 160 160V100ZM160 100C160 113.219 160 126.437 160 160V100ZM160 160C145.534 160 131.068 160 100 160H160ZM160 160C143.467 160 126.934 160 100 160H160ZM100 160C100 143.661 100 127.321 100 100V160Z"
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<g
fill={handlerColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="6"
>
<rect x="2.5" y="2.5" width="30" height="30" />
<rect x="78.5" y="149.5" width="30" height="30" />
<rect x="147.5" y="149.5" width="30" height="30" />
<rect x="147.5" y="78.5" width="30" height="30" />
<rect x="105.5" y="2.5" width="30" height="30" />
<rect x="2.5" y="102.5" width="30" height="30" />
</g>
</>,
{ width: 182, height: 182, mirror: true },
),
);
export const FillHachureIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
export const UngroupIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path d="M25 26H111V111H25" fill={iconFillColor(theme)} />
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20.101 16H28.0934L36 8.95989V4H33.5779L20.101 16ZM30.5704 4L17.0935 16H9.10101L22.5779 4H30.5704ZM19.5704 4L6.09349 16H4V10.7475L11.5779 4H19.5704ZM8.57036 4H4V8.06952L8.57036 4ZM36 11.6378L31.101 16H36V11.6378ZM2 2V18H38V2H2Z"
fill={iconFillColor(theme)}
/>,
{ width: 40, height: 20 },
),
d="M25 111C25 80.2068 25 49.4135 25 26M25 26C48.6174 26 72.2348 26 111 26H25ZM25 26C53.3671 26 81.7343 26 111 26H25ZM111 26C111 52.303 111 78.606 111 111V26ZM111 26C111 51.2947 111 76.5893 111 111V26ZM111 111C87.0792 111 63.1585 111 25 111H111ZM111 111C87.4646 111 63.9293 111 25 111H111ZM25 111C25 81.1514 25 51.3028 25 26V111Z"
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<path d="M100 100H160V160H100" fill={iconFillColor(theme)} />
<path
d="M100 160C100 144.106 100 128.211 100 100M100 100C117.706 100 135.412 100 160 100H100ZM100 100C114.214 100 128.428 100 160 100H100ZM160 100C160 120.184 160 140.369 160 160V100ZM160 100C160 113.219 160 126.437 160 160V100ZM160 160C145.534 160 131.068 160 100 160H160ZM160 160C143.467 160 126.934 160 100 160H160ZM100 160C100 143.661 100 127.321 100 100V160Z"
stroke={iconFillColor(theme)}
strokeWidth="2"
/>
<g
fill={handlerColor(theme)}
stroke={iconFillColor(theme)}
strokeWidth="6"
>
<rect x="2.5" y="2.5" width="30" height="30" />
<rect x="78.5" y="149.5" width="30" height="30" />
<rect x="147.5" y="149.5" width="30" height="30" />
<rect x="147.5" y="78.5" width="30" height="30" />
<rect x="105.5" y="2.5" width="30" height="30" />
<rect x="2.5" y="102.5" width="30" height="30" />
</g>
</>,
{ width: 182, height: 182, mirror: true },
),
);
export const FillCrossHatchIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<g fill={iconFillColor(theme)} fillRule="evenodd" clipRule="evenodd">
<path d="M20.101 16H28.0934L36 8.95989V4H33.5779L20.101 16ZM30.5704 4L17.0935 16H9.10101L22.5779 4H30.5704ZM19.5704 4L6.09349 16H4V10.7475L11.5779 4H19.5704ZM8.57036 4H4V8.06952L8.57036 4ZM36 11.6378L31.101 16H36V11.6378ZM2 2V18H38V2H2Z" />
<path d="M14.0001 18L3.00006 4.00002L4.5727 2.76438L15.5727 16.7644L14.0001 18ZM25.0001 18L14.0001 4.00002L15.5727 2.76438L26.5727 16.7644L25.0001 18ZM36.0001 18L25.0001 4.00002L26.5727 2.76438L37.5727 16.7644L36.0001 18Z" />
</g>,
{ width: 40, height: 20 },
),
export const FillHachureIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
fillRule="evenodd"
clipRule="evenodd"
d="M20.101 16H28.0934L36 8.95989V4H33.5779L20.101 16ZM30.5704 4L17.0935 16H9.10101L22.5779 4H30.5704ZM19.5704 4L6.09349 16H4V10.7475L11.5779 4H19.5704ZM8.57036 4H4V8.06952L8.57036 4ZM36 11.6378L31.101 16H36V11.6378ZM2 2V18H38V2H2Z"
fill={iconFillColor(theme)}
/>,
{ width: 40, height: 20 },
),
);
export const FillSolidIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(<path d="M2 2H38V18H2V2Z" fill={iconFillColor(theme)} />, {
width: 40,
height: 20,
}),
export const FillCrossHatchIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<g fill={iconFillColor(theme)} fillRule="evenodd" clipRule="evenodd">
<path d="M20.101 16H28.0934L36 8.95989V4H33.5779L20.101 16ZM30.5704 4L17.0935 16H9.10101L22.5779 4H30.5704ZM19.5704 4L6.09349 16H4V10.7475L11.5779 4H19.5704ZM8.57036 4H4V8.06952L8.57036 4ZM36 11.6378L31.101 16H36V11.6378ZM2 2V18H38V2H2Z" />
<path d="M14.0001 18L3.00006 4.00002L4.5727 2.76438L15.5727 16.7644L14.0001 18ZM25.0001 18L14.0001 4.00002L15.5727 2.76438L26.5727 16.7644L25.0001 18ZM36.0001 18L25.0001 4.00002L26.5727 2.76438L37.5727 16.7644L36.0001 18Z" />
</g>,
{ width: 40, height: 20 },
),
);
export const FillSolidIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(<path d="M2 2H38V18H2V2Z" fill={iconFillColor(theme)} />, {
width: 40,
height: 20,
}),
);
export const StrokeWidthIcon = React.memo(
({ theme, strokeWidth }: { theme: "light" | "dark"; strokeWidth: number }) =>
({ theme, strokeWidth }: { theme: Theme; strokeWidth: number }) =>
createIcon(
<path
d="M6 10H32"
@ -591,55 +580,52 @@ export const StrokeWidthIcon = React.memo(
),
);
export const StrokeStyleSolidIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2}
fill="none"
strokeLinecap="round"
/>,
{
width: 40,
height: 20,
},
),
export const StrokeStyleSolidIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2}
fill="none"
strokeLinecap="round"
/>,
{
width: 40,
height: 20,
},
),
);
export const StrokeStyleDashedIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2.5}
strokeDasharray={"10, 8"}
fill="none"
strokeLinecap="round"
/>,
{ width: 40, height: 20 },
),
export const StrokeStyleDashedIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2.5}
strokeDasharray={"10, 8"}
fill="none"
strokeLinecap="round"
/>,
{ width: 40, height: 20 },
),
);
export const StrokeStyleDottedIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M6 10H36"
stroke={iconFillColor(theme)}
strokeWidth={2.5}
strokeDasharray={"2, 4.5"}
fill="none"
strokeLinecap="round"
/>,
{ width: 40, height: 20 },
),
export const StrokeStyleDottedIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M6 10H36"
stroke={iconFillColor(theme)}
strokeWidth={2.5}
strokeDasharray={"2, 4.5"}
fill="none"
strokeLinecap="round"
/>,
{ width: 40, height: 20 },
),
);
export const SloppinessArchitectIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M3.00098 16.1691C6.28774 13.9744 19.6399 2.8905 22.7215 3.00082C25.8041 3.11113 19.1158 15.5488 21.4962 16.8309C23.8757 18.1131 34.4155 11.7148 37.0001 10.6919"
@ -652,22 +638,21 @@ export const SloppinessArchitectIcon = React.memo(
),
);
export const SloppinessArtistIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M3 17C6.68158 14.8752 16.1296 9.09849 22.0648 6.54922C28 3.99995 22.2896 13.3209 25 14C27.7104 14.6791 36.3757 9.6471 36.3757 9.6471M6.40706 15C13 11.1918 20.0468 1.51045 23.0234 3.0052C26 4.49995 20.457 12.8659 22.7285 16.4329C25 20 36.3757 13 36.3757 13"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
export const SloppinessArtistIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M3 17C6.68158 14.8752 16.1296 9.09849 22.0648 6.54922C28 3.99995 22.2896 13.3209 25 14C27.7104 14.6791 36.3757 9.6471 36.3757 9.6471M6.40706 15C13 11.1918 20.0468 1.51045 23.0234 3.0052C26 4.49995 20.457 12.8659 22.7285 16.4329C25 20 36.3757 13 36.3757 13"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
);
export const SloppinessCartoonistIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M3 15.6468C6.93692 13.5378 22.5544 2.81528 26.6206 3.00242C30.6877 3.18956 25.6708 15.3346 27.4009 16.7705C29.1309 18.2055 35.4001 12.4762 37 11.6177M3.97143 10.4917C6.61158 9.24563 16.3706 2.61886 19.8104 3.01724C23.2522 3.41472 22.0773 12.2013 24.6181 12.8783C27.1598 13.5536 33.3179 8.04068 35.0571 7.07244"
@ -680,52 +665,49 @@ export const SloppinessCartoonistIcon = React.memo(
),
);
export const EdgeSharpIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M10 17L10 5L35 5"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
export const EdgeSharpIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M10 17L10 5L35 5"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
);
export const EdgeRoundIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M10 17V15C10 8 13 5 21 5L33.5 5"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
export const EdgeRoundIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M10 17V15C10 8 13 5 21 5L33.5 5"
stroke={iconFillColor(theme)}
strokeWidth={2}
strokeLinecap="round"
fill="none"
/>,
{ width: 40, height: 20, mirror: true },
),
);
export const ArrowheadNoneIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2}
fill="none"
/>,
{
width: 40,
height: 20,
},
),
export const ArrowheadNoneIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M6 10H34"
stroke={iconFillColor(theme)}
strokeWidth={2}
fill="none"
/>,
{
width: 40,
height: 20,
},
),
);
export const ArrowheadArrowIcon = React.memo(
({ theme, flip = false }: { theme: "light" | "dark"; flip?: boolean }) =>
({ theme, flip = false }: { theme: Theme; flip?: boolean }) =>
createIcon(
<g
transform={flip ? "translate(40, 0) scale(-1, 1)" : ""}
@ -741,7 +723,7 @@ export const ArrowheadArrowIcon = React.memo(
);
export const ArrowheadDotIcon = React.memo(
({ theme, flip = false }: { theme: "light" | "dark"; flip?: boolean }) =>
({ theme, flip = false }: { theme: Theme; flip?: boolean }) =>
createIcon(
<g
stroke={iconFillColor(theme)}
@ -756,7 +738,7 @@ export const ArrowheadDotIcon = React.memo(
);
export const ArrowheadBarIcon = React.memo(
({ theme, flip = false }: { theme: "light" | "dark"; flip?: boolean }) =>
({ theme, flip = false }: { theme: Theme; flip?: boolean }) =>
createIcon(
<g transform={flip ? "translate(40, 0) scale(-1, 1)" : ""}>
<path
@ -770,41 +752,38 @@ export const ArrowheadBarIcon = React.memo(
),
);
export const FontSizeSmallIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 0 69.092 L 0 55.03 A 124.24 124.24 0 0 0 4.706 57.02 Q 6.826 57.863 8.708 58.5 A 53.466 53.466 0 0 0 12.231 59.571 Q 17.236 60.889 21.387 60.889 A 20.909 20.909 0 0 0 24.265 60.704 Q 25.719 60.502 26.903 60.077 A 8.649 8.649 0 0 0 29.028 58.985 Q 31.689 57.08 31.689 53.321 Q 31.689 51.221 30.518 49.585 A 10.126 10.126 0 0 0 29.282 48.177 Q 28.352 47.287 27.075 46.436 A 23.719 23.719 0 0 0 25.752 45.627 Q 23.774 44.492 20.176 42.735 A 254.44 254.44 0 0 0 17.822 41.602 Q 11.503 38.631 8.236 35.888 A 19.742 19.742 0 0 1 8.008 35.694 A 22.18 22.18 0 0 1 2.783 29.102 Q 0.83 25.342 0.83 20.313 A 22.471 22.471 0 0 1 1.733 13.778 A 17.283 17.283 0 0 1 7.251 5.42 A 21.486 21.486 0 0 1 15.177 1.272 Q 18.361 0.338 22.166 0.09 A 43.573 43.573 0 0 1 25 0 A 42.399 42.399 0 0 1 34.349 1.01 A 39.075 39.075 0 0 1 35.62 1.319 A 67.407 67.407 0 0 1 42.108 3.382 A 83.357 83.357 0 0 1 46.191 5.03 L 41.309 16.797 Q 35.596 14.453 31.86 13.526 A 30.762 30.762 0 0 0 25.417 12.612 A 28.337 28.337 0 0 0 24.512 12.598 A 14.846 14.846 0 0 0 22.022 12.793 Q 19.498 13.224 17.92 14.6 Q 15.625 16.602 15.625 19.824 Q 15.625 21.826 16.553 23.316 Q 17.48 24.805 19.507 26.197 A 18.343 18.343 0 0 0 20.659 26.912 Q 22.596 28.035 26.516 29.953 A 299.99 299.99 0 0 0 29.102 31.201 Q 37.91 35.412 41.841 39.642 A 16.553 16.553 0 0 1 42.822 40.796 A 17.675 17.675 0 0 1 46.301 49.233 A 23.517 23.517 0 0 1 46.533 52.588 A 21.581 21.581 0 0 1 45.471 59.515 A 17.733 17.733 0 0 1 39.575 67.823 Q 33.745 72.486 24.094 73.243 A 49.683 49.683 0 0 1 20.215 73.389 A 51.712 51.712 0 0 1 9.448 72.315 A 40.672 40.672 0 0 1 0 69.092 Z"
/>,
{ width: 47, height: 77 },
),
export const FontSizeSmallIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 0 69.092 L 0 55.03 A 124.24 124.24 0 0 0 4.706 57.02 Q 6.826 57.863 8.708 58.5 A 53.466 53.466 0 0 0 12.231 59.571 Q 17.236 60.889 21.387 60.889 A 20.909 20.909 0 0 0 24.265 60.704 Q 25.719 60.502 26.903 60.077 A 8.649 8.649 0 0 0 29.028 58.985 Q 31.689 57.08 31.689 53.321 Q 31.689 51.221 30.518 49.585 A 10.126 10.126 0 0 0 29.282 48.177 Q 28.352 47.287 27.075 46.436 A 23.719 23.719 0 0 0 25.752 45.627 Q 23.774 44.492 20.176 42.735 A 254.44 254.44 0 0 0 17.822 41.602 Q 11.503 38.631 8.236 35.888 A 19.742 19.742 0 0 1 8.008 35.694 A 22.18 22.18 0 0 1 2.783 29.102 Q 0.83 25.342 0.83 20.313 A 22.471 22.471 0 0 1 1.733 13.778 A 17.283 17.283 0 0 1 7.251 5.42 A 21.486 21.486 0 0 1 15.177 1.272 Q 18.361 0.338 22.166 0.09 A 43.573 43.573 0 0 1 25 0 A 42.399 42.399 0 0 1 34.349 1.01 A 39.075 39.075 0 0 1 35.62 1.319 A 67.407 67.407 0 0 1 42.108 3.382 A 83.357 83.357 0 0 1 46.191 5.03 L 41.309 16.797 Q 35.596 14.453 31.86 13.526 A 30.762 30.762 0 0 0 25.417 12.612 A 28.337 28.337 0 0 0 24.512 12.598 A 14.846 14.846 0 0 0 22.022 12.793 Q 19.498 13.224 17.92 14.6 Q 15.625 16.602 15.625 19.824 Q 15.625 21.826 16.553 23.316 Q 17.48 24.805 19.507 26.197 A 18.343 18.343 0 0 0 20.659 26.912 Q 22.596 28.035 26.516 29.953 A 299.99 299.99 0 0 0 29.102 31.201 Q 37.91 35.412 41.841 39.642 A 16.553 16.553 0 0 1 42.822 40.796 A 17.675 17.675 0 0 1 46.301 49.233 A 23.517 23.517 0 0 1 46.533 52.588 A 21.581 21.581 0 0 1 45.471 59.515 A 17.733 17.733 0 0 1 39.575 67.823 Q 33.745 72.486 24.094 73.243 A 49.683 49.683 0 0 1 20.215 73.389 A 51.712 51.712 0 0 1 9.448 72.315 A 40.672 40.672 0 0 1 0 69.092 Z"
/>,
{ width: 47, height: 77 },
),
);
export const FontSizeMediumIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 44.092 71.387 L 30.225 71.387 L 13.037 15.381 L 12.598 15.381 A 1505.093 1505.093 0 0 1 12.959 22.313 Q 13.426 31.715 13.508 36.4 A 102.991 102.991 0 0 1 13.525 38.184 L 13.525 71.387 L 0 71.387 L 0 0 L 20.605 0 L 37.5 54.59 L 37.793 54.59 L 55.713 0 L 76.318 0 L 76.318 71.387 L 62.207 71.387 L 62.207 37.598 Q 62.207 35.205 62.28 32.08 A 160.703 160.703 0 0 1 62.326 30.544 Q 62.452 26.754 62.866 17.168 A 5390.536 5390.536 0 0 1 62.939 15.479 L 62.5 15.479 L 44.092 71.387 Z"
/>,
{ width: 77, height: 75 },
),
export const FontSizeMediumIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 44.092 71.387 L 30.225 71.387 L 13.037 15.381 L 12.598 15.381 A 1505.093 1505.093 0 0 1 12.959 22.313 Q 13.426 31.715 13.508 36.4 A 102.991 102.991 0 0 1 13.525 38.184 L 13.525 71.387 L 0 71.387 L 0 0 L 20.605 0 L 37.5 54.59 L 37.793 54.59 L 55.713 0 L 76.318 0 L 76.318 71.387 L 62.207 71.387 L 62.207 37.598 Q 62.207 35.205 62.28 32.08 A 160.703 160.703 0 0 1 62.326 30.544 Q 62.452 26.754 62.866 17.168 A 5390.536 5390.536 0 0 1 62.939 15.479 L 62.5 15.479 L 44.092 71.387 Z"
/>,
{ width: 77, height: 75 },
),
);
export const FontSizeLargeIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 44.092 71.387 L 0 71.387 L 0 0 L 15.137 0 L 15.137 58.887 L 44.092 58.887 L 44.092 71.387 Z"
/>,
{ width: 45, height: 75 },
),
export const FontSizeLargeIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
fill={iconFillColor(theme)}
d="M 44.092 71.387 L 0 71.387 L 0 0 L 15.137 0 L 15.137 58.887 L 44.092 58.887 L 44.092 71.387 Z"
/>,
{ width: 45, height: 75 },
),
);
export const FontSizeExtraLargeIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<path
fill={iconFillColor(theme)}
@ -815,7 +794,7 @@ export const FontSizeExtraLargeIcon = React.memo(
);
export const FontFamilyHandDrawnIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
({ theme }: { theme: Theme }) =>
createIcon(
<path
fill={iconFillColor(theme)}
@ -825,67 +804,62 @@ export const FontFamilyHandDrawnIcon = React.memo(
),
);
export const FontFamilyNormalIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
fill={iconFillColor(theme)}
d="M 63.818 71.68 L 54.492 71.68 L 45.898 49.561 L 17.578 49.561 L 9.082 71.68 L 0 71.68 L 27.881 0 L 35.986 0 L 63.818 71.68 Z M 20.605 41.602 L 43.213 41.602 L 35.205 19.971 L 31.787 9.277 Q 30.322 15.137 28.711 19.971 L 20.605 41.602 Z"
/>
<path
fill={iconFillColor(theme)}
d="M 68.994 71.68 L 52.686 71.68 L 47.51 54.688 L 21.484 54.688 L 16.309 71.68 L 0 71.68 L 25.195 0 L 43.701 0 L 68.994 71.68 Z M 25.293 41.992 L 43.896 41.992 A 27590.463 27590.463 0 0 1 42.2 36.532 Q 36.965 19.676 35.937 16.273 A 120.932 120.932 0 0 1 35.815 15.869 A 131.65 131.65 0 0 1 35.396 14.435 Q 34.951 12.879 34.675 11.741 A 34.866 34.866 0 0 1 34.521 11.084 A 141.762 141.762 0 0 1 33.706 14.075 Q 31.482 21.957 25.293 41.992 Z"
/>
</>,
{ width: 70, height: 78 },
),
);
export const FontFamilyCodeIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<>
<path
fill={iconFillColor(theme)}
d="M278.9 511.5l-61-17.7c-6.4-1.8-10-8.5-8.2-14.9L346.2 8.7c1.8-6.4 8.5-10 14.9-8.2l61 17.7c6.4 1.8 10 8.5 8.2 14.9L293.8 503.3c-1.9 6.4-8.5 10.1-14.9 8.2zm-114-112.2l43.5-46.4c4.6-4.9 4.3-12.7-.8-17.2L117 256l90.6-79.7c5.1-4.5 5.5-12.3.8-17.2l-43.5-46.4c-4.5-4.8-12.1-5.1-17-.5L3.8 247.2c-5.1 4.7-5.1 12.8 0 17.5l144.1 135.1c4.9 4.6 12.5 4.4 17-.5zm327.2.6l144.1-135.1c5.1-4.7 5.1-12.8 0-17.5L492.1 112.1c-4.8-4.5-12.4-4.3-17 .5L431.6 159c-4.6 4.9-4.3 12.7.8 17.2L523 256l-90.6 79.7c-5.1 4.5-5.5 12.3-.8 17.2l43.5 46.4c4.5 4.9 12.1 5.1 17 .6z"
/>
</>,
{ width: 640, height: 512 },
),
);
export const TextAlignLeftIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
export const FontFamilyNormalIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M12.83 352h262.34A12.82 12.82 0 00288 339.17v-38.34A12.82 12.82 0 00275.17 288H12.83A12.82 12.82 0 000 300.83v38.34A12.82 12.82 0 0012.83 352zm0-256h262.34A12.82 12.82 0 00288 83.17V44.83A12.82 12.82 0 00275.17 32H12.83A12.82 12.82 0 000 44.83v38.34A12.82 12.82 0 0012.83 96zM432 160H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0 256H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16z"
fill={iconFillColor(theme)}
strokeLinecap="round"
/>,
{ width: 448, height: 512 },
),
d="M 63.818 71.68 L 54.492 71.68 L 45.898 49.561 L 17.578 49.561 L 9.082 71.68 L 0 71.68 L 27.881 0 L 35.986 0 L 63.818 71.68 Z M 20.605 41.602 L 43.213 41.602 L 35.205 19.971 L 31.787 9.277 Q 30.322 15.137 28.711 19.971 L 20.605 41.602 Z"
/>
<path
fill={iconFillColor(theme)}
d="M 68.994 71.68 L 52.686 71.68 L 47.51 54.688 L 21.484 54.688 L 16.309 71.68 L 0 71.68 L 25.195 0 L 43.701 0 L 68.994 71.68 Z M 25.293 41.992 L 43.896 41.992 A 27590.463 27590.463 0 0 1 42.2 36.532 Q 36.965 19.676 35.937 16.273 A 120.932 120.932 0 0 1 35.815 15.869 A 131.65 131.65 0 0 1 35.396 14.435 Q 34.951 12.879 34.675 11.741 A 34.866 34.866 0 0 1 34.521 11.084 A 141.762 141.762 0 0 1 33.706 14.075 Q 31.482 21.957 25.293 41.992 Z"
/>
</>,
{ width: 70, height: 78 },
),
);
export const TextAlignCenterIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
export const FontFamilyCodeIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<>
<path
d="M432 160H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0 256H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zM108.1 96h231.81A12.09 12.09 0 00352 83.9V44.09A12.09 12.09 0 00339.91 32H108.1A12.09 12.09 0 0096 44.09V83.9A12.1 12.1 0 00108.1 96zm231.81 256A12.09 12.09 0 00352 339.9v-39.81A12.09 12.09 0 00339.91 288H108.1A12.09 12.09 0 0096 300.09v39.81a12.1 12.1 0 0012.1 12.1z"
fill={iconFillColor(theme)}
/>,
{ width: 448, height: 512 },
),
d="M278.9 511.5l-61-17.7c-6.4-1.8-10-8.5-8.2-14.9L346.2 8.7c1.8-6.4 8.5-10 14.9-8.2l61 17.7c6.4 1.8 10 8.5 8.2 14.9L293.8 503.3c-1.9 6.4-8.5 10.1-14.9 8.2zm-114-112.2l43.5-46.4c4.6-4.9 4.3-12.7-.8-17.2L117 256l90.6-79.7c5.1-4.5 5.5-12.3.8-17.2l-43.5-46.4c-4.5-4.8-12.1-5.1-17-.5L3.8 247.2c-5.1 4.7-5.1 12.8 0 17.5l144.1 135.1c4.9 4.6 12.5 4.4 17-.5zm327.2.6l144.1-135.1c5.1-4.7 5.1-12.8 0-17.5L492.1 112.1c-4.8-4.5-12.4-4.3-17 .5L431.6 159c-4.6 4.9-4.3 12.7.8 17.2L523 256l-90.6 79.7c-5.1 4.5-5.5 12.3-.8 17.2l43.5 46.4c4.5 4.9 12.1 5.1 17 .6z"
/>
</>,
{ width: 640, height: 512 },
),
);
export const TextAlignRightIcon = React.memo(
({ theme }: { theme: "light" | "dark" }) =>
createIcon(
<path
d="M16 224h416a16 16 0 0016-16v-32a16 16 0 00-16-16H16a16 16 0 00-16 16v32a16 16 0 0016 16zm416 192H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm3.17-384H172.83A12.82 12.82 0 00160 44.83v38.34A12.82 12.82 0 00172.83 96h262.34A12.82 12.82 0 00448 83.17V44.83A12.82 12.82 0 00435.17 32zm0 256H172.83A12.82 12.82 0 00160 300.83v38.34A12.82 12.82 0 00172.83 352h262.34A12.82 12.82 0 00448 339.17v-38.34A12.82 12.82 0 00435.17 288z"
fill={iconFillColor(theme)}
strokeLinecap="round"
/>,
{ width: 448, height: 512 },
),
export const TextAlignLeftIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M12.83 352h262.34A12.82 12.82 0 00288 339.17v-38.34A12.82 12.82 0 00275.17 288H12.83A12.82 12.82 0 000 300.83v38.34A12.82 12.82 0 0012.83 352zm0-256h262.34A12.82 12.82 0 00288 83.17V44.83A12.82 12.82 0 00275.17 32H12.83A12.82 12.82 0 000 44.83v38.34A12.82 12.82 0 0012.83 96zM432 160H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0 256H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16z"
fill={iconFillColor(theme)}
strokeLinecap="round"
/>,
{ width: 448, height: 512 },
),
);
export const TextAlignCenterIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M432 160H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm0 256H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zM108.1 96h231.81A12.09 12.09 0 00352 83.9V44.09A12.09 12.09 0 00339.91 32H108.1A12.09 12.09 0 0096 44.09V83.9A12.1 12.1 0 00108.1 96zm231.81 256A12.09 12.09 0 00352 339.9v-39.81A12.09 12.09 0 00339.91 288H108.1A12.09 12.09 0 0096 300.09v39.81a12.1 12.1 0 0012.1 12.1z"
fill={iconFillColor(theme)}
/>,
{ width: 448, height: 512 },
),
);
export const TextAlignRightIcon = React.memo(({ theme }: { theme: Theme }) =>
createIcon(
<path
d="M16 224h416a16 16 0 0016-16v-32a16 16 0 00-16-16H16a16 16 0 00-16 16v32a16 16 0 0016 16zm416 192H16a16 16 0 00-16 16v32a16 16 0 0016 16h416a16 16 0 0016-16v-32a16 16 0 00-16-16zm3.17-384H172.83A12.82 12.82 0 00160 44.83v38.34A12.82 12.82 0 00172.83 96h262.34A12.82 12.82 0 00448 83.17V44.83A12.82 12.82 0 00435.17 32zm0 256H172.83A12.82 12.82 0 00160 300.83v38.34A12.82 12.82 0 00172.83 352h262.34A12.82 12.82 0 00448 339.17v-38.34A12.82 12.82 0 00435.17 288z"
fill={iconFillColor(theme)}
strokeLinecap="round"
/>,
{ width: 448, height: 512 },
),
);

View File

@ -70,6 +70,11 @@ export const FONT_FAMILY = {
Cascadia: 3,
};
export const THEME = {
LIGHT: "light",
DARK: "dark",
};
export const WINDOWS_EMOJI_FALLBACK_FONT = "Segoe UI Emoji";
export const DEFAULT_FONT_SIZE = 20;

View File

@ -1,10 +1,11 @@
import { Point } from "../types";
import { FONT_FAMILY } from "../constants";
import { FONT_FAMILY, THEME } from "../constants";
export type ChartType = "bar" | "line";
export type FillStyle = "hachure" | "cross-hatch" | "solid";
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
export type Theme = typeof THEME[keyof typeof THEME];
export type FontString = string & { _brand: "fontString" };
export type GroupId = string;
export type PointerType = "mouse" | "pen" | "touch";

View File

@ -1,9 +1,11 @@
import oc from "open-color";
import React from "react";
import { THEME } from "../../constants";
import { Theme } from "../../element/types";
// https://github.com/tholman/github-corners
export const GitHubCorner = React.memo(
({ theme, dir }: { theme: "light" | "dark"; dir: string }) => (
({ theme, dir }: { theme: Theme; dir: string }) => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="40"
@ -25,18 +27,18 @@ export const GitHubCorner = React.memo(
>
<path
d="M0 0l115 115h15l12 27 108 108V0z"
fill={theme === "light" ? oc.gray[6] : oc.gray[7]}
fill={theme === THEME.LIGHT ? oc.gray[6] : oc.gray[7]}
/>
<path
className="octo-arm"
d="M128 109c-15-9-9-19-9-19 3-7 2-11 2-11-1-7 3-2 3-2 4 5 2 11 2 11-3 10 5 15 9 16"
style={{ transformOrigin: "130px 106px" }}
fill={theme === "light" ? oc.white : "var(--default-bg-color)"}
fill={theme === THEME.LIGHT ? oc.white : "var(--default-bg-color)"}
/>
<path
className="octo-body"
d="M115 115s4 2 5 0l14-14c3-2 6-3 8-3-8-11-15-24 2-41 5-5 10-7 16-7 1-2 3-7 12-11 0 0 5 3 7 16 4 2 8 5 12 9s7 8 9 12c14 3 17 7 17 7-4 8-9 11-11 11 0 6-2 11-7 16-16 16-30 10-41 2 0 3-1 7-5 11l-12 11c-1 1 1 5 1 5z"
fill={theme === "light" ? oc.white : "var(--default-bg-color)"}
fill={theme === THEME.LIGHT ? oc.white : "var(--default-bg-color)"}
/>
</a>
</svg>

View File

@ -11,6 +11,20 @@ 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.
-->
## Unreleased
## Excalidraw API
### Features
- Export `THEME` constant from the package so host can use this when passing the theme
#### BREAKING CHANGE
The `Appearance` type is now removed and renamed to `Theme` so `Theme` type needs to be used.
---
## 0.10.0 (2021-10-13)
## Excalidraw API

View File

@ -371,7 +371,7 @@ To view the full example visit :point_down:
| [`zenModeEnabled`](#zenModeEnabled) | boolean | | This implies if the zen mode is enabled |
| [`gridModeEnabled`](#gridModeEnabled) | boolean | | This implies if the grid mode is enabled |
| [`libraryReturnUrl`](#libraryReturnUrl) | string | | What URL should [libraries.excalidraw.com](https://libraries.excalidraw.com) be installed to |
| [`theme`](#theme) | `light` or `dark` | | The theme of the Excalidraw component |
| [`theme`](#theme) | [THEME.LIGHT](#THEME-1) &#124; [THEME.LIGHT](#THEME-1) | [THEME.LIGHT](#THEME-1) | The theme of the Excalidraw component |
| [`name`](#name) | string | | Name of the drawing |
| [`UIOptions`](#UIOptions) | <pre>{ canvasActions: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L208"> CanvasActions<a/> }</pre> | [DEFAULT UI OPTIONS](https://github.com/excalidraw/excalidraw/blob/master/src/constants.ts#L129) | To customise UI options. Currently we support customising [`canvas actions`](#canvasActions) |
| [`onPaste`](#onPaste) | <pre>(data: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/clipboard.ts#L17">ClipboardData</a>, event: ClipboardEvent &#124; null) => boolean</pre> | | Callback to be triggered if passed when the something is pasted in to the scene |
@ -564,7 +564,7 @@ If supplied, this URL will be used when user tries to install a library from [li
#### `theme`
This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app.
This prop controls Excalidraw's theme. When supplied, the value takes precedence over `intialData.appState.theme`, the theme will be fully controlled by the host app, and users won't be able to toggle it from within the app. You can use [`THEME`](#THEME-1) to specify the theme.
#### `name`
@ -612,11 +612,7 @@ This callback must return a `boolean` value or a [promise](https://developer.moz
In case you want to prevent the excalidraw paste action you must return `false`, it will stop the native excalidraw clipboard management flow (nothing will be pasted into the scene).
### Does it support collaboration ?
No, Excalidraw package doesn't come with collaboration built in, since the implementation is specific to each host app. We expose APIs which you can use to communicate with Excalidraw which you can use to implement it. You can check our own implementation [here](https://github.com/excalidraw/excalidraw/blob/master/src/excalidraw-app/index.tsx).
### importLibrary
#### `importLibrary`
Imports library from given URL. You should call this on `hashchange`, passing the `addLibrary` value if you detect it as shown below. Optionally pass a CSRF `token` to skip prompting during installation (retrievable via `token` key from the url coming from [https://libraries.excalidraw.com](https://libraries.excalidraw.com/)).
@ -638,17 +634,17 @@ useEffect(() => {
Try out the [Demo](#Demo) to see it in action.
### detectScroll
#### `detectScroll`
Indicates whether Excalidraw should listen for `scroll` event on the nearest scrollable container in the DOM tree and recompute the coordinates (e.g. to correctly handle the cursor) when the component's position changes. You can disable this when you either know this doesn't affect your app or you want to take care of it yourself (calling the [`refresh()`](#ref) method).
### handleKeyboardGlobally
#### `handleKeyboardGlobally`
Indicates whether to bind keyboard events to `document`. Disabled by default, meaning the keyboard events are bound to the Excalidraw component. This allows for multiple Excalidraw components to live on the same page, and ensures that Excalidraw keyboard handling doesn't collide with your app's (or the browser) when the component isn't focused.
Enable this if you want Excalidraw to handle keyboard even if the component isn't focused (e.g. a user is interacting with the navbar, sidebar, or similar).
### onLibraryChange
#### `onLibraryChange`
Ths callback if supplied will get triggered when the library is updated and has the below signature.
@ -658,58 +654,17 @@ Ths callback if supplied will get triggered when the library is updated and has
It is invoked with empty items when user clears the library. You can use this callback when you want to do something additional when library is updated for example persisting it to local storage.
### id
#### `id`
The unique id of the excalidraw component. This can be used to identify the excalidraw component, for example importing the library items to the excalidraw component from where it was initiated when you have multiple excalidraw components rendered on the same page as shown in [multiple excalidraw demo](https://codesandbox.io/s/multiple-excalidraw-k1xx5).
### autoFocus
#### `autoFocus`
This prop implies whether to focus the Excalidraw component on page load. Defaults to false.
### Extra API's
### Does it support collaboration ?
#### `getSceneVersion`
**How to use**
<pre>
import { getSceneVersion } from "@excalidraw/excalidraw-next";
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
</pre>
This function returns the current scene version.
#### `isInvisiblySmallElement`
**_Signature_**
<pre>
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>): boolean
</pre>
**How to use**
```js
import { isInvisiblySmallElement } from "@excalidraw/excalidraw-next";
```
Returns `true` if element is invisibly small (e.g. width & height are zero).
#### `getElementMap`
**_Signature_**
<pre>
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
</pre>
**How to use**
```js
import { getElementsMap } from "@excalidraw/excalidraw-next";
```
This function returns an object where each element is mapped to its id.
No, Excalidraw package doesn't come with collaboration built in, since the implementation is specific to each host app. We expose APIs which you can use to communicate with Excalidraw which you can use to implement it. You can check our own implementation [here](https://github.com/excalidraw/excalidraw/blob/master/src/excalidraw-app/index.tsx).
### Restore utilities
@ -767,19 +722,6 @@ import { restore } from "@excalidraw/excalidraw-next";
This function makes sure elements and state is set to appropriate values and set to default value if not present. It is a combination of [restoreElements](#restoreElements) and [restoreAppState](#restoreAppState).
#### `serializeAsJSON`
**_Signature_**
<pre>
serializeAsJSON({
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>,
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42">AppState</a>,
}): string
</pre>
Takes the scene elements and state and returns a JSON string. Deleted `elements`as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L16) source for details).
### Export utilities
#### `exportToCanvas`
@ -864,7 +806,113 @@ This function returns a promise which resolves to svg of the exported drawing.
| exportWithDarkMode | boolean | false | Indicates whether to export with dark mode |
| exportEmbedScene | boolean | false | Indicates whether scene data should be embedded in svg. This will increase the svg size. |
### FONT_FAMILY
### Extra API's
#### `serializeAsJSON`
**_Signature_**
<pre>
serializeAsJSON({
elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>,
appState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42">AppState</a>,
}): string
</pre>
Takes the scene elements and state and returns a JSON string. Deleted `elements`as well as most properties from `AppState` are removed from the resulting JSON. (see [`serializeAsJSON()`](https://github.com/excalidraw/excalidraw/blob/master/src/data/json.ts#L16) source for details).
#### `getSceneVersion`
**How to use**
<pre>
import { getSceneVersion } from "@excalidraw/excalidraw-next";
getSceneVersion(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>)
</pre>
This function returns the current scene version.
#### `isInvisiblySmallElement`
**_Signature_**
<pre>
isInvisiblySmallElement(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>): boolean
</pre>
**How to use**
```js
import { isInvisiblySmallElement } from "@excalidraw/excalidraw-next";
```
Returns `true` if element is invisibly small (e.g. width & height are zero).
#### `getElementMap`
**_Signature_**
<pre>
getElementsMap(elements: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement[]</a>): {[id: string]: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L78">ExcalidrawElement</a>}
</pre>
**How to use**
```js
import { getElementsMap } from "@excalidraw/excalidraw-next";
```
This function returns an object where each element is mapped to its id.
#### `loadLibraryFromBlob`
```js
import { loadLibraryFromBlob } from "@excalidraw/excalidraw-next";
```
**_Signature_**
<pre>
loadLibraryFromBlob(blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>)
</pre>
This function loads the library from the blob.
#### `loadFromBlob`
**How to use**
```js
import { loadFromBlob } from "@excalidraw/excalidraw-next";
```
**Signature**
<pre>
loadFromBlob(blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>, localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42">AppState</a> | null)
</pre>
This function loads the scene data from the blob. If you pass `localAppState`, `localAppState` value will be preferred over the `appState` derived from `blob`
#### `getFreeDrawSvgPath`
**How to use**
```js
import { getFreeDrawSvgPath } from "@excalidraw/excalidraw-next";
```
**Signature**
<pre>
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L127">ExcalidrawFreeDrawElement</a>
</pre>
This function returns the free draw svg path for the element.
### Exported constants
#### `FONT_FAMILY`
**How to use**
@ -882,51 +930,22 @@ import { FONT_FAMILY } from "@excalidraw/excalidraw-next";
Defaults to `FONT_FAMILY.Virgil` unless passed in `initialData.appState.currentItemFontFamily`.
### loadLibraryFromBlob
```js
import { loadLibraryFromBlob } from "@excalidraw/excalidraw-next";
```
**_Signature_**
<pre>
loadLibraryFromBlob(blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>)
</pre>
This function loads the library from the blob.
### loadFromBlob
#### `THEME`
**How to use**
```js
import { loadFromBlob } from "@excalidraw/excalidraw-next";
import { THEME } from "@excalidraw/excalidraw-next";
```
**Signature**
`THEME` contains all the themes supported by `Excalidraw` as explained below
<pre>
loadFromBlob(blob: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">Blob</a>, localAppState: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/types.ts#L42">AppState</a> | null)
</pre>
| Theme | Description |
| ----- | --------------- |
| LIGHT | The light theme |
| DARK | The Dark theme |
This function loads the scene data from the blob. If you pass `localAppState`, `localAppState` value will be preferred over the `appState` derived from `blob`
### getFreeDrawSvgPath
**How to use**
```js
import { getFreeDrawSvgPath } from "@excalidraw/excalidraw-next";
```
**Signature**
<pre>
getFreeDrawSvgPath(element: <a href="https://github.com/excalidraw/excalidraw/blob/master/src/element/types.ts#L127">ExcalidrawFreeDrawElement</a>
</pre>
This function returns the free draw svg path for the element.
Defaults to `THEME.LIGHT` unless passed in `initialData.appState.theme`
## Need help?

View File

@ -183,4 +183,4 @@ export {
loadFromBlob,
getFreeDrawSvgPath,
} from "../../packages/utils";
export { FONT_FAMILY } from "../../constants";
export { FONT_FAMILY, THEME } from "../../constants";

View File

@ -2,7 +2,7 @@ import React from "react";
import { fireEvent, GlobalTestState, render } from "../test-utils";
import Excalidraw from "../../packages/excalidraw/index";
import { queryByText, queryByTestId } from "@testing-library/react";
import { GRID_SIZE } from "../../constants";
import { GRID_SIZE, THEME } from "../../constants";
import { t } from "../../i18n";
const { h } = window;
@ -91,7 +91,7 @@ describe("<Excalidraw/>", () => {
describe("Test theme prop", () => {
it('should show the dark mode toggle when the theme prop is "undefined"', async () => {
const { container } = await render(<Excalidraw />);
expect(h.state.theme).toBe("light");
expect(h.state.theme).toBe(THEME.LIGHT);
const darkModeToggle = queryByTestId(container, "toggle-dark-mode");
@ -100,7 +100,7 @@ describe("<Excalidraw/>", () => {
it('should not show the dark mode toggle when the theme prop is not "undefined"', async () => {
const { container } = await render(<Excalidraw theme="dark" />);
expect(h.state.theme).toBe("dark");
expect(h.state.theme).toBe(THEME.DARK);
expect(queryByTestId(container, "toggle-dark-mode")).toBe(null);
});

View File

@ -10,6 +10,7 @@ import {
Arrowhead,
ChartType,
FontFamilyValues,
Theme,
} from "./element/types";
import { SHAPES } from "./shapes";
import { Point as RoughPoint } from "roughjs/bin/geometry";
@ -98,7 +99,7 @@ export type AppState = {
showHelpDialog: boolean;
toastMessage: string | null;
zenModeEnabled: boolean;
theme: "light" | "dark";
theme: Theme;
gridSize: number | null;
viewModeEnabled: boolean;
@ -192,7 +193,7 @@ export interface ExcalidrawProps {
zenModeEnabled?: boolean;
gridModeEnabled?: boolean;
libraryReturnUrl?: string;
theme?: "dark" | "light";
theme?: Theme;
name?: string;
renderCustomStats?: (
elements: readonly NonDeletedExcalidrawElement[],