mirror of
				https://github.com/excalidraw/excalidraw.git
				synced 2025-10-31 02:44:50 +01:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
			v0.16.2
			...
			dwelle/ref
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 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, | ||||
|   | ||||
		Reference in New Issue
	
	Block a user