changed ContainerBehavior into an object {textFlow: "growing"|"fixed", margin: number}

This commit is contained in:
zsviczian
2025-09-22 17:14:16 +00:00
parent f90bf59ecd
commit f3a60a5ef6
10 changed files with 62 additions and 26 deletions

View File

@@ -458,7 +458,10 @@ export const DEFAULT_ELEMENT_PROPS: {
roughness: ROUGHNESS.artist, roughness: ROUGHNESS.artist,
opacity: 100, opacity: 100,
locked: false, locked: false,
containerBehavior: "growing", containerBehavior: {
textFlow: "growing",
margin: BOUND_TEXT_PADDING,
},
}; };
export const LIBRARY_SIDEBAR_TAB = "library"; export const LIBRARY_SIDEBAR_TAB = "library";

View File

@@ -10,6 +10,7 @@ import {
getFontString, getFontString,
getUpdatedTimestamp, getUpdatedTimestamp,
getLineHeight, getLineHeight,
BOUND_TEXT_PADDING,
} from "@excalidraw/common"; } from "@excalidraw/common";
import type { Radians } from "@excalidraw/math"; import type { Radians } from "@excalidraw/math";
@@ -169,7 +170,10 @@ export const newElement = (
opts.type as ExcalidrawFlowchartNodeElement["type"], opts.type as ExcalidrawFlowchartNodeElement["type"],
opts, opts,
), ),
containerBehavior: opts.containerBehavior ?? "growing", containerBehavior: {
textFlow: opts.containerBehavior?.textFlow ?? "growing",
margin: opts.containerBehavior?.margin ?? BOUND_TEXT_PADDING,
},
} as NonDeleted<ExcalidrawFlowchartNodeElement>; } as NonDeleted<ExcalidrawFlowchartNodeElement>;
} }
return _newElementBase<ExcalidrawGenericElement>( return _newElementBase<ExcalidrawGenericElement>(

View File

@@ -27,7 +27,10 @@ export type StrokeRoundness = "round" | "sharp";
export type RoundnessType = ValueOf<typeof ROUNDNESS>; export type RoundnessType = ValueOf<typeof ROUNDNESS>;
export type StrokeStyle = "solid" | "dashed" | "dotted"; export type StrokeStyle = "solid" | "dashed" | "dotted";
export type TextAlign = typeof TEXT_ALIGN[keyof typeof TEXT_ALIGN]; export type TextAlign = typeof TEXT_ALIGN[keyof typeof TEXT_ALIGN];
export type ContainerBehavior = "growing" | "stickyNote"; export type ContainerBehavior = {
textFlow: "growing" | "fixed";
margin?: number;
};
type VerticalAlignKeys = keyof typeof VERTICAL_ALIGN; type VerticalAlignKeys = keyof typeof VERTICAL_ALIGN;
export type VerticalAlign = typeof VERTICAL_ALIGN[VerticalAlignKeys]; export type VerticalAlign = typeof VERTICAL_ALIGN[VerticalAlignKeys];
@@ -88,7 +91,7 @@ export type ExcalidrawSelectionElement = _ExcalidrawElementBase & {
}; };
type _ExcalidrawStickyNoteContainer = _ExcalidrawElementBase & { type _ExcalidrawStickyNoteContainer = _ExcalidrawElementBase & {
containerBehavior: "stickyNote"; containerBehavior: ContainerBehavior;
}; };
export type ExcalidrawRectangleElement = _ExcalidrawStickyNoteContainer & { export type ExcalidrawRectangleElement = _ExcalidrawStickyNoteContainer & {

View File

@@ -21,6 +21,7 @@ import {
getLineHeight, getLineHeight,
isTransparent, isTransparent,
reduceToCommonValue, reduceToCommonValue,
BOUND_TEXT_PADDING,
} from "@excalidraw/common"; } from "@excalidraw/common";
import { import {
@@ -1559,14 +1560,24 @@ export const actionChangeContainerBehavior = register({
const nextElements = elements.map((el) => const nextElements = elements.map((el) =>
containerIdsToUpdate.has(el.id) containerIdsToUpdate.has(el.id)
? newElementWith(el, { ? newElementWith(el, {
containerBehavior: value, containerBehavior: {
textFlow: value,
margin: el.containerBehavior?.margin ?? BOUND_TEXT_PADDING,
},
}) })
: el, : el,
); );
return { return {
elements: nextElements, elements: nextElements,
appState: { ...appState, currentItemContainerBehavior: value }, appState: {
...appState,
currentItemContainerBehavior: {
textFlow: value,
margin:
appState.currentItemContainerBehavior?.margin ?? BOUND_TEXT_PADDING,
},
},
captureUpdate: CaptureUpdateAction.IMMEDIATELY, captureUpdate: CaptureUpdateAction.IMMEDIATELY,
}; };
}, },
@@ -1611,7 +1622,7 @@ export const actionChangeContainerBehavior = register({
const value = const value =
reduceToCommonValue( reduceToCommonValue(
targetContainers, targetContainers,
(el) => el.containerBehavior ?? "growing", (el) => el.containerBehavior?.textFlow ?? "growing",
) ?? ) ??
// mixed selection -> show null so nothing appears selected // mixed selection -> show null so nothing appears selected
null; null;
@@ -1631,8 +1642,8 @@ export const actionChangeContainerBehavior = register({
icon: growingContainerIcon, icon: growingContainerIcon,
}, },
{ {
value: "stickyNote", value: "fixed",
text: t("labels.container_sticky"), text: t("labels.container_fixed"),
icon: stickyNoteIcon, icon: stickyNoteIcon,
}, },
]} ]}
@@ -1640,7 +1651,7 @@ export const actionChangeContainerBehavior = register({
value ?? value ??
(targetContainers.length (targetContainers.length
? null ? null
: appState.currentItemContainerBehavior ?? "growing") : appState.currentItemContainerBehavior?.textFlow ?? "growing")
} }
onChange={(val) => updateData(val)} onChange={(val) => updateData(val)}
/> />

View File

@@ -9,6 +9,7 @@ import {
VERTICAL_ALIGN, VERTICAL_ALIGN,
randomId, randomId,
isDevEnv, isDevEnv,
BOUND_TEXT_PADDING,
} from "@excalidraw/common"; } from "@excalidraw/common";
import { import {
@@ -334,7 +335,10 @@ const chartBaseElements = (
strokeColor: COLOR_PALETTE.black, strokeColor: COLOR_PALETTE.black,
fillStyle: "solid", fillStyle: "solid",
opacity: 6, opacity: 6,
containerBehavior: "growing", containerBehavior: {
textFlow: "growing",
margin: BOUND_TEXT_PADDING,
},
}) })
: null; : null;
@@ -367,7 +371,10 @@ const chartTypeBar = (
y: y - barHeight - BAR_GAP, y: y - barHeight - BAR_GAP,
width: BAR_WIDTH, width: BAR_WIDTH,
height: barHeight, height: barHeight,
containerBehavior: "growing", containerBehavior: {
textFlow: "growing",
margin: BOUND_TEXT_PADDING,
},
}); });
}); });
@@ -434,7 +441,10 @@ const chartTypeLine = (
y: y + cy - BAR_GAP * 2, y: y + cy - BAR_GAP * 2,
width: BAR_GAP, width: BAR_GAP,
height: BAR_GAP, height: BAR_GAP,
containerBehavior: "growing", containerBehavior: {
textFlow: "growing",
margin: BOUND_TEXT_PADDING,
},
}); });
}); });

View File

@@ -17,6 +17,7 @@ import {
getSizeFromPoints, getSizeFromPoints,
normalizeLink, normalizeLink,
getLineHeight, getLineHeight,
BOUND_TEXT_PADDING,
} from "@excalidraw/common"; } from "@excalidraw/common";
import { import {
getNonDeletedElements, getNonDeletedElements,
@@ -238,9 +239,10 @@ const restoreElementWithProperties = <
locked: element.locked ?? false, locked: element.locked ?? false,
...(isFlowchartType(nextType) ...(isFlowchartType(nextType)
? { ? {
containerBehavior: containerBehavior: {
element.containerBehavior ?? textFlow: element.containerBehavior?.textFlow ?? "growing",
DEFAULT_ELEMENT_PROPS.containerBehavior, margin: element.containerBehavior?.margin ?? BOUND_TEXT_PADDING,
},
} }
: {}), : {}),
}; };

View File

@@ -32,7 +32,7 @@
"strokeStyle_dotted": "Dotted", "strokeStyle_dotted": "Dotted",
"sloppiness": "Sloppiness", "sloppiness": "Sloppiness",
"container": "Container", "container": "Container",
"container_sticky": "Sticky note", "container_fixed": "Sticky note",
"container_growing": "Fit to text", "container_growing": "Fit to text",
"opacity": "Opacity", "opacity": "Opacity",
"textAlign": "Text align", "textAlign": "Text align",

View File

@@ -1,4 +1,4 @@
import { DEFAULT_FONT_FAMILY } from "@excalidraw/common"; import { BOUND_TEXT_PADDING, DEFAULT_FONT_FAMILY } from "@excalidraw/common";
import type { Radians } from "@excalidraw/math"; import type { Radians } from "@excalidraw/math";
@@ -34,7 +34,7 @@ const elementBase: Omit<ExcalidrawElement, "type"> = {
export const rectangleFixture: ExcalidrawElement = { export const rectangleFixture: ExcalidrawElement = {
...elementBase, ...elementBase,
containerBehavior: "growing", containerBehavior: { textFlow: "growing", margin: BOUND_TEXT_PADDING },
type: "rectangle", type: "rectangle",
} as unknown as ExcalidrawElement; } as unknown as ExcalidrawElement;
export const embeddableFixture: ExcalidrawElement = { export const embeddableFixture: ExcalidrawElement = {
@@ -43,17 +43,17 @@ export const embeddableFixture: ExcalidrawElement = {
}; };
export const ellipseFixture: ExcalidrawElement = { export const ellipseFixture: ExcalidrawElement = {
...elementBase, ...elementBase,
containerBehavior: "growing", containerBehavior: { textFlow: "growing", margin: BOUND_TEXT_PADDING },
type: "ellipse", type: "ellipse",
} as unknown as ExcalidrawElement; } as unknown as ExcalidrawElement;
export const diamondFixture: ExcalidrawElement = { export const diamondFixture: ExcalidrawElement = {
...elementBase, ...elementBase,
containerBehavior: "growing", containerBehavior: { textFlow: "growing", margin: BOUND_TEXT_PADDING },
type: "diamond", type: "diamond",
} as unknown as ExcalidrawElement; } as unknown as ExcalidrawElement;
export const rectangleWithLinkFixture: ExcalidrawElement = { export const rectangleWithLinkFixture: ExcalidrawElement = {
...elementBase, ...elementBase,
containerBehavior: "growing", containerBehavior: { textFlow: "growing", margin: BOUND_TEXT_PADDING },
type: "rectangle", type: "rectangle",
link: "excalidraw.com", link: "excalidraw.com",
} as unknown as ExcalidrawElement; } as unknown as ExcalidrawElement;

View File

@@ -4,7 +4,7 @@ import util from "util";
import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math"; import { pointFrom, type LocalPoint, type Radians } from "@excalidraw/math";
import { DEFAULT_VERTICAL_ALIGN, ROUNDNESS, assertNever } from "@excalidraw/common"; import { BOUND_TEXT_PADDING, DEFAULT_VERTICAL_ALIGN, ROUNDNESS, assertNever } from "@excalidraw/common";
import { import {
newArrowElement, newArrowElement,
@@ -286,7 +286,10 @@ export class API {
element = newElement({ element = newElement({
type: type as "rectangle" | "diamond" | "ellipse", type: type as "rectangle" | "diamond" | "ellipse",
...base, ...base,
containerBehavior: rest.containerBehavior ?? "growing", containerBehavior: {
textFlow: rest.containerBehavior?.textFlow ?? "growing",
margin: rest.containerBehavior?.margin ?? BOUND_TEXT_PADDING,
},
}); });
break; break;
case "embeddable": case "embeddable":

View File

@@ -160,7 +160,7 @@ export const textWysiwyg = ({
let maxHeight = updatedTextElement.height; let maxHeight = updatedTextElement.height;
if (container && updatedTextElement.containerId) { if (container && updatedTextElement.containerId) {
if ((container as any).containerBehavior === "stickyNote") { if ((container as any).containerBehavior?.textFlow === "fixed") {
if (stickyNoteInitialFontSize == null) { if (stickyNoteInitialFontSize == null) {
stickyNoteInitialFontSize = updatedTextElement.fontSize; stickyNoteInitialFontSize = updatedTextElement.fontSize;
} }
@@ -244,7 +244,7 @@ export const textWysiwyg = ({
); );
// autogrow / autoshrink only for non-sticky behaviors // autogrow / autoshrink only for non-sticky behaviors
if ((container as any).containerBehavior !== "stickyNote") { if ((container as any).containerBehavior?.textFlow !== "fixed") {
// autogrow container height if text exceeds // autogrow container height if text exceeds
if (!isArrowElement(container) && height > maxHeight) { if (!isArrowElement(container) && height > maxHeight) {
const targetContainerHeight = const targetContainerHeight =