feat: Enhance BlockEditor with data handling and UI improvements

- Added a type switch for selecting between "design" and "data" modes in BlockEditor.
- Implemented DataDetailedDropdown component for improved data selection.
- Introduced DeviceIcon and ParametersIcon for better visual representation in dropdowns.
- Updated styles for BlockEditor and related components to improve layout and usability.
- Refactored background color and opacity handling in BlockEditor.
- Removed unnecessary loading page and scene components from MainScene.
This commit is contained in:
Nalvazhuthi
2025-12-16 12:39:15 +05:30
parent 083d008221
commit a771f34b04
6 changed files with 693 additions and 178 deletions

48
app/package-lock.json generated
View File

@@ -2031,7 +2031,7 @@
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"devOptional": true,
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
@@ -2043,7 +2043,7 @@
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"devOptional": true,
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
@@ -4242,26 +4242,6 @@
"url": "https://github.com/sponsors/gregberge"
}
},
"node_modules/@testing-library/dom": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.1.tgz",
"integrity": "sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==",
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
"@types/aria-query": "^5.0.1",
"aria-query": "5.3.0",
"dom-accessibility-api": "^0.5.9",
"lz-string": "^1.5.0",
"picocolors": "1.1.1",
"pretty-format": "^27.0.2"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@testing-library/jest-dom": {
"version": "5.17.0",
"resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-5.17.0.tgz",
@@ -4373,25 +4353,25 @@
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"devOptional": true
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"devOptional": true
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"devOptional": true
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"devOptional": true
"dev": true
},
"node_modules/@turf/along": {
"version": "7.2.0",
@@ -9233,7 +9213,7 @@
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"devOptional": true
"dev": true
},
"node_modules/cross-env": {
"version": "7.0.3",
@@ -10249,7 +10229,7 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"devOptional": true,
"dev": true,
"engines": {
"node": ">=0.3.1"
}
@@ -15652,7 +15632,7 @@
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"devOptional": true
"dev": true
},
"node_modules/makeerror": {
"version": "1.0.12",
@@ -21308,7 +21288,7 @@
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"devOptional": true,
"dev": true,
"dependencies": {
"@cspotcode/source-map-support": "^0.8.0",
"@tsconfig/node10": "^1.0.7",
@@ -21351,7 +21331,7 @@
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
"integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"devOptional": true,
"dev": true,
"dependencies": {
"acorn": "^8.11.0"
},
@@ -21363,7 +21343,7 @@
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"devOptional": true
"dev": true
},
"node_modules/tsconfig-paths": {
"version": "3.15.0",
@@ -21859,7 +21839,7 @@
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"devOptional": true
"dev": true
},
"node_modules/v8-to-istanbul": {
"version": "8.1.1",
@@ -22952,7 +22932,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"devOptional": true,
"dev": true,
"engines": {
"node": ">=6"
}

View File

@@ -1,4 +1,4 @@
import type { RefObject } from "react";
import { useState, type RefObject } from "react";
import { Block } from "../../../../types/exportedTypes";
import { getAlphaFromRgba, rgbaToHex } from "../../functions/helpers/colorHandlers";
import { getCurrentBlockStyleValue } from "../../functions/helpers/getCurrentBlockStyleValue";
@@ -8,6 +8,9 @@ import { handleBlurAmountChange } from "../../functions/helpers/handleBlurAmount
import InputRange from "../../../ui/inputs/InputRange";
import RegularDropDown from "../../../ui/inputs/RegularDropDown";
import { DeleteIcon } from "../../../icons/ContextMenuIcons";
import InputWithDropDown from "../../../ui/inputs/InputWithDropDown";
import { AddIcon, DeviceIcon, EyeDroperIcon, ParametersIcon } from "../../../icons/ExportCommonIcons";
import DataDetailedDropdown from "../../../ui/inputs/DataDetailedDropdown";
interface BlockEditorProps {
blockEditorRef: RefObject<HTMLDivElement>;
@@ -30,27 +33,48 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
updateBlockPositionType,
updateBlockZIndex,
}) => {
const [selectType, setSelectType] = useState("data")
return (
<div ref={blockEditorRef} className="panel block-editor-panel">
<div className="header">
<h4>Block Style</h4>
<div className="delete icon">
{/* <div className="delete icon">
<DeleteIcon />
</div> */}
</div>
<div className="type-switch">
<div
className={`type ${selectType === "design" ? "active" : ""}`}
onClick={() => setSelectType("design")}>
Design
</div>
<div
className={`type ${selectType === "data" ? "active" : ""}`}
onClick={() => setSelectType("data")}>
Data
</div>
</div>
<div className="form-group">
<label className="form-label">Position Type: </label>
<select
value={currentBlock.positionType || "relative"}
onChange={(e) => updateBlockPositionType(selectedBlock, e.target.value as "relative" | "absolute" | "fixed")}
className="form-select"
>
<option value="relative">Relative</option>
<option value="absolute">Absolute</option>
<option value="fixed">Fixed</option>
</select>
{/* <RegularDropDown
{selectType === "design" && (
<>
<div className="form-group">
<label className="form-label">Position Type: </label>
<select
value={currentBlock.positionType || "relative"}
onChange={(e) => updateBlockPositionType(selectedBlock, e.target.value as "relative" | "absolute" | "fixed")}
className="form-select"
>
<option value="relative">Relative</option>
<option value="absolute">Absolute</option>
<option value="fixed">Fixed</option>
</select>
{/* <RegularDropDown
header={currentBlock.positionType || "relative"}
options={["Relative", "Absolute", "Fixed"]} // Pass layout names as options
onSelect={(option) => updateBlockPositionType(
@@ -59,55 +83,55 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
)}
search={false}
/> */}
</div>
</div>
{currentBlock.positionType === "absolute" && (
<>
<div className="form-group">
<label className="form-label">X Position: </label>
<input
type="number"
placeholder="X"
value={currentBlock.position?.x || 0}
onChange={(e) =>
updateBlockPosition(selectedBlock, {
...currentBlock.position!,
x: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Y Position: </label>
<input
type="number"
placeholder="Y"
value={currentBlock.position?.y || 0}
onChange={(e) =>
updateBlockPosition(selectedBlock, {
...currentBlock.position!,
y: Number(e.target.value),
})
}
className="form-input"
/>
</div>
</>
)}
{currentBlock.positionType === "absolute" && (
<>
<div className="form-group">
<label className="form-label">X Position: </label>
<label className="form-label">Background Color: </label>
<input
type="number"
placeholder="X"
value={currentBlock.position?.x || 0}
onChange={(e) =>
updateBlockPosition(selectedBlock, {
...currentBlock.position!,
x: Number(e.target.value),
})
}
className="form-input"
type="color"
value={rgbaToHex(getCurrentBlockStyleValue(currentBlock, "backgroundColor"))}
onChange={(e) => handleBackgroundColorChange(currentBlock, selectedBlock, updateBlockStyle, e.target.value)}
className="color-input"
/>
</div>
<div className="form-group">
<label className="form-label">Y Position: </label>
<input
type="number"
placeholder="Y"
value={currentBlock.position?.y || 0}
onChange={(e) =>
updateBlockPosition(selectedBlock, {
...currentBlock.position!,
y: Number(e.target.value),
})
}
className="form-input"
/>
</div>
</>
)}
<div className="form-group">
<label className="form-label">Background Color: </label>
<input
type="color"
value={rgbaToHex(getCurrentBlockStyleValue(currentBlock, "backgroundColor"))}
onChange={(e) => handleBackgroundColorChange(currentBlock, selectedBlock, updateBlockStyle, e.target.value)}
className="color-input"
/>
</div>
<div className="form-group">
{/* <label className="form-label">
{/* <label className="form-label">
Background Opacity:{" "}
{Math.round(
getAlphaFromRgba(
@@ -136,20 +160,20 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
className="range-input"
/> */}
<InputRange
label="Background Opacity"
disabled={false}
value={Math.round(getAlphaFromRgba(getCurrentBlockStyleValue(currentBlock, "backgroundColor")) * 100)}
min={0}
max={100}
onChange={(value: number) => handleBackgroundAlphaChange(currentBlock, selectedBlock, updateBlockStyle, Number(value))}
// onPointerUp={updatedDist}
key={"6"}
/>
</div>
<InputRange
label="Background Opacity"
disabled={false}
value={Math.round(getAlphaFromRgba(getCurrentBlockStyleValue(currentBlock, "backgroundColor")) * 100)}
min={0}
max={100}
onChange={(value: number) => handleBackgroundAlphaChange(currentBlock, selectedBlock, updateBlockStyle, Number(value))}
// onPointerUp={updatedDist}
key={"6"}
/>
</div>
<div className="form-group">
{/* <label className="form-label">
<div className="form-group">
{/* <label className="form-label">
Blur Amount:{" "}
{parseInt(
getCurrentBlockStyleValue(currentBlock, "backdropFilter")?.match(
@@ -177,80 +201,216 @@ const BlockEditor: React.FC<BlockEditorProps> = ({
className="range-input"
/> */}
<InputRange
label="Blur Amount"
disabled={false}
value={parseInt(getCurrentBlockStyleValue(currentBlock, "backdropFilter")?.match(/\d+/)?.[0] || "10")}
min={0}
max={50}
onChange={(value: number) => handleBlurAmountChange(selectedBlock, updateBlockStyle, Number(value))}
// onPointerUp={updatedDist}
key={"6"}
/>
</div>
<InputRange
label="Blur Amount"
disabled={false}
value={parseInt(getCurrentBlockStyleValue(currentBlock, "backdropFilter")?.match(/\d+/)?.[0] || "10")}
min={0}
max={50}
onChange={(value: number) => handleBlurAmountChange(selectedBlock, updateBlockStyle, Number(value))}
// onPointerUp={updatedDist}
key={"6"}
/>
</div>
<div className="form-group">
<label className="form-label">Width: </label>
<input
type="number"
placeholder="Width"
value={currentBlock.size?.width || 400}
onChange={(e) =>
updateBlockSize(selectedBlock, {
...currentBlock.size!,
width: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Width: </label>
<input
type="number"
placeholder="Width"
value={currentBlock.size?.width || 400}
onChange={(e) =>
updateBlockSize(selectedBlock, {
...currentBlock.size!,
width: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Height: </label>
<input
type="number"
placeholder="Height"
value={currentBlock.size?.height || 300}
onChange={(e) =>
updateBlockSize(selectedBlock, {
...currentBlock.size!,
height: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Height: </label>
<input
type="number"
placeholder="Height"
value={currentBlock.size?.height || 300}
onChange={(e) =>
updateBlockSize(selectedBlock, {
...currentBlock.size!,
height: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Z-Index: </label>
<input type="number" placeholder="Z-Index" value={currentBlock.zIndex || 1} onChange={(e) => updateBlockZIndex(selectedBlock, Number(e.target.value))} className="form-input" />
</div>
<div className="form-group">
<label className="form-label">Z-Index: </label>
<input type="number" placeholder="Z-Index" value={currentBlock.zIndex || 1} onChange={(e) => updateBlockZIndex(selectedBlock, Number(e.target.value))} className="form-input" />
</div>
<div className="form-group">
<label className="form-label">Padding: </label>
<input
type="number"
placeholder="Padding"
value={parseInt(getCurrentBlockStyleValue(currentBlock, "padding")) || 10}
onChange={(e) => updateBlockStyle(selectedBlock, { padding: Number(e.target.value) })}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Padding: </label>
<input
type="number"
placeholder="Padding"
value={parseInt(getCurrentBlockStyleValue(currentBlock, "padding")) || 10}
onChange={(e) => updateBlockStyle(selectedBlock, { padding: Number(e.target.value) })}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Border Radius: </label>
<input
type="number"
placeholder="Border Radius"
value={parseInt(getCurrentBlockStyleValue(currentBlock, "borderRadius")) || 8}
onChange={(e) =>
updateBlockStyle(selectedBlock, {
borderRadius: Number(e.target.value),
})
}
className="form-input"
/>
</div>
<div className="form-group">
<label className="form-label">Border Radius: </label>
<input
type="number"
placeholder="Border Radius"
value={parseInt(getCurrentBlockStyleValue(currentBlock, "borderRadius")) || 8}
onChange={(e) =>
updateBlockStyle(selectedBlock, {
borderRadius: Number(e.target.value),
})
}
className="form-input"
/>
</div>
</>
)}
{selectType === "data" && (
<div className="data-details">
<div className="data-wrapper">
<InputWithDropDown
label="Title"
value={`title`}
placeholder={"Label 1"}
min={0.1}
step={0.1}
max={2}
onChange={() => { }}
/>
<div className="data">
<DataDetailedDropdown
title="Data Source"
placeholder="Select assets"
sections={[
{
title: "Global",
items: [
{ id: "global", label: "Global", icon: <DeviceIcon /> },
],
},
{
title: "Assets",
items: [
{ id: "cmm-001", label: "CMM-001", icon: <DeviceIcon /> },
{ id: "cnc-1", label: "CNC-Lathe-0001", icon: <DeviceIcon /> },
{ id: "cnc-2", label: "CNC-drilling-tapping-3Axis", icon: <DeviceIcon /> },
{ id: "cnc-3", label: "CNC_0001", icon: <DeviceIcon /> },
],
},
]}
value={null}
onChange={() => { }}
dropDownHeader={"RT-Data"}
eyedroper={true}
/>
</div>
<div className="data">
<DataDetailedDropdown
title="Value"
placeholder="Select Value"
sections={[
{
title: "Selected Assets name",
items: [
{ id: "ambientTemp", label: "ambientTemp", icon: <ParametersIcon /> },
{ id: "measurementDeviation", label: "measurementDeviation", icon: <ParametersIcon /> },
{ id: "powerConsumption", label: "powerConsumption", icon: <ParametersIcon /> },
{ id: "probeX", label: "probePositionX", icon: <ParametersIcon /> },
{ id: "probeY", label: "probePositionY", icon: <ParametersIcon /> },
{ id: "probeZ", label: "probePositionZ", icon: <ParametersIcon /> },
],
},
]}
value={null}
onChange={() => { }}
dropDownHeader={"RT-Data-Value"}
/>
</div>
</div>
{/* <div className="data-mapping">
<div className="heading">Data Mapping</div>
<div className="type-switch">
<div
className={`type active`}
onClick={() => setSelectType("design")}
>
Single Machine
</div>
<div
className={`type`}
onClick={() => setSelectType("data")}
>
Multiple Machine
</div>
</div>
<div className="fields-wrapper">
<div className="datas">
<div className="datas__label">Data Source</div>
<div className="datas__class">
<RegularDropDown
header={"Select value"}
options={["1h", "2h", "12h"]}
onSelect={() => { }}
search={false}
/>
</div>
</div>
<div className="datas">
<div className="datas__label">Input 1</div>
<div className="datas__class">
<RegularDropDown
header={"Select value"}
options={["1h", "2h", "12h"]}
onSelect={() => { }}
search={false}
/>
</div>
</div>
<div className="datas">
<div className="datas__label">Input 2</div>
<div className="datas__class">
<RegularDropDown
header={"Select value"}
options={["1h", "2h", "12h"]}
onSelect={() => { }}
search={false}
/>
</div>
</div>
<div className="add-field">
<div className="icon"><AddIcon /></div>
<div className="label">Add Field</div>
</div>
</div>
</div> */}
</div>
)}
</div>
);
};

View File

@@ -1748,3 +1748,29 @@ export const PerformanceStatsIcon = () => {
</svg>
);
};
export const DeviceIcon = () => {
return (
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.4 1.125H5.38395C4.97753 1.125 4.64972 1.125 4.38427 1.14668C4.11095 1.16902 3.87088 1.2162 3.64877 1.32937C3.29597 1.50913 3.00913 1.79597 2.82937 2.14877C2.7162 2.37088 2.66902 2.61095 2.64668 2.88427C2.625 3.14972 2.625 3.47753 2.625 3.88395V3.9V8.1V8.11605C2.625 8.52245 2.625 8.8503 2.64668 9.11575C2.66902 9.38905 2.7162 9.6291 2.82937 9.85125C3.00913 10.2041 3.29597 10.4908 3.64877 10.6706C3.87088 10.7838 4.11095 10.831 4.38427 10.8533C4.64972 10.875 4.97753 10.875 5.38395 10.875H5.4H6.6H6.61605C7.0225 10.875 7.3503 10.875 7.61575 10.8533C7.88905 10.831 8.1291 10.7838 8.35125 10.6706C8.70405 10.4908 8.99085 10.2041 9.17065 9.85125C9.2838 9.6291 9.331 9.38905 9.3533 9.11575C9.375 8.8503 9.375 8.5225 9.375 8.11605V8.1V3.9V3.88394C9.375 3.47753 9.375 3.14972 9.3533 2.88427C9.331 2.61095 9.2838 2.37088 9.17065 2.14877C8.99085 1.79597 8.70405 1.50913 8.35125 1.32937C8.1291 1.2162 7.88905 1.16902 7.61575 1.14668C7.3503 1.125 7.0225 1.125 6.61605 1.125H6.6H5.4ZM3.98926 1.99762C4.08802 1.9473 4.2184 1.91274 4.44534 1.89419C4.67666 1.87529 4.97378 1.875 5.4 1.875H6.6C7.02625 1.875 7.32335 1.87529 7.55465 1.89419C7.7816 1.91274 7.912 1.9473 8.01075 1.99762C8.2224 2.10548 8.3945 2.27758 8.5024 2.48926C8.5527 2.58802 8.58725 2.71841 8.6058 2.94534C8.6247 3.17666 8.625 3.47378 8.625 3.9V8.1C8.625 8.52625 8.6247 8.82335 8.6058 9.05465C8.58725 9.2816 8.5527 9.412 8.5024 9.51075C8.3945 9.7224 8.2224 9.8945 8.01075 10.0024C7.912 10.0527 7.7816 10.0872 7.55465 10.1058C7.32335 10.1247 7.02625 10.125 6.6 10.125H5.4C4.97378 10.125 4.67666 10.1247 4.44534 10.1058C4.2184 10.0872 4.08802 10.0527 3.98926 10.0024C3.77758 9.8945 3.60548 9.7224 3.49762 9.51075C3.4473 9.412 3.41274 9.2816 3.39419 9.05465C3.37529 8.82335 3.375 8.52625 3.375 8.1V3.9C3.375 3.47378 3.37529 3.17666 3.39419 2.94534C3.41274 2.71841 3.4473 2.58802 3.49762 2.48926C3.60548 2.27758 3.77758 2.10548 3.98926 1.99762ZM5 8.625C4.7929 8.625 4.625 8.7929 4.625 9C4.625 9.2071 4.7929 9.375 5 9.375H7C7.2071 9.375 7.375 9.2071 7.375 9C7.375 8.7929 7.2071 8.625 7 8.625H5Z" fill="#CCACFF" />
</svg>
);
};
export const ParametersIcon = () => {
return (
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_6422_4175)">
<path d="M10.5 4.875V3C10.4998 2.80116 10.4207 2.61052 10.2801 2.46992C10.1395 2.32932 9.94884 2.25023 9.75 2.25H8.625V3H9.75V4.875C9.75072 5.08872 9.79738 5.29978 9.88681 5.49388C9.97625 5.68799 10.1064 5.86059 10.2684 6C10.1064 6.13941 9.97625 6.31201 9.88681 6.50612C9.79738 6.70022 9.75072 6.91128 9.75 7.125V9H8.625V9.75H9.75C9.94884 9.74977 10.1395 9.67068 10.2801 9.53008C10.4207 9.38948 10.4998 9.19884 10.5 9V7.125C10.5002 6.92616 10.5793 6.73552 10.7199 6.59492C10.8605 6.45432 11.0512 6.37523 11.25 6.375V5.625C11.0512 5.62477 10.8605 5.54568 10.7199 5.40508C10.5793 5.26447 10.5002 5.07384 10.5 4.875Z" fill="#B7B7C6" />
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.375 3.375L6.05362 4.5H6.80362L7.125 3.375H7.875L7.55362 4.5H8.25V5.25H7.3395L6.91088 6.75H7.875V7.5H6.69638L6.375 8.625H5.625L5.94638 7.5H5.19638L4.875 8.625H4.125L4.44638 7.5H3.75V6.75H4.66087L5.0895 5.25H4.125V4.5H5.30362L5.625 3.375H6.375ZM6.5895 5.25H5.8395L5.41087 6.75H6.16088L6.5895 5.25Z" fill="#B7B7C6" />
<path d="M2.25 4.875V3H3.375V2.25H2.25C2.05116 2.25023 1.86052 2.32932 1.71992 2.46992C1.57932 2.61052 1.50023 2.80116 1.5 3V4.875C1.49977 5.07384 1.42068 5.26447 1.28008 5.40508C1.13948 5.54568 0.948842 5.62477 0.75 5.625V6.375C0.948842 6.37523 1.13948 6.45432 1.28008 6.59492C1.42068 6.73552 1.49977 6.92616 1.5 7.125V9C1.50023 9.19884 1.57932 9.38948 1.71992 9.53008C1.86052 9.67068 2.05116 9.74977 2.25 9.75H3.375V9H2.25V7.125C2.24928 6.91128 2.20262 6.70022 2.11319 6.50612C2.02375 6.31201 1.89363 6.13941 1.73164 6C1.89363 5.86059 2.02375 5.68799 2.11319 5.49388C2.20262 5.29978 2.24928 5.08872 2.25 4.875Z" fill="#B7B7C6" />
</g>
<defs>
<clipPath id="clip0_6422_4175">
<rect width="12" height="12" fill="white" />
</clipPath>
</defs>
</svg>
);
};

View File

@@ -188,7 +188,7 @@ function MainScene() {
{!selectedUser && (
<>
<KeyPressListener />
{!createNewWindow && loadingProgress > 0 && <LoadingPage progress={loadingProgress} />}
{/* {!createNewWindow && loadingProgress > 0 && <LoadingPage progress={loadingProgress} />} */}
{!isPlaying && (
<>
{!toggleView && !isComparing && <ModuleToggle />}
@@ -254,7 +254,7 @@ function MainScene() {
}
onDragOver={(event) => event.preventDefault()}
>
<Scene layout="Main Layout" />
{/* <Scene layout="Main Layout" /> */}
</div>
</>
);

View File

@@ -0,0 +1,110 @@
import React, { useState, useMemo } from "react";
import { EyeDroperIcon, SearchIcon } from "../../icons/ExportCommonIcons";
export type DropdownItem = {
id: string;
label: string;
icon?: React.ReactNode;
};
type DataDetailedDropdownProps = {
title: string;
placeholder?: string;
sections: {
title?: string;
items: DropdownItem[];
}[];
value?: DropdownItem | null;
onChange?: (item: DropdownItem) => void;
dropDownHeader?: string;
eyedroper?: boolean
};
const DataDetailedDropdown: React.FC<DataDetailedDropdownProps> = ({
title,
placeholder = "Select value",
sections,
value,
onChange,
dropDownHeader,
eyedroper
}) => {
const [open, setOpen] = useState(false);
const [search, setSearch] = useState("");
const filteredSections = useMemo(() => {
if (!search) return sections;
return sections
.map((section) => ({
...section,
items: section.items.filter((item) =>
item.label.toLowerCase().includes(search.toLowerCase())
),
}))
.filter((section) => section.items.length > 0);
}, [search, sections]);
return (
<div className="data-detailed-dropdown">
<div className="title">{title}</div>
<div className="input-container">
<div className="input-wrapper">
<div
className="input"
onClick={() => setOpen((v) => !v)}
>
{value?.label || placeholder}
<div className="icon"></div>
</div>
{open && (
<div className="dropdown-panel">
<div className="heading">{dropDownHeader}</div>
<div className="search">
<div className="icon">
<SearchIcon />
</div>
<input
placeholder="Search Assets"
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
</div>
{filteredSections.map((section, index) => (
<div key={index} className="data-section">
{section.title && (
<div className="data-header">
<div className="data-section-title">{section.title}</div>
<div className="data-section-count">
{section.items.length}
</div>
</div>
)}
{section.items.map((item) => (
<div
key={item.id}
className="item"
onClick={() => {
onChange?.(item);
setOpen(false);
}}
>
{item.icon && <span className="icon">{item.icon}</span>}
<span>{item.label}</span>
</div>
))}
</div>
))}
</div>
)}
</div>
{eyedroper && <div className="icon"><EyeDroperIcon isActive={false} /></div>}
</div>
</div>
);
};
export default DataDetailedDropdown;

View File

@@ -12,7 +12,7 @@
left: 0;
pointer-events: none;
* > {
*> {
pointer-events: auto;
}
@@ -276,7 +276,7 @@
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 0 10px 0;
// margin: 0 0 10px 0;
border-bottom: 1px solid gray;
padding-bottom: 10px;
@@ -312,12 +312,121 @@
}
&.block-editor-panel {
display: flex;
flex-direction: column;
gap: 11px;
min-width: 280px;
height: fit-content;
min-width: 320px;
min-height: 70vh;
padding: 20px 8px;
// h4 {
// color: #4caf50;
// }
.type-switch {
display: flex;
padding: 6px 12px;
.type {
flex: 1;
text-align: center;
padding: 4px 0;
border-radius: 19px;
cursor: pointer;
&.active {
background: var(--background-color-button);
}
}
}
.data-details {
display: flex;
flex-direction: column;
gap: 6px;
.data-wrapper {
display: flex;
flex-direction: column;
gap: 6px;
padding: 6px 12px;
.value-field-container {
margin: 0;
padding: 0;
.label,
.input.default {
width: auto;
flex: 1;
}
}
.data {
display: flex;
justify-content: center;
align-items: center;
gap: 9px;
.datas_label,
.regularDropdown-container {
flex: 1;
}
}
}
.data-mapping {
display: flex;
flex-direction: column;
gap: 9px;
background: var(--background-color);
border: 1px solid var(--border-color);
box-shadow: var(--box-shadow-medium);
padding: 15px 12px;
border-radius: 25px;
.heading {
text-align: center;
}
.type-switch {
padding: 0;
}
.fields-wrapper {
display: flex;
flex-direction: column;
gap: 2px;
.datas {
width: 100%;
display: flex;
padding: 6px 12px;
.datas__label,
.datas__class {
flex: 1;
}
}
.add-field {
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
svg path {
stroke: #CCACFF !important;
}
.label {
color: #CCACFF;
}
}
}
}
}
}
&.element-editor-panel {
@@ -534,3 +643,133 @@
}
}
}
// DataDetailedDropdown
.data-detailed-dropdown {
display: flex;
width: 100%;
.title,
.input-container {
flex: 1;
}
.input-container {
width: 100%;
display: flex;
align-items: center;
gap: 6px;
.input-wrapper {
width: 100%;
}
.icon {
cursor: pointer;
}
}
.input-wrapper {
outline: 1px solid var(--input-border-color);
outline-offset: -1px;
border: none;
background: var(--background-color-input);
color: var(--input-text-color);
border-radius: 100px;
position: relative;
.input {
display: flex;
justify-content: space-between;
padding: 4px 8px;
}
.dropdown-panel {
position: absolute;
z-index: 1;
top: 0;
right: 0;
transform: translateY(30px);
min-width: 200px;
padding: 12px;
outline: 1px solid var(--border-color);
outline-offset: -1px;
border-radius: 12px;
background: var(--background-color);
backdrop-filter: blur(20px);
display: flex;
flex-direction: column;
gap: 8px;
.search {
outline: 1px solid var(--border-color);
outline-offset: -1px;
border-radius: 12px;
background: var(--background-color);
display: flex;
align-items: center;
padding: 4px 9px;
.icon {
height: 10px;
display: flex;
justify-content: center;
align-items: center;
}
input {
outline: none;
border: none;
background: transparent;
padding: 0;
padding-left: 3px;
}
}
.data-section {
.data-header {
display: flex;
justify-content: space-between;
align-items: center;
.data-section-count{
font-size: 10px;
}
}
.item {
padding: 8px 0;
display: flex;
gap: 2px;
align-items: center;
.icon {
display: flex;
justify-content: center;
align-items: center;
}
&.active {
span {
color: #CCACFF;
}
}
}
}
}
}
}