mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-09-23 01:10:10 +02:00
better types
This commit is contained in:
@@ -1,4 +1,10 @@
|
|||||||
import { ExcalidrawElement, ExcalidrawGenericElement } from "../element/types";
|
import {
|
||||||
|
ExcalidrawElement,
|
||||||
|
ExcalidrawGenericElement,
|
||||||
|
FontFamilyValues,
|
||||||
|
TextAlign,
|
||||||
|
VerticalAlign,
|
||||||
|
} from "../element/types";
|
||||||
import {
|
import {
|
||||||
AppState,
|
AppState,
|
||||||
BinaryFiles,
|
BinaryFiles,
|
||||||
@@ -8,7 +14,10 @@ import {
|
|||||||
import type { cleanAppStateForExport } from "../appState";
|
import type { cleanAppStateForExport } from "../appState";
|
||||||
import { VERSIONS } from "../constants";
|
import { VERSIONS } from "../constants";
|
||||||
import { MarkOptional } from "../utility-types";
|
import { MarkOptional } from "../utility-types";
|
||||||
import { ElementConstructorOpts } from "../element/newElement";
|
import {
|
||||||
|
ElementConstructorOpts,
|
||||||
|
ELEMENTS_SUPPORTING_PROGRAMMATIC_API,
|
||||||
|
} from "../element/newElement";
|
||||||
|
|
||||||
export interface ExportedDataState {
|
export interface ExportedDataState {
|
||||||
type: string;
|
type: string;
|
||||||
@@ -38,18 +47,31 @@ export interface ImportedDataState {
|
|||||||
elements?:
|
elements?:
|
||||||
| readonly (
|
| readonly (
|
||||||
| (ExcalidrawElement & {
|
| (ExcalidrawElement & {
|
||||||
label?: { text: string } & MarkOptional<
|
label?: {
|
||||||
ElementConstructorOpts,
|
text: string;
|
||||||
"x" | "y"
|
fontSize?: number;
|
||||||
|
fontFamily?: FontFamilyValues;
|
||||||
|
textAlign?: TextAlign;
|
||||||
|
verticalAlign?: VerticalAlign;
|
||||||
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
|
} & ElementConstructorOpts)
|
||||||
|
| ({
|
||||||
|
type: Exclude<
|
||||||
|
typeof ELEMENTS_SUPPORTING_PROGRAMMATIC_API[number],
|
||||||
|
"text"
|
||||||
>;
|
>;
|
||||||
})
|
label?: {
|
||||||
| {
|
text: string;
|
||||||
type: Exclude<ExcalidrawGenericElement["type"], "selection">;
|
fontSize?: number;
|
||||||
label?: { text: string } & MarkOptional<
|
fontFamily?: FontFamilyValues;
|
||||||
ElementConstructorOpts,
|
textAlign?: TextAlign;
|
||||||
"x" | "y"
|
verticalAlign?: VerticalAlign;
|
||||||
>;
|
} & MarkOptional<ElementConstructorOpts, "x" | "y">;
|
||||||
}
|
} & ElementConstructorOpts)
|
||||||
|
| ({
|
||||||
|
type: "text";
|
||||||
|
text: string;
|
||||||
|
} & ElementConstructorOpts)
|
||||||
)[]
|
)[]
|
||||||
| null;
|
| null;
|
||||||
appState?: Readonly<
|
appState?: Readonly<
|
||||||
|
@@ -36,7 +36,7 @@ import {
|
|||||||
getBoundTextMaxWidth,
|
getBoundTextMaxWidth,
|
||||||
getDefaultLineHeight,
|
getDefaultLineHeight,
|
||||||
bindTextToContainer,
|
bindTextToContainer,
|
||||||
isValidTextContainer,
|
VALID_CONTAINER_TYPES,
|
||||||
} from "./textElement";
|
} from "./textElement";
|
||||||
import {
|
import {
|
||||||
DEFAULT_ELEMENT_PROPS,
|
DEFAULT_ELEMENT_PROPS,
|
||||||
@@ -50,7 +50,7 @@ import { isArrowElement } from "./typeChecks";
|
|||||||
import { MarkOptional, Merge, Mutable } from "../utility-types";
|
import { MarkOptional, Merge, Mutable } from "../utility-types";
|
||||||
import { ImportedDataState } from "../data/types";
|
import { ImportedDataState } from "../data/types";
|
||||||
|
|
||||||
const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
export const ELEMENTS_SUPPORTING_PROGRAMMATIC_API = [
|
||||||
"rectangle",
|
"rectangle",
|
||||||
"ellipse",
|
"ellipse",
|
||||||
"diamond",
|
"diamond",
|
||||||
@@ -664,67 +664,53 @@ export const convertToExcalidrawElements = (
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
elements.forEach((element) => {
|
elements.forEach((element) => {
|
||||||
if (!element) {
|
if (
|
||||||
|
!element ||
|
||||||
|
!ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (isValidTextContainer(element) && element?.label?.text) {
|
//@ts-ignore
|
||||||
|
if (VALID_CONTAINER_TYPES.has(element.type) && element?.label?.text) {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const elements = bindTextToContainer(element, element.label);
|
const elements = bindTextToContainer(element, element.label);
|
||||||
res.push(...elements);
|
res.push(...elements);
|
||||||
} else {
|
} else {
|
||||||
let excalidrawElement;
|
let excalidrawElement;
|
||||||
|
const { type, ...rest } = element;
|
||||||
if (element.type === "text") {
|
if (element.type === "text") {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
excalidrawElement = newTextElement({
|
excalidrawElement = newTextElement({
|
||||||
//@ts-ignore
|
|
||||||
x: 0,
|
|
||||||
//@ts-ignore
|
|
||||||
y: 0,
|
|
||||||
...element,
|
...element,
|
||||||
});
|
});
|
||||||
} else if (element.type === "arrow" || element.type === "line") {
|
} else if (type === "arrow" || type === "line") {
|
||||||
excalidrawElement = newLinearElement({
|
excalidrawElement = newLinearElement({
|
||||||
//@ts-ignore
|
type,
|
||||||
x: 0,
|
|
||||||
//@ts-ignore
|
|
||||||
y: 0,
|
|
||||||
//@ts-ignore
|
|
||||||
type: element.type,
|
|
||||||
//@ts-ignore
|
|
||||||
width: 200,
|
width: 200,
|
||||||
//@ts-ignore
|
|
||||||
height: 24,
|
height: 24,
|
||||||
//@ts-ignore,
|
|
||||||
endArrowhead: element.type === "arrow" ? "arrow" : null,
|
endArrowhead: element.type === "arrow" ? "arrow" : null,
|
||||||
//@ts-ignore
|
|
||||||
points: [
|
points: [
|
||||||
[0, 0],
|
[0, 0],
|
||||||
[200, 0],
|
[200, 0],
|
||||||
],
|
],
|
||||||
...element,
|
...rest,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
excalidrawElement = newElement({
|
excalidrawElement = newElement({
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
|
|
||||||
...element,
|
...element,
|
||||||
width:
|
width:
|
||||||
//@ts-ignore
|
|
||||||
element?.width ||
|
element?.width ||
|
||||||
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
||||||
? 100
|
? 100
|
||||||
: 0),
|
: 0),
|
||||||
height:
|
height:
|
||||||
//@ts-ignore
|
|
||||||
element?.height ||
|
element?.height ||
|
||||||
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
(ELEMENTS_SUPPORTING_PROGRAMMATIC_API.includes(element.type)
|
||||||
? 100
|
? 100
|
||||||
: 0),
|
: 0),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
//@ts-ignore
|
|
||||||
|
|
||||||
res.push(excalidrawElement);
|
res.push(excalidrawElement);
|
||||||
}
|
}
|
||||||
|
@@ -865,7 +865,7 @@ export const getTextBindableContainerAtPosition = (
|
|||||||
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
return isTextBindableContainer(hitElement, false) ? hitElement : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const VALID_CONTAINER_TYPES = new Set([
|
export const VALID_CONTAINER_TYPES = new Set([
|
||||||
"rectangle",
|
"rectangle",
|
||||||
"ellipse",
|
"ellipse",
|
||||||
"diamond",
|
"diamond",
|
||||||
|
@@ -7,7 +7,6 @@ import {
|
|||||||
VERTICAL_ALIGN,
|
VERTICAL_ALIGN,
|
||||||
} from "../constants";
|
} from "../constants";
|
||||||
import { MarkNonNullable, MarkOptional, ValueOf } from "../utility-types";
|
import { MarkNonNullable, MarkOptional, ValueOf } from "../utility-types";
|
||||||
import { ElementConstructorOpts } from "./newElement";
|
|
||||||
|
|
||||||
export type ChartType = "bar" | "line";
|
export type ChartType = "bar" | "line";
|
||||||
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
export type FillStyle = "hachure" | "cross-hatch" | "solid" | "zigzag";
|
||||||
|
@@ -606,6 +606,136 @@ const ExcalidrawWrapper = () => {
|
|||||||
|
|
||||||
const isOffline = useAtomValue(isOfflineAtom);
|
const isOffline = useAtomValue(isOfflineAtom);
|
||||||
|
|
||||||
|
const getInitialData = (): ExcalidrawInitialDataState => {
|
||||||
|
return {
|
||||||
|
scrollToContent: true,
|
||||||
|
//"type": "excalidraw/clipboard",
|
||||||
|
elements: [
|
||||||
|
// Test case with simple rectangle
|
||||||
|
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 10,
|
||||||
|
y: 10,
|
||||||
|
},
|
||||||
|
// Test case with simple ellipse
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 50,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
// Test case with simple diamond
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 120,
|
||||||
|
y: 20,
|
||||||
|
},
|
||||||
|
// Test case with simple text element
|
||||||
|
{
|
||||||
|
type: "text",
|
||||||
|
x: 300,
|
||||||
|
y: 100,
|
||||||
|
text: "HELLO",
|
||||||
|
},
|
||||||
|
// Test case with rectangle and some properties
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
backgroundColor: "#4dabf7",
|
||||||
|
width: 500,
|
||||||
|
height: 200,
|
||||||
|
x: 100,
|
||||||
|
y: 200,
|
||||||
|
},
|
||||||
|
// Test case with arrow and some properties
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
strokeWidth: 2,
|
||||||
|
x: 100,
|
||||||
|
y: 20,
|
||||||
|
},
|
||||||
|
// Test case with rectangle text container
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: 240,
|
||||||
|
y: 30,
|
||||||
|
label: {
|
||||||
|
text: "HELLO FROM RECT",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Test case with ellipse text container
|
||||||
|
{
|
||||||
|
type: "ellipse",
|
||||||
|
x: 400,
|
||||||
|
y: 410,
|
||||||
|
label: {
|
||||||
|
text: "HELLO FROM ELLIPSE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Test case with diamond text container
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 10,
|
||||||
|
y: 530,
|
||||||
|
label: {
|
||||||
|
text: "HELLO Text In Diamond",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Test case with diamond text container and some properties
|
||||||
|
{
|
||||||
|
type: "diamond",
|
||||||
|
x: 199,
|
||||||
|
y: 123,
|
||||||
|
backgroundColor: "#fff3bf",
|
||||||
|
strokeWidth: 2,
|
||||||
|
label: {
|
||||||
|
text: "HELLO Text In Diamond\n with props",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Test case with simple arrow
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: -120,
|
||||||
|
y: 40,
|
||||||
|
label: { text: "HELLO FROM ARROW" },
|
||||||
|
},
|
||||||
|
// Test case with simple line
|
||||||
|
{
|
||||||
|
type: "line",
|
||||||
|
x: -202,
|
||||||
|
y: 70,
|
||||||
|
},
|
||||||
|
// Test case for labeled arrow
|
||||||
|
{
|
||||||
|
type: "arrow",
|
||||||
|
x: -190,
|
||||||
|
y: 169,
|
||||||
|
label: {
|
||||||
|
text: "HELLO LABELED ARROW",
|
||||||
|
strokeColor: "#099268",
|
||||||
|
fontSize: 20,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// Test case for container with label alignments
|
||||||
|
{
|
||||||
|
type: "rectangle",
|
||||||
|
x: -300,
|
||||||
|
y: 200,
|
||||||
|
width: 113.3515625,
|
||||||
|
height: 100,
|
||||||
|
strokeColor: "#495057",
|
||||||
|
label: {
|
||||||
|
text: "HELLO RECT",
|
||||||
|
fontSize: 13.5,
|
||||||
|
textAlign: "left",
|
||||||
|
verticalAlign: "top",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
style={{ height: "100%" }}
|
style={{ height: "100%" }}
|
||||||
@@ -616,7 +746,7 @@ const ExcalidrawWrapper = () => {
|
|||||||
<Excalidraw
|
<Excalidraw
|
||||||
ref={excalidrawRefCallback}
|
ref={excalidrawRefCallback}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
initialData={initialStatePromiseRef.current.promise}
|
initialData={getInitialData()}
|
||||||
isCollaborating={isCollaborating}
|
isCollaborating={isCollaborating}
|
||||||
onPointerUpdate={collabAPI?.onPointerUpdate}
|
onPointerUpdate={collabAPI?.onPointerUpdate}
|
||||||
UIOptions={{
|
UIOptions={{
|
||||||
|
Reference in New Issue
Block a user