diff options
| author | kj_sh604 | 2026-03-15 16:19:35 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-03-15 16:19:35 -0400 |
| commit | 6ec259a0e71174651bae95d4628138bf6fd68742 (patch) | |
| tree | 5e33c6a5ec091ecabfcb257fdc7b6a88ed8754ac /packages/excalidraw/components/Stats/FontSize.tsx | |
| parent | 16c8578b15c727f22921f8a80a56ee4d4e7f2272 (diff) | |
refactor: packages/
Diffstat (limited to 'packages/excalidraw/components/Stats/FontSize.tsx')
| -rw-r--r-- | packages/excalidraw/components/Stats/FontSize.tsx | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/packages/excalidraw/components/Stats/FontSize.tsx b/packages/excalidraw/components/Stats/FontSize.tsx new file mode 100644 index 0000000..13dc6db --- /dev/null +++ b/packages/excalidraw/components/Stats/FontSize.tsx @@ -0,0 +1,99 @@ +import type { + ExcalidrawElement, + ExcalidrawTextElement, +} from "../../element/types"; +import StatsDragInput from "./DragInput"; +import type { DragInputCallbackType } from "./DragInput"; +import { mutateElement } from "../../element/mutateElement"; +import { getStepSizedValue } from "./utils"; +import { fontSizeIcon } from "../icons"; +import type Scene from "../../scene/Scene"; +import type { AppState } from "../../types"; +import { isTextElement, redrawTextBoundingBox } from "../../element"; +import { hasBoundTextElement } from "../../element/typeChecks"; +import { getBoundTextElement } from "../../element/textElement"; + +interface FontSizeProps { + element: ExcalidrawElement; + scene: Scene; + appState: AppState; + property: "fontSize"; +} + +const MIN_FONT_SIZE = 4; +const STEP_SIZE = 4; + +const handleFontSizeChange: DragInputCallbackType< + FontSizeProps["property"], + ExcalidrawTextElement +> = ({ + accumulatedChange, + originalElements, + shouldChangeByStepSize, + nextValue, + scene, +}) => { + const elementsMap = scene.getNonDeletedElementsMap(); + + const origElement = originalElements[0]; + if (origElement) { + const latestElement = elementsMap.get(origElement.id); + if (!latestElement || !isTextElement(latestElement)) { + return; + } + + let nextFontSize; + + if (nextValue !== undefined) { + nextFontSize = Math.max(Math.round(nextValue), MIN_FONT_SIZE); + } else if (origElement.type === "text") { + const originalFontSize = Math.round(origElement.fontSize); + const changeInFontSize = Math.round(accumulatedChange); + nextFontSize = Math.max( + originalFontSize + changeInFontSize, + MIN_FONT_SIZE, + ); + if (shouldChangeByStepSize) { + nextFontSize = getStepSizedValue(nextFontSize, STEP_SIZE); + } + } + + if (nextFontSize) { + mutateElement(latestElement, { + fontSize: nextFontSize, + }); + redrawTextBoundingBox( + latestElement, + scene.getContainerElement(latestElement), + scene.getNonDeletedElementsMap(), + ); + } + } +}; + +const FontSize = ({ element, scene, appState, property }: FontSizeProps) => { + const _element = isTextElement(element) + ? element + : hasBoundTextElement(element) + ? getBoundTextElement(element, scene.getNonDeletedElementsMap()) + : null; + + if (!_element) { + return null; + } + + return ( + <StatsDragInput + label="F" + value={Math.round(_element.fontSize * 10) / 10} + elements={[_element]} + dragInputCallback={handleFontSizeChange} + icon={fontSizeIcon} + appState={appState} + scene={scene} + property={property} + /> + ); +}; + +export default FontSize; |
