234 lines
6.3 KiB
TypeScript
234 lines
6.3 KiB
TypeScript
import { editorChartToRawChart } from "@/components/slide-editor/model/chart-model";
|
|
import {
|
|
asRecord,
|
|
isRecord,
|
|
normalizeId,
|
|
readArray,
|
|
readNumber,
|
|
readPoint,
|
|
readString,
|
|
stripUndefined,
|
|
type Box,
|
|
type RawComponent,
|
|
type RawElement,
|
|
type RawUi,
|
|
type Size,
|
|
type UnknownRecord,
|
|
} from "@/components/slide-editor/model/core";
|
|
import { rawFontToSource } from "@/components/slide-editor/text/template-v2-text";
|
|
|
|
export function appendInsertedContent(
|
|
sourceUi: RawUi,
|
|
elements: UnknownRecord[],
|
|
insertedComponents: UnknownRecord[],
|
|
label?: string,
|
|
) {
|
|
const components = [...readArray(sourceUi.components)];
|
|
const start = components.length;
|
|
elements.forEach((element, offset) => {
|
|
components.push(insertedElementToComponent(element, label, start + offset));
|
|
});
|
|
insertedComponents.forEach((component, offset) => {
|
|
components.push(
|
|
insertedComponentToRaw(
|
|
component,
|
|
label,
|
|
start + elements.length + offset,
|
|
),
|
|
);
|
|
});
|
|
return { ...sourceUi, components };
|
|
}
|
|
|
|
export function insertedComponentToRaw(
|
|
component: UnknownRecord,
|
|
label: string | undefined,
|
|
index: number,
|
|
): RawComponent {
|
|
const box = sourceElementBox(component);
|
|
const elements = readArray(component.elements)
|
|
.filter(isRecord)
|
|
.map((element) => rawElementFromInsertedElement(element));
|
|
return {
|
|
...component,
|
|
id: `${normalizeId(
|
|
readString(component.id) ?? label ?? "inserted-component",
|
|
)}_${index + 1}`,
|
|
description:
|
|
readString(component.description) ?? label ?? "Inserted component",
|
|
position: { x: box.x, y: box.y },
|
|
size: { width: box.width, height: box.height },
|
|
elements,
|
|
};
|
|
}
|
|
|
|
export function insertedElementToComponent(
|
|
element: UnknownRecord,
|
|
label: string | undefined,
|
|
index: number,
|
|
) {
|
|
const box = sourceElementBox(element);
|
|
return {
|
|
id: `${normalizeId(label ?? readString(element.type) ?? "inserted")}_${index + 1}`,
|
|
description: label ?? "Inserted element",
|
|
position: { x: box.x, y: box.y },
|
|
size: { width: box.width, height: box.height },
|
|
elements: [
|
|
{
|
|
...rawElementFromInsertedElement(element),
|
|
position: { x: 0, y: 0 },
|
|
size: { width: box.width, height: box.height },
|
|
},
|
|
],
|
|
};
|
|
}
|
|
|
|
export function rawElementFromInsertedElement(
|
|
element: UnknownRecord,
|
|
): RawElement {
|
|
const type = readString(element.type) ?? "rectangle";
|
|
const rawElement = normalizeInsertedElementGeometry(element);
|
|
const normalizedElement = {
|
|
...rawElement,
|
|
font: rawFontToSource(rawElement.font),
|
|
border_radius: normalizeInsertedBorderRadius(
|
|
rawElement.border_radius ?? rawElement.borderRadius,
|
|
),
|
|
line_height: rawElement.line_height ?? rawElement.lineHeight,
|
|
};
|
|
const textNormalizedElement = normalizeInsertedTextCollections(
|
|
normalizedElement,
|
|
hasTemplateV2Metadata(element),
|
|
);
|
|
|
|
if (type === "chart") {
|
|
return editorChartToRawChart(textNormalizedElement, textNormalizedElement);
|
|
}
|
|
|
|
return textNormalizedElement;
|
|
}
|
|
|
|
export function sourceElementBox(element: UnknownRecord): Box {
|
|
const position = readPoint(element.position);
|
|
const size = sourceElementSize(element);
|
|
return {
|
|
x: position.x,
|
|
y: position.y,
|
|
width: Math.max(1, size.width),
|
|
height: Math.max(1, size.height),
|
|
};
|
|
}
|
|
|
|
export function sourceElementSize(element: UnknownRecord): Size {
|
|
const size = asRecord(element.size);
|
|
return {
|
|
width: Math.max(1, readNumber(size?.width) ?? 1),
|
|
height: Math.max(1, readNumber(size?.height) ?? 1),
|
|
};
|
|
}
|
|
|
|
export function normalizeInsertedElementGeometry(
|
|
element: UnknownRecord,
|
|
): RawElement {
|
|
return convertInsertedChildArrays(element);
|
|
}
|
|
|
|
export function convertInsertedChildArrays(element: UnknownRecord): RawElement {
|
|
const next: RawElement = { ...element };
|
|
|
|
if (Array.isArray(element.children)) {
|
|
next.children = element.children.map((child) =>
|
|
isRecord(child) ? rawElementFromInsertedElement(child) : child,
|
|
);
|
|
}
|
|
if (Array.isArray(element.elements)) {
|
|
next.elements = element.elements.map((child) =>
|
|
isRecord(child) ? rawElementFromInsertedElement(child) : child,
|
|
);
|
|
}
|
|
if (isRecord(element.child)) {
|
|
next.child = rawElementFromInsertedElement(element.child);
|
|
}
|
|
|
|
return next;
|
|
}
|
|
|
|
export function normalizeInsertedBorderRadius(value: unknown) {
|
|
const radius = asRecord(value);
|
|
if (!radius) return value;
|
|
return stripUndefined({
|
|
...radius,
|
|
radius: radius.radius,
|
|
tl: radius.tl,
|
|
tr: radius.tr,
|
|
bl: radius.bl,
|
|
br: radius.br,
|
|
topLeft: radius.topLeft,
|
|
topRight: radius.topRight,
|
|
bottomLeft: radius.bottomLeft,
|
|
bottomRight: radius.bottomRight,
|
|
});
|
|
}
|
|
|
|
export function hasTemplateV2Metadata(element: UnknownRecord) {
|
|
return Boolean(
|
|
element.component_id ||
|
|
element.component_instance_id ||
|
|
element.component_slot ||
|
|
element.component_description ||
|
|
(Array.isArray(element.design_variables) &&
|
|
element.design_variables.length > 0),
|
|
);
|
|
}
|
|
|
|
export function normalizeInsertedTextCollections(
|
|
element: RawElement,
|
|
normalizeTemplateText: boolean,
|
|
): RawElement {
|
|
if (!normalizeTemplateText) return element;
|
|
return stripUndefined({
|
|
...element,
|
|
runs: normalizeInsertedTextRuns(element.runs),
|
|
items: normalizeInsertedTextListItems(element.items),
|
|
columns: normalizeInsertedTableCells(element.columns),
|
|
rows: normalizeInsertedTableRows(element.rows),
|
|
});
|
|
}
|
|
|
|
export function normalizeInsertedTextRuns(value: unknown) {
|
|
if (!Array.isArray(value)) return value;
|
|
return value.map((run) => {
|
|
if (!isRecord(run)) return run;
|
|
return {
|
|
...run,
|
|
font: rawFontToSource(run.font),
|
|
};
|
|
});
|
|
}
|
|
|
|
export function normalizeInsertedTextListItems(value: unknown) {
|
|
if (!Array.isArray(value)) return value;
|
|
return value.map((item) =>
|
|
Array.isArray(item) ? normalizeInsertedTextRuns(item) : item,
|
|
);
|
|
}
|
|
|
|
export function normalizeInsertedTableRows(value: unknown) {
|
|
if (!Array.isArray(value)) return value;
|
|
return value.map((row) =>
|
|
Array.isArray(row) ? normalizeInsertedTableCells(row) : row,
|
|
);
|
|
}
|
|
|
|
export function normalizeInsertedTableCells(value: unknown) {
|
|
if (!Array.isArray(value)) return value;
|
|
return value.map((cell) => {
|
|
if (!isRecord(cell)) return cell;
|
|
return {
|
|
...cell,
|
|
font: rawFontToSource(cell.font),
|
|
runs: normalizeInsertedTextRuns(cell.runs),
|
|
};
|
|
});
|
|
}
|