schema: remove frame bg guard flag from runtime
This commit is contained in:
@@ -10,7 +10,6 @@ import {
|
|||||||
getFontString,
|
getFontString,
|
||||||
getUpdatedTimestamp,
|
getUpdatedTimestamp,
|
||||||
getLineHeight,
|
getLineHeight,
|
||||||
isTransparent,
|
|
||||||
} from "@excalidraw/common";
|
} from "@excalidraw/common";
|
||||||
|
|
||||||
import type { Radians } from "@excalidraw/math";
|
import type { Radians } from "@excalidraw/math";
|
||||||
@@ -186,13 +185,11 @@ export const newFrameElement = (
|
|||||||
name?: string;
|
name?: string;
|
||||||
} & ElementConstructorOpts,
|
} & ElementConstructorOpts,
|
||||||
): NonDeleted<ExcalidrawFrameElement> => {
|
): NonDeleted<ExcalidrawFrameElement> => {
|
||||||
const frameBase = _newElementBase<ExcalidrawFrameElement>("frame", opts);
|
|
||||||
const frameElement = newElementWith(
|
const frameElement = newElementWith(
|
||||||
{
|
{
|
||||||
...frameBase,
|
..._newElementBase<ExcalidrawFrameElement>("frame", opts),
|
||||||
type: "frame",
|
type: "frame",
|
||||||
name: opts?.name || null,
|
name: opts?.name || null,
|
||||||
backgroundEnabled: !isTransparent(frameBase.backgroundColor),
|
|
||||||
},
|
},
|
||||||
{},
|
{},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -787,7 +787,7 @@ export const renderFrameBackground = (
|
|||||||
roundCorners?: boolean;
|
roundCorners?: boolean;
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
if (!frame.backgroundEnabled || isTransparent(frame.backgroundColor)) {
|
if (isTransparent(frame.backgroundColor)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,6 @@ export type InitializedExcalidrawImageElement = MarkNonNullable<
|
|||||||
export type ExcalidrawFrameElement = _ExcalidrawElementBase & {
|
export type ExcalidrawFrameElement = _ExcalidrawElementBase & {
|
||||||
type: "frame";
|
type: "frame";
|
||||||
name: string | null;
|
name: string | null;
|
||||||
backgroundEnabled: boolean;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ExcalidrawMagicFrameElement = _ExcalidrawElementBase & {
|
export type ExcalidrawMagicFrameElement = _ExcalidrawElementBase & {
|
||||||
|
|||||||
@@ -420,7 +420,6 @@ export const actionChangeBackgroundColor = register<
|
|||||||
if (isFrameElement(el)) {
|
if (isFrameElement(el)) {
|
||||||
return newElementWith(el, {
|
return newElementWith(el, {
|
||||||
backgroundColor: value.currentItemBackgroundColor,
|
backgroundColor: value.currentItemBackgroundColor,
|
||||||
backgroundEnabled: !isTransparent(value.currentItemBackgroundColor),
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return hasBackground(el.type)
|
return hasBackground(el.type)
|
||||||
|
|||||||
@@ -509,16 +509,8 @@ export const restoreElement = (
|
|||||||
name: element.name ?? null,
|
name: element.name ?? null,
|
||||||
});
|
});
|
||||||
case "frame":
|
case "frame":
|
||||||
const backgroundEnabled =
|
|
||||||
typeof (element as any).backgroundEnabled === "boolean"
|
|
||||||
? (element as any).backgroundEnabled
|
|
||||||
: false;
|
|
||||||
return restoreElementWithProperties(element, {
|
return restoreElementWithProperties(element, {
|
||||||
name: element.name ?? null,
|
name: element.name ?? null,
|
||||||
backgroundEnabled,
|
|
||||||
...(!backgroundEnabled
|
|
||||||
? { backgroundColor: DEFAULT_ELEMENT_PROPS.backgroundColor }
|
|
||||||
: {}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Don't use default case so as to catch a missing an element type case.
|
// Don't use default case so as to catch a missing an element type case.
|
||||||
|
|||||||
@@ -13,12 +13,14 @@ describe("schema migration", () => {
|
|||||||
type: "frame",
|
type: "frame",
|
||||||
backgroundColor: "#ffc9c9",
|
backgroundColor: "#ffc9c9",
|
||||||
});
|
});
|
||||||
frame.backgroundEnabled = true;
|
(frame as any).backgroundEnabled = true;
|
||||||
|
|
||||||
const migrated = migrateElementsBySchema([frame], SCHEMA_VERSIONS.initial)!;
|
const migrated = migrateElementsBySchema([frame], SCHEMA_VERSIONS.initial)!;
|
||||||
|
|
||||||
expect(migrated[0].backgroundColor).toBe(DEFAULT_ELEMENT_PROPS.backgroundColor);
|
expect(migrated[0].backgroundColor).toBe(
|
||||||
expect((migrated[0] as any).backgroundEnabled).toBe(false);
|
DEFAULT_ELEMENT_PROPS.backgroundColor,
|
||||||
|
);
|
||||||
|
expect((migrated[0] as any).backgroundEnabled).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should keep latest-schema frame backgrounds unchanged", () => {
|
it("should keep latest-schema frame backgrounds unchanged", () => {
|
||||||
@@ -26,7 +28,7 @@ describe("schema migration", () => {
|
|||||||
type: "frame",
|
type: "frame",
|
||||||
backgroundColor: "#ffc9c9",
|
backgroundColor: "#ffc9c9",
|
||||||
});
|
});
|
||||||
frame.backgroundEnabled = true;
|
(frame as any).backgroundEnabled = true;
|
||||||
|
|
||||||
const migrated = migrateElementsBySchema(
|
const migrated = migrateElementsBySchema(
|
||||||
[frame],
|
[frame],
|
||||||
@@ -34,7 +36,7 @@ describe("schema migration", () => {
|
|||||||
)!;
|
)!;
|
||||||
|
|
||||||
expect(migrated[0].backgroundColor).toBe("#ffc9c9");
|
expect(migrated[0].backgroundColor).toBe("#ffc9c9");
|
||||||
expect((migrated[0] as any).backgroundEnabled).toBe(true);
|
expect((migrated[0] as any).backgroundEnabled).toBeUndefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should resolve invalid schema versions using fallback", () => {
|
it("should resolve invalid schema versions using fallback", () => {
|
||||||
@@ -47,4 +49,3 @@ describe("schema migration", () => {
|
|||||||
expect(resolveSchemaVersion(2, SCHEMA_VERSIONS.initial)).toBe(2);
|
expect(resolveSchemaVersion(2, SCHEMA_VERSIONS.initial)).toBe(2);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const migrateElementsBySchema = (
|
|||||||
elements: readonly ExcalidrawElement[] | null | undefined,
|
elements: readonly ExcalidrawElement[] | null | undefined,
|
||||||
schemaVersion: number,
|
schemaVersion: number,
|
||||||
) => {
|
) => {
|
||||||
if (!elements || schemaVersion >= SCHEMA_VERSIONS.frameBackgrounds) {
|
if (!elements) {
|
||||||
return elements;
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,10 +34,18 @@ export const migrateElementsBySchema = (
|
|||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { backgroundEnabled: _, ...frameWithoutBackgroundEnabled } =
|
||||||
|
element as ExcalidrawElement & {
|
||||||
|
backgroundEnabled?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (schemaVersion >= SCHEMA_VERSIONS.frameBackgrounds) {
|
||||||
|
return frameWithoutBackgroundEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...element,
|
...frameWithoutBackgroundEnabled,
|
||||||
backgroundColor: DEFAULT_ELEMENT_PROPS.backgroundColor,
|
backgroundColor: DEFAULT_ELEMENT_PROPS.backgroundColor,
|
||||||
backgroundEnabled: false,
|
|
||||||
} as ExcalidrawElement;
|
} as ExcalidrawElement;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -336,9 +336,6 @@ const _renderStaticScene = ({
|
|||||||
if (!isFrameElement(frame) || renderedFrameBackgrounds.has(frame.id)) {
|
if (!isFrameElement(frame) || renderedFrameBackgrounds.has(frame.id)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!frame.backgroundEnabled) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
frameBackgroundByElementId.set(element.id, frame);
|
frameBackgroundByElementId.set(element.id, frame);
|
||||||
renderedFrameBackgrounds.add(frame.id);
|
renderedFrameBackgrounds.add(frame.id);
|
||||||
|
|||||||
@@ -731,7 +731,6 @@ export const renderSceneToSvg = (
|
|||||||
const renderFrameBackgroundNode = (frame: ExcalidrawFrameElement) => {
|
const renderFrameBackgroundNode = (frame: ExcalidrawFrameElement) => {
|
||||||
if (
|
if (
|
||||||
!frame ||
|
!frame ||
|
||||||
!frame.backgroundEnabled ||
|
|
||||||
!frame.backgroundColor ||
|
!frame.backgroundColor ||
|
||||||
isTransparent(frame.backgroundColor)
|
isTransparent(frame.backgroundColor)
|
||||||
) {
|
) {
|
||||||
@@ -794,7 +793,6 @@ export const renderSceneToSvg = (
|
|||||||
if (
|
if (
|
||||||
!isFrameElement(frame) ||
|
!isFrameElement(frame) ||
|
||||||
renderedFrameBackgrounds.has(frame.id) ||
|
renderedFrameBackgrounds.has(frame.id) ||
|
||||||
!frame.backgroundEnabled ||
|
|
||||||
!frame.backgroundColor ||
|
!frame.backgroundColor ||
|
||||||
isTransparent(frame.backgroundColor)
|
isTransparent(frame.backgroundColor)
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import type { LocalPoint } from "@excalidraw/math";
|
|||||||
import type {
|
import type {
|
||||||
ExcalidrawArrowElement,
|
ExcalidrawArrowElement,
|
||||||
ExcalidrawElement,
|
ExcalidrawElement,
|
||||||
ExcalidrawFrameElement,
|
|
||||||
ExcalidrawFreeDrawElement,
|
ExcalidrawFreeDrawElement,
|
||||||
ExcalidrawLinearElement,
|
ExcalidrawLinearElement,
|
||||||
ExcalidrawTextElement,
|
ExcalidrawTextElement,
|
||||||
@@ -82,72 +81,19 @@ describe("restoreElements", () => {
|
|||||||
).toEqual([expect.objectContaining({ isDeleted: true })]);
|
).toEqual([expect.objectContaining({ isDeleted: true })]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should disable frame background for legacy frames missing backgroundEnabled", () => {
|
it("should restore frame element", () => {
|
||||||
const frame = API.createElement({
|
const frame = API.createElement({
|
||||||
type: "frame",
|
type: "frame",
|
||||||
backgroundColor: "#ffc9c9",
|
backgroundColor: "#ffc9c9",
|
||||||
});
|
});
|
||||||
const legacyFrame = { ...frame } as any;
|
|
||||||
delete legacyFrame.backgroundEnabled;
|
|
||||||
|
|
||||||
const restoredFrame = restore.restoreElements(
|
|
||||||
[legacyFrame],
|
|
||||||
null,
|
|
||||||
)[0] as ExcalidrawFrameElement;
|
|
||||||
|
|
||||||
expect(restoredFrame.backgroundColor).toBe("transparent");
|
|
||||||
expect(restoredFrame.backgroundEnabled).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should disable frame background when legacy backgroundEnabled is non-boolean", () => {
|
|
||||||
const frame = API.createElement({
|
|
||||||
type: "frame",
|
|
||||||
backgroundColor: "#ffc9c9",
|
|
||||||
});
|
|
||||||
const legacyFrame = {
|
|
||||||
...frame,
|
|
||||||
backgroundEnabled: undefined,
|
|
||||||
} as any;
|
|
||||||
|
|
||||||
const restoredFrame = restore.restoreElements(
|
|
||||||
[legacyFrame],
|
|
||||||
null,
|
|
||||||
)[0] as ExcalidrawFrameElement;
|
|
||||||
|
|
||||||
expect(restoredFrame.backgroundColor).toBe("transparent");
|
|
||||||
expect(restoredFrame.backgroundEnabled).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should normalize frame background color when backgroundEnabled is false", () => {
|
|
||||||
const frame = API.createElement({
|
|
||||||
type: "frame",
|
|
||||||
backgroundColor: "#ffc9c9",
|
|
||||||
});
|
|
||||||
frame.backgroundEnabled = false;
|
|
||||||
|
|
||||||
const restoredFrame = restore.restoreElements(
|
const restoredFrame = restore.restoreElements(
|
||||||
[frame],
|
[frame],
|
||||||
null,
|
null,
|
||||||
)[0] as ExcalidrawFrameElement;
|
)[0] as ExcalidrawElement;
|
||||||
|
|
||||||
expect(restoredFrame.backgroundColor).toBe("transparent");
|
|
||||||
expect(restoredFrame.backgroundEnabled).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should preserve frame backgroundEnabled when present", () => {
|
|
||||||
const frame = API.createElement({
|
|
||||||
type: "frame",
|
|
||||||
backgroundColor: "#ffc9c9",
|
|
||||||
});
|
|
||||||
frame.backgroundEnabled = true;
|
|
||||||
|
|
||||||
const restoredFrame = restore.restoreElements(
|
|
||||||
[frame],
|
|
||||||
null,
|
|
||||||
)[0] as ExcalidrawFrameElement;
|
|
||||||
|
|
||||||
|
expect(restoredFrame.type).toBe("frame");
|
||||||
expect(restoredFrame.backgroundColor).toBe("#ffc9c9");
|
expect(restoredFrame.backgroundColor).toBe("#ffc9c9");
|
||||||
expect(restoredFrame.backgroundEnabled).toBe(true);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should restore text element correctly passing value for each attribute", () => {
|
it("should restore text element correctly passing value for each attribute", () => {
|
||||||
|
|||||||
@@ -364,27 +364,6 @@ describe("exporting frames", () => {
|
|||||||
expect(emptyBgSvg.querySelector('rect[fill=""]')).toBeNull();
|
expect(emptyBgSvg.querySelector('rect[fill=""]')).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should not render SVG frame background when background is disabled", async () => {
|
|
||||||
const frame = API.createElement({
|
|
||||||
type: "frame",
|
|
||||||
width: 100,
|
|
||||||
height: 100,
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
backgroundColor: "#ffc9c9",
|
|
||||||
});
|
|
||||||
frame.backgroundEnabled = false;
|
|
||||||
|
|
||||||
const svg = await exportToSvg({
|
|
||||||
elements: [frame],
|
|
||||||
files: null,
|
|
||||||
exportPadding: 0,
|
|
||||||
exportingFrame: frame,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(svg.querySelector('rect[fill="#ffc9c9"]')).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("should filter non-overlapping elements when exporting a frame", async () => {
|
it("should filter non-overlapping elements when exporting a frame", async () => {
|
||||||
const frame = API.createElement({
|
const frame = API.createElement({
|
||||||
type: "frame",
|
type: "frame",
|
||||||
|
|||||||
Reference in New Issue
Block a user