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