feat: add ElementDesign component for UI element styling and positioning.
This commit is contained in:
@@ -1,15 +1,7 @@
|
|||||||
import React, { RefObject, useEffect, useState } from "react";
|
import React, { RefObject, useEffect, useState } from "react";
|
||||||
import DataSourceSelector from "../../../ui/inputs/DataSourceSelector";
|
import DataSourceSelector from "../../../ui/inputs/DataSourceSelector";
|
||||||
import RenameInput from "../../../ui/inputs/RenameInput";
|
import RenameInput from "../../../ui/inputs/RenameInput";
|
||||||
import {
|
import { AlignJustifyIcon, AlignLeftIcon, AlignRightIcon, ArrowIcon, FlexColumnIcon, FlexRowIcon, FlexRowReverseIcon } from "../../../icons/ExportCommonIcons";
|
||||||
AlignJustifyIcon,
|
|
||||||
AlignLeftIcon,
|
|
||||||
AlignRightIcon,
|
|
||||||
ArrowIcon,
|
|
||||||
FlexColumnIcon,
|
|
||||||
FlexRowIcon,
|
|
||||||
FlexRowReverseIcon,
|
|
||||||
} from "../../../icons/ExportCommonIcons";
|
|
||||||
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
|
||||||
import InputRange from "../../../ui/inputs/InputRange";
|
import InputRange from "../../../ui/inputs/InputRange";
|
||||||
import { getAlphaFromRgba, hexToRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
|
import { getAlphaFromRgba, hexToRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
|
||||||
@@ -24,35 +16,15 @@ interface ElementDesignProps {
|
|||||||
selectedBlock: string;
|
selectedBlock: string;
|
||||||
selectedElement: string;
|
selectedElement: string;
|
||||||
updateElementStyle: (blockId: string, elementId: string, style: ExtendedCSSProperties) => void;
|
updateElementStyle: (blockId: string, elementId: string, style: ExtendedCSSProperties) => void;
|
||||||
updateElementSize: (
|
updateElementSize: (blockId: string, elementId: string, size: { width: number; height: number }) => void;
|
||||||
blockId: string,
|
updateElementPosition: (blockId: string, elementId: string, position: { x: number; y: number }) => void;
|
||||||
elementId: string,
|
updateElementPositionType: (blockId: string, elementId: string, positionType: "relative" | "absolute" | "fixed") => void;
|
||||||
size: { width: number; height: number }
|
|
||||||
) => void;
|
|
||||||
updateElementPosition: (
|
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
position: { x: number; y: number }
|
|
||||||
) => void;
|
|
||||||
updateElementPositionType: (
|
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
positionType: "relative" | "absolute" | "fixed"
|
|
||||||
) => void;
|
|
||||||
updateElementZIndex: (blockId: string, elementId: string, zIndex: number) => void;
|
updateElementZIndex: (blockId: string, elementId: string, zIndex: number) => void;
|
||||||
updateElementData: (
|
updateElementData: (blockId: string, elementId: string, updates: Partial<ElementDataBinding>) => void;
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
updates: Partial<ElementDataBinding>
|
|
||||||
) => void;
|
|
||||||
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
|
updateGraphData: (blockId: string, elementId: string, newData: GraphDataPoint[]) => void;
|
||||||
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
updateGraphTitle: (blockId: string, elementId: string, title: string) => void;
|
||||||
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
|
updateGraphType: (blockId: string, elementId: string, type: GraphTypes) => void;
|
||||||
updateDataType: (
|
updateDataType: (blockId: string, elementId: string, dataType: "single-machine" | "multiple-machine") => void;
|
||||||
blockId: string,
|
|
||||||
elementId: string,
|
|
||||||
dataType: "single-machine" | "multiple-machine"
|
|
||||||
) => void;
|
|
||||||
updateCommonValue: (blockId: string, elementId: string, commonValue: string) => void;
|
updateCommonValue: (blockId: string, elementId: string, commonValue: string) => void;
|
||||||
updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void;
|
updateDataValue: (blockId: string, elementId: string, dataValue: string | string[]) => void;
|
||||||
updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void;
|
updateDataSource: (blockId: string, elementId: string, dataSource: string | string[]) => void;
|
||||||
@@ -76,9 +48,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
const [color, setColor] = useState("#000000");
|
const [color, setColor] = useState("#000000");
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setColor(
|
setColor(rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "#000000"));
|
||||||
rgbaToHex(getCurrentElementStyleValue(currentElement, "backgroundColor") || "#000000")
|
|
||||||
);
|
|
||||||
}, [currentElement]);
|
}, [currentElement]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -95,11 +65,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
{ id: "radar", label: "Radar Chart" },
|
{ id: "radar", label: "Radar Chart" },
|
||||||
]}
|
]}
|
||||||
onSelect={(newValue) => {
|
onSelect={(newValue) => {
|
||||||
updateGraphType(
|
updateGraphType(selectedBlock, selectedElement, newValue.id as GraphTypes);
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
newValue.id as GraphTypes
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
showEyeDropper={false}
|
showEyeDropper={false}
|
||||||
/>
|
/>
|
||||||
@@ -112,15 +78,8 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
{["relative", "absolute"].map((position) => (
|
{["relative", "absolute"].map((position) => (
|
||||||
<div
|
<div
|
||||||
key={position}
|
key={position}
|
||||||
className={`type ${currentElement.positionType === position ? "active" : ""
|
className={`type ${currentElement.positionType === position ? "active" : ""}`}
|
||||||
}`}
|
onClick={() => updateElementPositionType(selectedBlock, selectedElement, position as "relative" | "absolute" | "fixed")}
|
||||||
onClick={() =>
|
|
||||||
updateElementPositionType(
|
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
position as "relative" | "absolute" | "fixed"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
{position.charAt(0).toUpperCase() + position.slice(1)}
|
{position.charAt(0).toUpperCase() + position.slice(1)}
|
||||||
</div>
|
</div>
|
||||||
@@ -129,48 +88,16 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<div className="position-canvas">
|
<div className="position-canvas">
|
||||||
<div className="canvas">
|
<div className="canvas">
|
||||||
<div className="value padding-top">
|
<div className="value padding-top">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-right">
|
<div className="value padding-right">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-bottom">
|
<div className="value padding-bottom">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="value padding-left">
|
<div className="value padding-left">
|
||||||
<RenameInput
|
<RenameInput value={getCurrentElementStyleValue(currentElement, "padding") ? String(getCurrentElementStyleValue(currentElement, "padding")) : "120"} />
|
||||||
value={
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
? String(
|
|
||||||
getCurrentElementStyleValue(currentElement, "padding")
|
|
||||||
)
|
|
||||||
: "120"
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -178,10 +105,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<div className="alignments-section">
|
<div className="alignments-section">
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right"
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "right" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
@@ -191,11 +115,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<AlignRightIcon />
|
<AlignRightIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") ===
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "justify" ? "active" : ""}`}
|
||||||
"justify"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "justify",
|
textAlign: "justify",
|
||||||
@@ -205,10 +125,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<AlignJustifyIcon />
|
<AlignJustifyIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left"
|
className={`icon ${getCurrentElementStyleValue(currentElement, "textAlign") === "left" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
textAlign: "left",
|
textAlign: "left",
|
||||||
@@ -220,10 +137,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
</div>
|
</div>
|
||||||
<div className="section">
|
<div className="section">
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row"
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row" ? "active" : ""}`}
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
@@ -233,11 +147,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexRowIcon />
|
<FlexRowIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column" ? "active" : ""}`}
|
||||||
"column"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "column",
|
flexDirection: "column",
|
||||||
@@ -247,11 +157,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexColumnIcon />
|
<FlexColumnIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "row-reverse" ? "active" : ""}`}
|
||||||
"row-reverse"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "row-reverse",
|
flexDirection: "row-reverse",
|
||||||
@@ -261,11 +167,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<FlexRowReverseIcon />
|
<FlexRowReverseIcon />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={`icon ${((currentElement.style.flexDirection as string) || "row") ===
|
className={`icon ${((currentElement.style.flexDirection as string) || "row") === "column-reverse" ? "active" : ""}`}
|
||||||
"column-reverse"
|
|
||||||
? "active"
|
|
||||||
: ""
|
|
||||||
}`}
|
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
flexDirection: "column-reverse",
|
flexDirection: "column-reverse",
|
||||||
@@ -282,22 +184,12 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
label="Layer"
|
label="Layer"
|
||||||
value={String(currentElement.zIndex || 1)}
|
value={String(currentElement.zIndex || 1)}
|
||||||
placeholder={"Layer"}
|
placeholder={"Layer"}
|
||||||
onChange={(newValue: string) =>
|
onChange={(newValue: string) => updateElementZIndex(selectedBlock, selectedElement, Number(newValue))}
|
||||||
updateElementZIndex(
|
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(newValue)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
className="increase-z"
|
className="increase-z"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
updateElementZIndex(
|
updateElementZIndex(selectedBlock, selectedElement, Number(currentElement.zIndex ? currentElement.zIndex + 1 : 1));
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(currentElement.zIndex ? currentElement.zIndex + 1 : 1)
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
@@ -305,11 +197,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
<button
|
<button
|
||||||
className="decrease-z"
|
className="decrease-z"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
updateElementZIndex(
|
updateElementZIndex(selectedBlock, selectedElement, Number(currentElement.zIndex ? currentElement.zIndex - 1 : 1));
|
||||||
selectedBlock,
|
|
||||||
selectedElement,
|
|
||||||
Number(currentElement.zIndex ? currentElement.zIndex - 1 : 1)
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowIcon />
|
<ArrowIcon />
|
||||||
@@ -353,10 +241,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
/>
|
/>
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
label="Width"
|
label="Width"
|
||||||
value={String(
|
value={String(currentElement.size?.width ?? (currentElement.type === "graph" ? 400 : 200))}
|
||||||
currentElement.size?.width ??
|
|
||||||
(currentElement.type === "graph" ? 400 : 200)
|
|
||||||
)}
|
|
||||||
placeholder={"Width"}
|
placeholder={"Width"}
|
||||||
onChange={(newValue: string) => {
|
onChange={(newValue: string) => {
|
||||||
updateElementSize(selectedBlock, selectedElement, {
|
updateElementSize(selectedBlock, selectedElement, {
|
||||||
@@ -367,10 +252,7 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
/>
|
/>
|
||||||
<InputWithDropDown
|
<InputWithDropDown
|
||||||
label="Height"
|
label="Height"
|
||||||
value={String(
|
value={String(currentElement.size?.height ?? (currentElement.type === "graph" ? 200 : 60))}
|
||||||
currentElement.size?.height ??
|
|
||||||
(currentElement.type === "graph" ? 200 : 60)
|
|
||||||
)}
|
|
||||||
placeholder={"Height"}
|
placeholder={"Height"}
|
||||||
onChange={(newValue: string) => {
|
onChange={(newValue: string) => {
|
||||||
updateElementSize(selectedBlock, selectedElement, {
|
updateElementSize(selectedBlock, selectedElement, {
|
||||||
@@ -380,6 +262,17 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<InputRange
|
||||||
|
label={"Border Radius"}
|
||||||
|
min={0}
|
||||||
|
max={8}
|
||||||
|
value={parseInt(getCurrentElementStyleValue(currentElement, "borderRadius") || "") || 8}
|
||||||
|
onChange={(newValue: number) => {
|
||||||
|
updateElementStyle(selectedBlock, selectedElement, {
|
||||||
|
borderRadius: Number(newValue),
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="design-section element-color">
|
<div className="design-section element-color">
|
||||||
@@ -443,21 +336,6 @@ const ElementDesign: React.FC<ElementDesignProps> = ({
|
|||||||
updateElementStyle(selectedBlock, selectedElement, { backdropFilter: `blur(${Number(value)}px)` });
|
updateElementStyle(selectedBlock, selectedElement, { backdropFilter: `blur(${Number(value)}px)` });
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<InputRange
|
|
||||||
label={"Border Radius"}
|
|
||||||
min={0}
|
|
||||||
max={8}
|
|
||||||
value={
|
|
||||||
parseInt(
|
|
||||||
getCurrentElementStyleValue(currentElement, "borderRadius") || ""
|
|
||||||
) || 8
|
|
||||||
}
|
|
||||||
onChange={(newValue: number) => {
|
|
||||||
updateElementStyle(selectedBlock, selectedElement, {
|
|
||||||
borderRadius: Number(newValue),
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user