refactor: FONT_FAMILY and related helpers
This commit is contained in:
parent
de1ebad755
commit
ffa4cea61c
|
@ -10,13 +10,13 @@ import { FONT_FAMILY } from "@excalidraw/excalidraw";
|
|||
|
||||
`FONT_FAMILY` contains all the font families used in `Excalidraw` as explained below
|
||||
|
||||
| Font Family | Description |
|
||||
| ----------- | ---------------------- |
|
||||
| `Virgil` | The `handwritten` font |
|
||||
| `Helvetica` | The `Normal` Font |
|
||||
| `Cascadia` | The `Code` Font |
|
||||
| Font Family | Description |
|
||||
| ------------ | ------------------------------------------- |
|
||||
| `HAND_DRAWN` | The handwritten font (by default, `Virgil`) |
|
||||
| `NORMAL` | The regular font (by default, `Helvetica`) |
|
||||
| `CODE` | The code font (by default, `Cascadia`) |
|
||||
|
||||
Defaults to `FONT_FAMILY.Virgil` unless passed in `initialData.appState.currentItemFontFamily`.
|
||||
Defaults to `HAND_DRAWN` unless passed in `initialData.appState.currentItemFontFamily`.
|
||||
|
||||
### THEME
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import {
|
|||
computeBoundTextPosition,
|
||||
computeContainerDimensionForBoundText,
|
||||
getBoundTextElement,
|
||||
getFontString,
|
||||
measureText,
|
||||
redrawTextBoundingBox,
|
||||
} from "../element/textElement";
|
||||
|
@ -31,7 +32,6 @@ import {
|
|||
} from "../element/types";
|
||||
import { AppState } from "../types";
|
||||
import { Mutable } from "../utility-types";
|
||||
import { getFontString } from "../utils";
|
||||
import { register } from "./register";
|
||||
|
||||
export const actionUnbindText = register({
|
||||
|
|
|
@ -74,7 +74,7 @@ import {
|
|||
ExcalidrawElement,
|
||||
ExcalidrawLinearElement,
|
||||
ExcalidrawTextElement,
|
||||
FontFamilyValues,
|
||||
FontFamilyId,
|
||||
TextAlign,
|
||||
VerticalAlign,
|
||||
} from "../element/types";
|
||||
|
@ -689,22 +689,22 @@ export const actionChangeFontFamily = register({
|
|||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => {
|
||||
const options: {
|
||||
value: FontFamilyValues;
|
||||
value: FontFamilyId;
|
||||
text: string;
|
||||
icon: JSX.Element;
|
||||
}[] = [
|
||||
{
|
||||
value: FONT_FAMILY.Virgil,
|
||||
value: FONT_FAMILY.HAND_DRAWN.fontFamilyId,
|
||||
text: t("labels.handDrawn"),
|
||||
icon: FreedrawIcon,
|
||||
},
|
||||
{
|
||||
value: FONT_FAMILY.Helvetica,
|
||||
value: FONT_FAMILY.NORMAL.fontFamilyId,
|
||||
text: t("labels.normal"),
|
||||
icon: FontFamilyNormalIcon,
|
||||
},
|
||||
{
|
||||
value: FONT_FAMILY.Cascadia,
|
||||
value: FONT_FAMILY.CODE.fontFamilyId,
|
||||
text: t("labels.code"),
|
||||
icon: FontFamilyCodeIcon,
|
||||
},
|
||||
|
@ -713,7 +713,7 @@ export const actionChangeFontFamily = register({
|
|||
return (
|
||||
<fieldset>
|
||||
<legend>{t("labels.fontFamily")}</legend>
|
||||
<ButtonIconSelect<FontFamilyValues | false>
|
||||
<ButtonIconSelect<FontFamilyId | false>
|
||||
group="font-family"
|
||||
options={options}
|
||||
value={getFormValue(
|
||||
|
|
|
@ -231,7 +231,6 @@ import {
|
|||
import {
|
||||
debounce,
|
||||
distance,
|
||||
getFontString,
|
||||
getNearestScrollableContainer,
|
||||
isInputLike,
|
||||
isToolIcon,
|
||||
|
@ -298,6 +297,7 @@ import {
|
|||
getContainerCenter,
|
||||
getContainerElement,
|
||||
getDefaultLineHeight,
|
||||
getFontString,
|
||||
getLineHeightInPx,
|
||||
getTextBindableContainerAtPosition,
|
||||
isMeasureTextSupported,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import cssVariables from "./css/variables.module.scss";
|
||||
import { AppProps } from "./types";
|
||||
import { ExcalidrawElement, FontFamilyValues } from "./element/types";
|
||||
import { ExcalidrawElement, FontFamilyId } from "./element/types";
|
||||
import { COLOR_PALETTE } from "./colors";
|
||||
|
||||
export const isDarwin = /Mac|iPod|iPhone|iPad/.test(navigator.platform);
|
||||
|
@ -94,10 +94,19 @@ export const CLASSES = {
|
|||
|
||||
// 1-based in case we ever do `if(element.fontFamily)`
|
||||
export const FONT_FAMILY = {
|
||||
Virgil: 1,
|
||||
Helvetica: 2,
|
||||
Cascadia: 3,
|
||||
};
|
||||
HAND_DRAWN: {
|
||||
fontFamilyId: 1,
|
||||
fontFamily: "Virgil",
|
||||
},
|
||||
NORMAL: {
|
||||
fontFamilyId: 2,
|
||||
fontFamily: "Helvetica",
|
||||
},
|
||||
CODE: {
|
||||
fontFamilyId: 3,
|
||||
fontFamily: "Cascadia",
|
||||
},
|
||||
} as const;
|
||||
|
||||
export const THEME = {
|
||||
LIGHT: "light",
|
||||
|
@ -119,7 +128,8 @@ export const WINDOWS_EMOJI_FALLBACK_FONT = "Segoe UI Emoji";
|
|||
|
||||
export const MIN_FONT_SIZE = 1;
|
||||
export const DEFAULT_FONT_SIZE = 20;
|
||||
export const DEFAULT_FONT_FAMILY: FontFamilyValues = FONT_FAMILY.Virgil;
|
||||
export const DEFAULT_FONT_FAMILY: FontFamilyId =
|
||||
FONT_FAMILY.HAND_DRAWN.fontFamilyId;
|
||||
export const DEFAULT_TEXT_ALIGN = "left";
|
||||
export const DEFAULT_VERTICAL_ALIGN = "top";
|
||||
export const DEFAULT_VERSION = "{version}";
|
||||
|
|
|
@ -2,7 +2,6 @@ import {
|
|||
ExcalidrawElement,
|
||||
ExcalidrawSelectionElement,
|
||||
ExcalidrawTextElement,
|
||||
FontFamilyValues,
|
||||
PointBinding,
|
||||
StrokeRoundness,
|
||||
} from "../element/types";
|
||||
|
@ -22,11 +21,9 @@ import {
|
|||
import { isTextElement, isUsingAdaptiveRadius } from "../element/typeChecks";
|
||||
import { randomId } from "../random";
|
||||
import {
|
||||
DEFAULT_FONT_FAMILY,
|
||||
DEFAULT_TEXT_ALIGN,
|
||||
DEFAULT_VERTICAL_ALIGN,
|
||||
PRECEDING_ELEMENT_KEY,
|
||||
FONT_FAMILY,
|
||||
ROUNDNESS,
|
||||
DEFAULT_SIDEBAR,
|
||||
DEFAULT_ELEMENT_PROPS,
|
||||
|
@ -34,12 +31,14 @@ import {
|
|||
import { getDefaultAppState } from "../appState";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import { bumpVersion } from "../element/mutateElement";
|
||||
import { getFontString, getUpdatedTimestamp, updateActiveTool } from "../utils";
|
||||
import { getUpdatedTimestamp, updateActiveTool } from "../utils";
|
||||
import { arrayToMap } from "../utils";
|
||||
import { MarkOptional, Mutable } from "../utility-types";
|
||||
import {
|
||||
detectLineHeight,
|
||||
getDefaultLineHeight,
|
||||
getFontFamilyIdByName,
|
||||
getFontString,
|
||||
measureBaseline,
|
||||
} from "../element/textElement";
|
||||
import { normalizeLink } from "./url";
|
||||
|
@ -75,15 +74,6 @@ export type RestoredDataState = {
|
|||
files: BinaryFiles;
|
||||
};
|
||||
|
||||
const getFontFamilyByName = (fontFamilyName: string): FontFamilyValues => {
|
||||
if (Object.keys(FONT_FAMILY).includes(fontFamilyName)) {
|
||||
return FONT_FAMILY[
|
||||
fontFamilyName as keyof typeof FONT_FAMILY
|
||||
] as FontFamilyValues;
|
||||
}
|
||||
return DEFAULT_FONT_FAMILY;
|
||||
};
|
||||
|
||||
const repairBinding = (binding: PointBinding | null) => {
|
||||
if (!binding) {
|
||||
return null;
|
||||
|
@ -186,7 +176,7 @@ const restoreElement = (
|
|||
element as any
|
||||
).font.split(" ");
|
||||
fontSize = parseFloat(fontPx);
|
||||
fontFamily = getFontFamilyByName(_fontFamily);
|
||||
fontFamily = getFontFamilyIdByName(_fontFamily);
|
||||
}
|
||||
const text = element.text ?? "";
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ import {
|
|||
} from "../element/newElement";
|
||||
import {
|
||||
getDefaultLineHeight,
|
||||
getFontString,
|
||||
measureText,
|
||||
normalizeText,
|
||||
} from "../element/textElement";
|
||||
|
@ -33,12 +34,12 @@ import {
|
|||
ExcalidrawSelectionElement,
|
||||
ExcalidrawTextElement,
|
||||
FileId,
|
||||
FontFamilyValues,
|
||||
FontFamilyId,
|
||||
TextAlign,
|
||||
VerticalAlign,
|
||||
} from "../element/types";
|
||||
import { MarkOptional } from "../utility-types";
|
||||
import { assertNever, getFontString } from "../utils";
|
||||
import { assertNever } from "../utils";
|
||||
|
||||
export type ValidLinearElement = {
|
||||
type: "arrow" | "line";
|
||||
|
@ -47,7 +48,7 @@ export type ValidLinearElement = {
|
|||
label?: {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: FontFamilyValues;
|
||||
fontFamily?: FontFamilyId;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
|
@ -124,7 +125,7 @@ export type ValidContainer =
|
|||
label?: {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: FontFamilyValues;
|
||||
fontFamily?: FontFamilyId;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||
|
|
|
@ -2,9 +2,9 @@ import { register } from "../actions/register";
|
|||
import { FONT_FAMILY, VERTICAL_ALIGN } from "../constants";
|
||||
import { t } from "../i18n";
|
||||
import { ExcalidrawProps } from "../types";
|
||||
import { getFontString, setCursorForShape, updateActiveTool } from "../utils";
|
||||
import { setCursorForShape, updateActiveTool } from "../utils";
|
||||
import { newTextElement } from "./newElement";
|
||||
import { getContainerElement, wrapText } from "./textElement";
|
||||
import { getContainerElement, getFontString, wrapText } from "./textElement";
|
||||
import { isEmbeddableElement } from "./typeChecks";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
|
@ -218,7 +218,7 @@ export const createPlaceholderEmbeddableLabel = (
|
|||
Math.min(element.width / 2, element.width / text.length),
|
||||
element.width / 30,
|
||||
);
|
||||
const fontFamily = FONT_FAMILY.Helvetica;
|
||||
const fontFamily = FONT_FAMILY.NORMAL.fontFamilyId;
|
||||
|
||||
const fontString = getFontString({
|
||||
fontSize,
|
||||
|
|
|
@ -79,7 +79,7 @@ describe("duplicating single elements", () => {
|
|||
opacity: 100,
|
||||
text: "hello",
|
||||
fontSize: 20,
|
||||
fontFamily: FONT_FAMILY.Virgil,
|
||||
fontFamily: FONT_FAMILY.HAND_DRAWN.fontFamilyId,
|
||||
textAlign: "left",
|
||||
verticalAlign: "top",
|
||||
});
|
||||
|
|
|
@ -10,17 +10,12 @@ import {
|
|||
VerticalAlign,
|
||||
Arrowhead,
|
||||
ExcalidrawFreeDrawElement,
|
||||
FontFamilyValues,
|
||||
FontFamilyId,
|
||||
ExcalidrawTextContainer,
|
||||
ExcalidrawFrameElement,
|
||||
ExcalidrawEmbeddableElement,
|
||||
} from "../element/types";
|
||||
import {
|
||||
arrayToMap,
|
||||
getFontString,
|
||||
getUpdatedTimestamp,
|
||||
isTestEnv,
|
||||
} from "../utils";
|
||||
import { arrayToMap, getUpdatedTimestamp, isTestEnv } from "../utils";
|
||||
import { randomInteger, randomId } from "../random";
|
||||
import { bumpVersion, newElementWith } from "./mutateElement";
|
||||
import { getNewGroupIdsForDuplication } from "../groups";
|
||||
|
@ -35,6 +30,7 @@ import {
|
|||
wrapText,
|
||||
getBoundTextMaxWidth,
|
||||
getDefaultLineHeight,
|
||||
getFontString,
|
||||
} from "./textElement";
|
||||
import {
|
||||
DEFAULT_ELEMENT_PROPS,
|
||||
|
@ -184,7 +180,7 @@ export const newTextElement = (
|
|||
opts: {
|
||||
text: string;
|
||||
fontSize?: number;
|
||||
fontFamily?: FontFamilyValues;
|
||||
fontFamily?: FontFamilyId;
|
||||
textAlign?: TextAlign;
|
||||
verticalAlign?: VerticalAlign;
|
||||
containerId?: ExcalidrawTextContainer["id"] | null;
|
||||
|
|
|
@ -34,7 +34,6 @@ import {
|
|||
isTextElement,
|
||||
} from "./typeChecks";
|
||||
import { mutateElement } from "./mutateElement";
|
||||
import { getFontString } from "../utils";
|
||||
import { updateBoundElements } from "./binding";
|
||||
import {
|
||||
TransformHandleType,
|
||||
|
@ -53,6 +52,7 @@ import {
|
|||
getApproxMinLineHeight,
|
||||
measureText,
|
||||
getBoundTextMaxHeight,
|
||||
getFontString,
|
||||
} from "./textElement";
|
||||
import { LinearElementEditor } from "./linearElementEditor";
|
||||
|
||||
|
|
|
@ -427,6 +427,6 @@ describe("Test getDefaultLineHeight", () => {
|
|||
});
|
||||
|
||||
it("should return correct line height", () => {
|
||||
expect(getDefaultLineHeight(FONT_FAMILY.Cascadia)).toBe(1.2);
|
||||
expect(getDefaultLineHeight(FONT_FAMILY.CODE.fontFamilyId)).toBe(1.2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { getFontString, arrayToMap, isTestEnv } from "../utils";
|
||||
import { arrayToMap, isTestEnv } from "../utils";
|
||||
import {
|
||||
ExcalidrawElement,
|
||||
ExcalidrawTextContainer,
|
||||
ExcalidrawTextElement,
|
||||
ExcalidrawTextElementWithContainer,
|
||||
FontFamilyValues,
|
||||
FontFamilyId,
|
||||
FontString,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "./types";
|
||||
|
@ -19,6 +19,7 @@ import {
|
|||
isSafari,
|
||||
TEXT_ALIGN,
|
||||
VERTICAL_ALIGN,
|
||||
WINDOWS_EMOJI_FALLBACK_FONT,
|
||||
} from "../constants";
|
||||
import { MaybeTransformHandleType } from "./transformHandles";
|
||||
import Scene from "../scene/Scene";
|
||||
|
@ -967,17 +968,57 @@ export const isMeasureTextSupported = () => {
|
|||
const DEFAULT_LINE_HEIGHT = {
|
||||
// ~1.25 is the average for Virgil in WebKit and Blink.
|
||||
// Gecko (FF) uses ~1.28.
|
||||
[FONT_FAMILY.Virgil]: 1.25 as ExcalidrawTextElement["lineHeight"],
|
||||
[FONT_FAMILY.HAND_DRAWN.fontFamilyId]:
|
||||
1.25 as ExcalidrawTextElement["lineHeight"],
|
||||
// ~1.15 is the average for Virgil in WebKit and Blink.
|
||||
// Gecko if all over the place.
|
||||
[FONT_FAMILY.Helvetica]: 1.15 as ExcalidrawTextElement["lineHeight"],
|
||||
[FONT_FAMILY.NORMAL.fontFamilyId]:
|
||||
1.15 as ExcalidrawTextElement["lineHeight"],
|
||||
// ~1.2 is the average for Virgil in WebKit and Blink, and kinda Gecko too
|
||||
[FONT_FAMILY.Cascadia]: 1.2 as ExcalidrawTextElement["lineHeight"],
|
||||
[FONT_FAMILY.CODE.fontFamilyId]: 1.2 as ExcalidrawTextElement["lineHeight"],
|
||||
};
|
||||
|
||||
export const getDefaultLineHeight = (fontFamily: FontFamilyValues) => {
|
||||
if (fontFamily in DEFAULT_LINE_HEIGHT) {
|
||||
return DEFAULT_LINE_HEIGHT[fontFamily];
|
||||
export const getDefaultLineHeight = (fontId: number) => {
|
||||
if (fontId in DEFAULT_LINE_HEIGHT) {
|
||||
return (
|
||||
DEFAULT_LINE_HEIGHT as Record<number, ExcalidrawTextElement["lineHeight"]>
|
||||
)[fontId];
|
||||
}
|
||||
return DEFAULT_LINE_HEIGHT[DEFAULT_FONT_FAMILY];
|
||||
};
|
||||
|
||||
export const getFontFamilyIdByName = (fontFamilyName: string): FontFamilyId => {
|
||||
for (const key in FONT_FAMILY) {
|
||||
const font = FONT_FAMILY[key as keyof typeof FONT_FAMILY];
|
||||
if (font.fontFamily === fontFamilyName) {
|
||||
return font.fontFamilyId;
|
||||
}
|
||||
}
|
||||
return DEFAULT_FONT_FAMILY;
|
||||
};
|
||||
|
||||
export const getFontFamilyString = ({
|
||||
fontFamily,
|
||||
}: {
|
||||
fontFamily: FontFamilyId;
|
||||
}) => {
|
||||
for (const key in FONT_FAMILY) {
|
||||
const font = FONT_FAMILY[key as keyof typeof FONT_FAMILY];
|
||||
if (font.fontFamilyId === fontFamily) {
|
||||
return `${font.fontFamily}, ${WINDOWS_EMOJI_FALLBACK_FONT}`;
|
||||
}
|
||||
}
|
||||
|
||||
return WINDOWS_EMOJI_FALLBACK_FONT;
|
||||
};
|
||||
|
||||
/** returns fontSize+fontFamily string for assignment to DOM elements */
|
||||
export const getFontString = ({
|
||||
fontSize,
|
||||
fontFamily,
|
||||
}: {
|
||||
fontSize: number;
|
||||
fontFamily: FontFamilyId;
|
||||
}) => {
|
||||
return `${fontSize}px ${getFontFamilyString({ fontFamily })}` as FontString;
|
||||
};
|
||||
|
|
|
@ -798,7 +798,7 @@ describe("textWysiwyg", () => {
|
|||
await new Promise((r) => setTimeout(r, 0));
|
||||
updateTextEditor(editor, "Hello World!");
|
||||
editor.blur();
|
||||
expect(text.fontFamily).toEqual(FONT_FAMILY.Virgil);
|
||||
expect(text.fontFamily).toEqual(FONT_FAMILY.HAND_DRAWN.fontFamilyId);
|
||||
UI.clickTool("text");
|
||||
|
||||
mouse.clickAt(
|
||||
|
@ -815,7 +815,7 @@ describe("textWysiwyg", () => {
|
|||
editor.blur();
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Cascadia);
|
||||
).toEqual(FONT_FAMILY.CODE.fontFamilyId);
|
||||
|
||||
//undo
|
||||
Keyboard.withModifierKeys({ ctrl: true }, () => {
|
||||
|
@ -823,7 +823,7 @@ describe("textWysiwyg", () => {
|
|||
});
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Virgil);
|
||||
).toEqual(FONT_FAMILY.HAND_DRAWN.fontFamilyId);
|
||||
|
||||
//redo
|
||||
Keyboard.withModifierKeys({ ctrl: true, shift: true }, () => {
|
||||
|
@ -831,7 +831,7 @@ describe("textWysiwyg", () => {
|
|||
});
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Cascadia);
|
||||
).toEqual(FONT_FAMILY.CODE.fontFamilyId);
|
||||
});
|
||||
|
||||
it("should wrap text and vertcially center align once text submitted", async () => {
|
||||
|
@ -1220,7 +1220,7 @@ describe("textWysiwyg", () => {
|
|||
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Cascadia);
|
||||
).toEqual(FONT_FAMILY.CODE.fontFamilyId);
|
||||
expect(getOriginalContainerHeightFromCache(rectangle.id)).toBe(75);
|
||||
|
||||
fireEvent.click(screen.getByTitle(/Very large/i));
|
||||
|
@ -1247,7 +1247,7 @@ describe("textWysiwyg", () => {
|
|||
fireEvent.click(screen.getByTitle(/code/i));
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Cascadia);
|
||||
).toEqual(FONT_FAMILY.CODE.fontFamilyId);
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).lineHeight,
|
||||
).toEqual(1.2);
|
||||
|
@ -1255,7 +1255,7 @@ describe("textWysiwyg", () => {
|
|||
fireEvent.click(screen.getByTitle(/normal/i));
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).fontFamily,
|
||||
).toEqual(FONT_FAMILY.Helvetica);
|
||||
).toEqual(FONT_FAMILY.NORMAL.fontFamilyId);
|
||||
expect(
|
||||
(h.elements[1] as ExcalidrawTextElementWithContainer).lineHeight,
|
||||
).toEqual(1.15);
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
import { CODES, KEYS } from "../keys";
|
||||
import {
|
||||
isWritableElement,
|
||||
getFontString,
|
||||
getFontFamilyString,
|
||||
isTestEnv,
|
||||
} from "../utils";
|
||||
import { isWritableElement, isTestEnv } from "../utils";
|
||||
import Scene from "../scene/Scene";
|
||||
import {
|
||||
isArrowElement,
|
||||
|
@ -34,6 +29,8 @@ import {
|
|||
computeContainerDimensionForBoundText,
|
||||
detectLineHeight,
|
||||
computeBoundTextPosition,
|
||||
getFontString,
|
||||
getFontFamilyString,
|
||||
} from "./textElement";
|
||||
import {
|
||||
actionDecreaseFontSize,
|
||||
|
|
|
@ -10,8 +10,8 @@ import { MarkNonNullable, ValueOf } from "../utility-types";
|
|||
|
||||
export type ChartType = "bar" | "line";
|
||||
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
||||
export type FontFamilyKeys = keyof typeof FONT_FAMILY;
|
||||
export type FontFamilyValues = typeof FONT_FAMILY[FontFamilyKeys];
|
||||
export type FontFamilyId =
|
||||
typeof FONT_FAMILY[keyof typeof FONT_FAMILY]["fontFamilyId"];
|
||||
export type Theme = typeof THEME[keyof typeof THEME];
|
||||
export type FontString = string & { _brand: "fontString" };
|
||||
export type GroupId = string;
|
||||
|
@ -150,7 +150,7 @@ export type ExcalidrawTextElement = _ExcalidrawElementBase &
|
|||
Readonly<{
|
||||
type: "text";
|
||||
fontSize: number;
|
||||
fontFamily: FontFamilyValues;
|
||||
fontFamily: FontFamilyId;
|
||||
text: string;
|
||||
baseline: number;
|
||||
textAlign: TextAlign;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { ExcalidrawElementSkeleton } from "../../../data/transform";
|
||||
import { FileId } from "../../../element/types";
|
||||
import { FONT_FAMILY } from "../entry";
|
||||
|
||||
const elements: ExcalidrawElementSkeleton[] = [
|
||||
{
|
||||
|
@ -39,7 +40,10 @@ const elements: ExcalidrawElementSkeleton[] = [
|
|||
];
|
||||
export default {
|
||||
elements,
|
||||
appState: { viewBackgroundColor: "#AFEEEE", currentItemFontFamily: 1 },
|
||||
appState: {
|
||||
viewBackgroundColor: "#AFEEEE",
|
||||
currentItemFontFamily: FONT_FAMILY.HAND_DRAWN.fontFamilyId,
|
||||
},
|
||||
scrollToContent: true,
|
||||
libraryItems: [
|
||||
[
|
||||
|
|
|
@ -20,7 +20,7 @@ import type { Drawable } from "roughjs/bin/core";
|
|||
import type { RoughSVG } from "roughjs/bin/svg";
|
||||
|
||||
import { StaticCanvasRenderConfig } from "../scene/types";
|
||||
import { distance, getFontString, getFontFamilyString, isRTL } from "../utils";
|
||||
import { distance, isRTL } from "../utils";
|
||||
import { getCornerRadius, isPathALoop, isRightAngle } from "../math";
|
||||
import rough from "roughjs/bin/rough";
|
||||
import {
|
||||
|
@ -46,6 +46,8 @@ import {
|
|||
getLineHeightInPx,
|
||||
getBoundTextMaxHeight,
|
||||
getBoundTextMaxWidth,
|
||||
getFontFamilyString,
|
||||
getFontString,
|
||||
} from "../element/textElement";
|
||||
import { LinearElementEditor } from "../element/linearElementEditor";
|
||||
import {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { isTextElement, refreshTextDimensions } from "../element";
|
||||
import { newElementWith } from "../element/mutateElement";
|
||||
import { getFontString } from "../element/textElement";
|
||||
import { isBoundToContainer } from "../element/typeChecks";
|
||||
import { ExcalidrawElement, ExcalidrawTextElement } from "../element/types";
|
||||
import { getFontString } from "../utils";
|
||||
import type Scene from "./Scene";
|
||||
import { ShapeCache } from "./ShapeCache";
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ describe("restoreElements", () => {
|
|||
const textElement = API.createElement({
|
||||
type: "text",
|
||||
fontSize: 14,
|
||||
fontFamily: FONT_FAMILY.Virgil,
|
||||
fontFamily: FONT_FAMILY.HAND_DRAWN.fontFamilyId,
|
||||
text: "text",
|
||||
textAlign: "center",
|
||||
verticalAlign: "middle",
|
||||
|
|
|
@ -666,9 +666,13 @@ describe("regression tests", () => {
|
|||
|
||||
it("updates fontSize & fontFamily appState", () => {
|
||||
UI.clickTool("text");
|
||||
expect(h.state.currentItemFontFamily).toEqual(FONT_FAMILY.Virgil);
|
||||
expect(h.state.currentItemFontFamily).toEqual(
|
||||
FONT_FAMILY.HAND_DRAWN.fontFamilyId,
|
||||
);
|
||||
fireEvent.click(screen.getByTitle(/code/i));
|
||||
expect(h.state.currentItemFontFamily).toEqual(FONT_FAMILY.Cascadia);
|
||||
expect(h.state.currentItemFontFamily).toEqual(
|
||||
FONT_FAMILY.CODE.fontFamilyId,
|
||||
);
|
||||
});
|
||||
|
||||
it("deselects selected element, on pointer up, when click hits element bounding box but doesn't hit the element", () => {
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
ExcalidrawBindableElement,
|
||||
Arrowhead,
|
||||
ChartType,
|
||||
FontFamilyValues,
|
||||
FontFamilyId,
|
||||
FileId,
|
||||
ExcalidrawImageElement,
|
||||
Theme,
|
||||
|
@ -221,7 +221,7 @@ export type AppState = {
|
|||
currentItemStrokeStyle: ExcalidrawElement["strokeStyle"];
|
||||
currentItemRoughness: number;
|
||||
currentItemOpacity: number;
|
||||
currentItemFontFamily: FontFamilyValues;
|
||||
currentItemFontFamily: FontFamilyId;
|
||||
currentItemFontSize: number;
|
||||
currentItemTextAlign: TextAlign;
|
||||
currentItemStartArrowhead: Arrowhead | null;
|
||||
|
|
32
src/utils.ts
32
src/utils.ts
|
@ -4,17 +4,11 @@ import {
|
|||
CURSOR_TYPE,
|
||||
DEFAULT_VERSION,
|
||||
EVENT,
|
||||
FONT_FAMILY,
|
||||
isDarwin,
|
||||
MIME_TYPES,
|
||||
THEME,
|
||||
WINDOWS_EMOJI_FALLBACK_FONT,
|
||||
} from "./constants";
|
||||
import {
|
||||
FontFamilyValues,
|
||||
FontString,
|
||||
NonDeletedExcalidrawElement,
|
||||
} from "./element/types";
|
||||
import { NonDeletedExcalidrawElement } from "./element/types";
|
||||
import { AppState, DataURL, LastActiveTool, Zoom } from "./types";
|
||||
import { unstable_batchedUpdates } from "react-dom";
|
||||
import { SHAPES } from "./shapes";
|
||||
|
@ -85,30 +79,6 @@ export const isWritableElement = (
|
|||
(target instanceof HTMLInputElement &&
|
||||
(target.type === "text" || target.type === "number"));
|
||||
|
||||
export const getFontFamilyString = ({
|
||||
fontFamily,
|
||||
}: {
|
||||
fontFamily: FontFamilyValues;
|
||||
}) => {
|
||||
for (const [fontFamilyString, id] of Object.entries(FONT_FAMILY)) {
|
||||
if (id === fontFamily) {
|
||||
return `${fontFamilyString}, ${WINDOWS_EMOJI_FALLBACK_FONT}`;
|
||||
}
|
||||
}
|
||||
return WINDOWS_EMOJI_FALLBACK_FONT;
|
||||
};
|
||||
|
||||
/** returns fontSize+fontFamily string for assignment to DOM elements */
|
||||
export const getFontString = ({
|
||||
fontSize,
|
||||
fontFamily,
|
||||
}: {
|
||||
fontSize: number;
|
||||
fontFamily: FontFamilyValues;
|
||||
}) => {
|
||||
return `${fontSize}px ${getFontFamilyString({ fontFamily })}` as FontString;
|
||||
};
|
||||
|
||||
export const debounce = <T extends any[]>(
|
||||
fn: (...args: T) => void,
|
||||
timeout: number,
|
||||
|
|
Loading…
Reference in New Issue