old dwinzo files updated
This commit is contained in:
89
app/src/components/ui/3d-ui/distanceText.jsx
Normal file
89
app/src/components/ui/3d-ui/distanceText.jsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import { useEffect, useState } from "react"
|
||||
import { getLines } from "../../services/factoryBuilder/lines/getLinesApi";
|
||||
import * as THREE from "three";
|
||||
import { useActiveLayer, useDeletedLines, useNewLines, useToggleView } from "../../store/store";
|
||||
import objectLinesToArray from "../scene/geomentries/lines/lineConvertions/objectLinesToArray";
|
||||
import { Html } from "@react-three/drei";
|
||||
|
||||
|
||||
const DistanceText = () => {
|
||||
const [lines, setLines] = useState([]);
|
||||
const { activeLayer } = useActiveLayer();
|
||||
const { toggleView } = useToggleView();
|
||||
const { newLines, setNewLines } = useNewLines();
|
||||
const { deletedLines, setDeletedLines } = useDeletedLines();
|
||||
|
||||
useEffect(() => {
|
||||
const email = localStorage.getItem('email')
|
||||
const organization = (email.split("@")[1]).split(".")[0];
|
||||
|
||||
getLines(organization).then((data) => {
|
||||
data = objectLinesToArray(data);
|
||||
|
||||
const lines = data.filter(line => line[0][2] === activeLayer)
|
||||
.map(line => {
|
||||
const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z);
|
||||
const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z);
|
||||
const distance = point1.distanceTo(point2);
|
||||
const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2);
|
||||
return {
|
||||
distance: distance.toFixed(1),
|
||||
position: midpoint,
|
||||
userData: line,
|
||||
layer: activeLayer,
|
||||
};
|
||||
});
|
||||
setLines(lines)
|
||||
})
|
||||
}, [activeLayer])
|
||||
|
||||
useEffect(() => {
|
||||
if (newLines.length > 0) {
|
||||
if (newLines[0][0][2] !== activeLayer ) return;
|
||||
const newLinesData = newLines.map((line) => {
|
||||
const point1 = new THREE.Vector3(line[0][0].x, line[0][0].y, line[0][0].z);
|
||||
const point2 = new THREE.Vector3(line[1][0].x, line[1][0].y, line[1][0].z);
|
||||
const distance = point1.distanceTo(point2);
|
||||
const midpoint = new THREE.Vector3().addVectors(point1, point2).divideScalar(2);
|
||||
|
||||
return {
|
||||
distance: distance.toFixed(1),
|
||||
position: midpoint,
|
||||
userData: line,
|
||||
layer: activeLayer,
|
||||
};
|
||||
});
|
||||
setLines((prevLines) => [...prevLines, ...newLinesData]);
|
||||
setNewLines([]);
|
||||
}
|
||||
}, [newLines, activeLayer]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (deletedLines.length > 0) {
|
||||
setLines((prevLines) =>
|
||||
prevLines.filter(
|
||||
(line) => !deletedLines.some((deletedLine) => deletedLine[0][1] === line.userData[0][1] && deletedLine[1][1] === line.userData[1][1])
|
||||
)
|
||||
);
|
||||
setDeletedLines([]);
|
||||
}
|
||||
}, [deletedLines]);
|
||||
|
||||
return (
|
||||
<>
|
||||
{toggleView && (
|
||||
<group name='Distance_Text'>
|
||||
{lines.map((text) => (
|
||||
<Html key={`${text.userData[0][1]}_${text.userData[1][1]}`} transform sprite userData={text.userData} scale={5} position={[text.position.x, 1, text.position.z]} style={{ pointerEvents: 'none' }} >
|
||||
<div key={`${text.userData[0][1]}_${text.userData[1][1]}`} className={`Distance line-${text.userData[0][1]}_${text.userData[1][1]}_${text.layer}`} >{text.distance} m</div>
|
||||
</Html>
|
||||
))}
|
||||
</group>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
export default DistanceText;
|
||||
42
app/src/components/ui/3d-ui/functions/updateDistanceText.ts
Normal file
42
app/src/components/ui/3d-ui/functions/updateDistanceText.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import * as THREE from 'three';
|
||||
|
||||
import * as Types from "../../scene/world/worldTypes";
|
||||
|
||||
function updateDistanceText(
|
||||
scene: THREE.Scene,
|
||||
floorPlanGroupLine: Types.RefGroup,
|
||||
affectedLines: Types.NumberArray
|
||||
): void {
|
||||
|
||||
////////// Updating the Distance Texts of the lines that are affected during drag //////////
|
||||
|
||||
const DistanceGroup = scene.children.find((child) => child.name === "Distance_Text") as THREE.Group;
|
||||
|
||||
affectedLines.forEach((lineIndex) => {
|
||||
const mesh = floorPlanGroupLine.current.children[lineIndex] as THREE.Mesh;
|
||||
const linePoints = mesh.userData.linePoints;
|
||||
|
||||
if (linePoints) {
|
||||
const distance = linePoints[0][0].distanceTo(linePoints[1][0]).toFixed(1);
|
||||
const position = new THREE.Vector3().addVectors(linePoints[0][0], linePoints[1][0]).divideScalar(2);
|
||||
|
||||
if (!DistanceGroup || !linePoints) {
|
||||
return
|
||||
}
|
||||
|
||||
DistanceGroup.children.forEach((text) => {
|
||||
const textMesh = text as THREE.Mesh;
|
||||
if (textMesh.userData[0][1] === linePoints[0][1] && textMesh.userData[1][1] === linePoints[1][1]) {
|
||||
textMesh.position.set(position.x, 1, position.z);
|
||||
const className = `Distance line-${textMesh.userData[0][1]}_${textMesh.userData[1][1]}_${linePoints[0][2]}`;
|
||||
const element = document.getElementsByClassName(className)[0] as HTMLElement;
|
||||
if (element) {
|
||||
element.innerHTML = `${distance} m`;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export default updateDistanceText;
|
||||
39
app/src/components/ui/3d-ui/referenceDistanceText.jsx
Normal file
39
app/src/components/ui/3d-ui/referenceDistanceText.jsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import * as THREE from 'three';
|
||||
import { Html } from '@react-three/drei';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useActiveLayer } from '../../store/store';
|
||||
|
||||
const ReferenceDistanceText = ({ line }) => {
|
||||
const [text, setTexts] = useState(null);
|
||||
const { activeLayer } = useActiveLayer();
|
||||
|
||||
useEffect(() => {
|
||||
if (line === undefined || line.parent === null) {
|
||||
setTexts(null);
|
||||
return;
|
||||
}
|
||||
const distance = line.userData.linePoints.cursorPosition.distanceTo(line.userData.linePoints.startPoint);
|
||||
const midpoint = new THREE.Vector3().addVectors(line.userData.linePoints.cursorPosition, line.userData.linePoints.startPoint).divideScalar(2);
|
||||
const newTexts = {
|
||||
distance: distance.toFixed(1),
|
||||
position: midpoint,
|
||||
userData: line,
|
||||
layer: activeLayer
|
||||
};
|
||||
setTexts(newTexts);
|
||||
});
|
||||
|
||||
return (
|
||||
<group name='Reference_Distance_Text'>
|
||||
<mesh>
|
||||
{text !== null &&
|
||||
< Html transform sprite key={text.length} userData={text.userData} scale={5} position={[text.position.x, 1, text.position.z]} style={{ pointerEvents: 'none' }}>
|
||||
<div className={`Reference_Distance line-${text.userData.userData}`}>{text.distance} m</div>
|
||||
</Html>
|
||||
}
|
||||
</mesh>
|
||||
</group >
|
||||
);
|
||||
};
|
||||
|
||||
export default ReferenceDistanceText;
|
||||
23
app/src/components/ui/inputs/EyeDropInput.tsx
Normal file
23
app/src/components/ui/inputs/EyeDropInput.tsx
Normal file
@@ -0,0 +1,23 @@
|
||||
import React from "react";
|
||||
import RegularDropDown from "./RegularDropDown";
|
||||
import { EyeDroperIcon } from "../../icons/ExportCommonIcons";
|
||||
|
||||
const EyeDropInput: React.FC = () => {
|
||||
return (
|
||||
<div className="eye-dropper-input-container">
|
||||
<div className="label">Object</div>
|
||||
<div className="input-container">
|
||||
<RegularDropDown
|
||||
header="select object"
|
||||
options={[]}
|
||||
onSelect={() => {}}
|
||||
/>
|
||||
<div className="eye-picker-button">
|
||||
<EyeDroperIcon isActive={false} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EyeDropInput;
|
||||
69
app/src/components/ui/inputs/InputRange.tsx
Normal file
69
app/src/components/ui/inputs/InputRange.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
interface InputToggleProps {
|
||||
label: string; // Represents the toggle state (on/off)
|
||||
min?: number;
|
||||
max?: number;
|
||||
onClick?: () => void; // Function to handle toggle clicks
|
||||
onChange?: (value: number) => void; // Function to handle toggle clicks
|
||||
disabled?: boolean;
|
||||
value?: number;
|
||||
}
|
||||
|
||||
const InputRange: React.FC<InputToggleProps> = ({
|
||||
label,
|
||||
onClick,
|
||||
onChange,
|
||||
min = 0,
|
||||
max = 10,
|
||||
disabled,
|
||||
value = 5,
|
||||
}) => {
|
||||
const [rangeValue, setRangeValue] = useState<number>(value);
|
||||
|
||||
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const newValue = parseInt(e.target.value); // Parse the value to an integer
|
||||
setRangeValue(newValue); // Update the local state
|
||||
|
||||
if (onChange) {
|
||||
onChange(newValue); // Call the onChange function if it exists
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
setRangeValue(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className="input-range-container">
|
||||
<label
|
||||
htmlFor={`range-input ${value}`}
|
||||
className="label"
|
||||
onClick={onClick}
|
||||
>
|
||||
{label}
|
||||
</label>
|
||||
<div className="input-container">
|
||||
<input
|
||||
id={`range-input ${value}`}
|
||||
type="range"
|
||||
min={min}
|
||||
max={max}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
value={rangeValue}
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
min={min}
|
||||
className="input-value"
|
||||
max={max}
|
||||
value={rangeValue}
|
||||
onChange={handleChange}
|
||||
disabled={disabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputRange;
|
||||
51
app/src/components/ui/inputs/InputToggle.tsx
Normal file
51
app/src/components/ui/inputs/InputToggle.tsx
Normal file
@@ -0,0 +1,51 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
|
||||
interface InputToggleProps {
|
||||
label: string; // Represents the toggle state (on/off)
|
||||
onClick?: () => void; // Function to handle toggle clicks
|
||||
value?: boolean;
|
||||
inputKey: string;
|
||||
}
|
||||
|
||||
const InputToggle: React.FC<InputToggleProps> = ({
|
||||
label,
|
||||
onClick,
|
||||
value = false,
|
||||
inputKey,
|
||||
}) => {
|
||||
const [activeValue, setActiveValue] = useState<boolean>(value);
|
||||
|
||||
function handleOnClick() {
|
||||
setActiveValue(!activeValue);
|
||||
if (onClick) onClick();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setActiveValue(value);
|
||||
}, [value]);
|
||||
|
||||
return (
|
||||
<div className="input-toggle-container">
|
||||
<label htmlFor={`toogle-input-${inputKey}`} className="label">
|
||||
{label}
|
||||
</label>
|
||||
<div className={"check-box"} onClick={handleOnClick}>
|
||||
<div
|
||||
className="check-box-style"
|
||||
style={{
|
||||
left: activeValue ? "50%" : "2px",
|
||||
background: activeValue ? "" : "var(--text-disabled)",
|
||||
}}
|
||||
></div>
|
||||
<input
|
||||
type="checkbox"
|
||||
name=""
|
||||
id={`toogle-input-${inputKey}`}
|
||||
defaultChecked={value}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InputToggle;
|
||||
@@ -1,10 +1,14 @@
|
||||
import React, { useState } from "react";
|
||||
import RenameInput from "./RenameInput";
|
||||
|
||||
type InputWithDropDownProps = {
|
||||
label: string;
|
||||
value: string;
|
||||
options?: string[]; // Array of dropdown options
|
||||
activeOption?: string; // The currently active dropdown option
|
||||
onClick?: () => void;
|
||||
onChange: (newValue: string) => void;
|
||||
editableLabel?: boolean;
|
||||
};
|
||||
|
||||
const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
@@ -12,6 +16,9 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
value,
|
||||
options,
|
||||
activeOption,
|
||||
onClick,
|
||||
onChange,
|
||||
editableLabel = false,
|
||||
}) => {
|
||||
const separatedWords = label
|
||||
.split(/(?=[A-Z])/)
|
||||
@@ -22,29 +29,45 @@ const InputWithDropDown: React.FC<InputWithDropDownProps> = ({
|
||||
|
||||
return (
|
||||
<div className="value-field-container">
|
||||
<label htmlFor={separatedWords} className="label">
|
||||
{label}
|
||||
</label>
|
||||
{editableLabel ? (
|
||||
<RenameInput value={label} />
|
||||
) : (
|
||||
<label htmlFor={separatedWords} className="label">
|
||||
{label}
|
||||
</label>
|
||||
)}
|
||||
<div className="input default" id={separatedWords}>
|
||||
<input type="text" defaultValue={value} />
|
||||
|
||||
<div
|
||||
className="dropdown"
|
||||
onClick={() => {
|
||||
setOpenDropdown(true);
|
||||
<input
|
||||
type="text"
|
||||
defaultValue={value}
|
||||
onChange={(e) => {
|
||||
onChange(e.target.value);
|
||||
}}
|
||||
>
|
||||
<div className="active-option">{activeOption}</div>
|
||||
{options && openDropdown && (
|
||||
<div className="dropdown-options-list">
|
||||
{options.map((option, index) => (
|
||||
<div key={index} className={"dropdown-option"}>
|
||||
{option}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
/>
|
||||
|
||||
{activeOption && (
|
||||
<div
|
||||
className="dropdown"
|
||||
onClick={() => {
|
||||
setOpenDropdown(true);
|
||||
}}
|
||||
>
|
||||
<div className="active-option">{activeOption}</div>
|
||||
{options && openDropdown && (
|
||||
<div className="dropdown-options-list">
|
||||
{options.map((option, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={"dropdown-option"}
|
||||
onClick={onClick}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
26
app/src/components/ui/inputs/LabledButton.tsx
Normal file
26
app/src/components/ui/inputs/LabledButton.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from "react";
|
||||
|
||||
interface LabeledButtonProps {
|
||||
label: string; // Label for the button
|
||||
onClick?: () => void; // Function to call when the button is clicked
|
||||
disabled?: boolean; // Optional prop to disable the button
|
||||
value?: string;
|
||||
}
|
||||
|
||||
const LabeledButton: React.FC<LabeledButtonProps> = ({
|
||||
label,
|
||||
onClick,
|
||||
disabled = false,
|
||||
value = "Click here",
|
||||
}) => {
|
||||
return (
|
||||
<div className="labeled-button-container">
|
||||
<div className="label">{label}</div>
|
||||
<button className="button" onClick={onClick} disabled={disabled}>
|
||||
{value}
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default LabeledButton;
|
||||
@@ -20,6 +20,7 @@ const LabledDropdown: React.FC<LabledDropdownProps> = ({ defaultOption, options
|
||||
header={activeOption} // Display the current active option
|
||||
options={options} // Use the options from props
|
||||
onSelect={handleSelect} // Handle option selection
|
||||
search = {false}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
||||
71
app/src/components/ui/inputs/MultiEmailInvite.tsx
Normal file
71
app/src/components/ui/inputs/MultiEmailInvite.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React, { useState } from "react";
|
||||
|
||||
const MultiEmailInvite: React.FC = () => {
|
||||
const [emails, setEmails] = useState<string[]>([]);
|
||||
const [inputValue, setInputValue] = useState("");
|
||||
|
||||
const handleAddEmail = () => {
|
||||
const trimmedEmail = inputValue.trim();
|
||||
|
||||
// Validate email
|
||||
if (!trimmedEmail || !validateEmail(trimmedEmail)) {
|
||||
alert("Please enter a valid email address.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check for duplicates
|
||||
if (emails.includes(trimmedEmail)) {
|
||||
alert("This email has already been added.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Add email to the list
|
||||
setEmails([...emails, trimmedEmail]);
|
||||
setInputValue(""); // Clear the input field after adding
|
||||
};
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
|
||||
if (e.key === "Enter" || e.key === ",") {
|
||||
e.preventDefault();
|
||||
handleAddEmail();
|
||||
}
|
||||
};
|
||||
|
||||
const handleRemoveEmail = (emailToRemove: string) => {
|
||||
setEmails(emails.filter((email) => email !== emailToRemove));
|
||||
};
|
||||
|
||||
const validateEmail = (email: string) => {
|
||||
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
return emailRegex.test(email);
|
||||
};
|
||||
|
||||
const [inputFocus, setInputFocus] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="multi-email-invite-input-container">
|
||||
<div className={`multi-email-invite-input${inputFocus ? " active" : ""}`}>
|
||||
{emails.map((email, index) => (
|
||||
<div key={index} className="entered-emails">
|
||||
{email}
|
||||
<span onClick={() => handleRemoveEmail(email)}>×</span>
|
||||
</div>
|
||||
))}
|
||||
<input
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={(e) => setInputValue(e.target.value)}
|
||||
onFocus={() => setInputFocus(true)}
|
||||
onBlur={() => setInputFocus(false)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder="Enter email and press Enter or comma"
|
||||
/>
|
||||
</div>
|
||||
<div onClick={handleAddEmail} className="invite-button">
|
||||
Invite
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MultiEmailInvite;
|
||||
@@ -4,53 +4,81 @@ interface DropdownProps {
|
||||
header: string;
|
||||
options: string[];
|
||||
onSelect: (option: string) => void;
|
||||
search?: boolean;
|
||||
onClick?: () => void;
|
||||
onChange?: () => void;
|
||||
}
|
||||
|
||||
const RegularDropDown: React.FC<DropdownProps> = ({
|
||||
header,
|
||||
options,
|
||||
onSelect,
|
||||
search = true,
|
||||
onClick,
|
||||
onChange,
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [selectedOption, setSelectedOption] = useState<string | null>(null);
|
||||
const dropdownRef = useRef<HTMLDivElement>(null); // Create a ref for the dropdown container
|
||||
const [searchTerm, setSearchTerm] = useState(""); // State to store search term
|
||||
const [filteredOptions, setFilteredOptions] = useState<string[]>(options); // State for filtered options
|
||||
const dropdownRef = useRef<HTMLDivElement>(null); // Ref for the dropdown container
|
||||
|
||||
// Reset selectedOption when the dropdown closes
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
setSelectedOption(null); // Clear local state when the dropdown closes
|
||||
setSelectedOption(null);
|
||||
setSearchTerm(""); // Clear the search term when the dropdown closes
|
||||
setFilteredOptions(options); // Reset filtered options when the dropdown closes
|
||||
}
|
||||
}, [isOpen]);
|
||||
}, [isOpen, options]);
|
||||
|
||||
// Reset selectedOption when the header prop changes
|
||||
useEffect(() => {
|
||||
setSelectedOption(null); // Ensure the dropdown reflects the updated header
|
||||
}, [header]);
|
||||
setSelectedOption(null);
|
||||
setSearchTerm(""); // Reset search term if header changes
|
||||
setFilteredOptions(options); // Reset options if header changes
|
||||
}, [header, options]);
|
||||
|
||||
// Close dropdown if clicked outside
|
||||
useEffect(() => {
|
||||
const handleClickOutside = (event: MouseEvent) => {
|
||||
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
|
||||
setIsOpen(false); // Close the dropdown if clicked outside
|
||||
if (
|
||||
dropdownRef.current &&
|
||||
!dropdownRef.current.contains(event.target as Node)
|
||||
) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
};
|
||||
|
||||
document.addEventListener("click", handleClickOutside);
|
||||
|
||||
// Cleanup the event listener on component unmount
|
||||
return () => {
|
||||
document.removeEventListener("click", handleClickOutside);
|
||||
};
|
||||
}, []);
|
||||
|
||||
// Toggle the dropdown
|
||||
const toggleDropdown = () => {
|
||||
setIsOpen((prev) => !prev);
|
||||
};
|
||||
|
||||
// Handle option selection
|
||||
const handleOptionClick = (option: string) => {
|
||||
setSelectedOption(option);
|
||||
onSelect(option); // Call the onSelect function passed from the parent
|
||||
setIsOpen(false); // Close the dropdown after selection
|
||||
onSelect(option);
|
||||
setIsOpen(false);
|
||||
};
|
||||
|
||||
// Handle search input change
|
||||
const handleSearchChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const term = event.target.value;
|
||||
setSearchTerm(term);
|
||||
|
||||
// Filter options based on the search term
|
||||
const filtered = options.filter((option) =>
|
||||
option.toLowerCase().includes(term.toLowerCase())
|
||||
);
|
||||
setFilteredOptions(filtered);
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -64,15 +92,32 @@ const RegularDropDown: React.FC<DropdownProps> = ({
|
||||
{/* Dropdown Options */}
|
||||
{isOpen && (
|
||||
<div className="dropdown-options">
|
||||
{options.map((option, index) => (
|
||||
<div
|
||||
className="option"
|
||||
key={index}
|
||||
onClick={() => handleOptionClick(option)}
|
||||
>
|
||||
{option}
|
||||
{/* Search Bar */}
|
||||
{search && (
|
||||
<div className="dropdown-search">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search..."
|
||||
value={searchTerm}
|
||||
onChange={handleSearchChange}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
)}
|
||||
|
||||
{/* Filtered Options */}
|
||||
{filteredOptions.length > 0 ? (
|
||||
filteredOptions.map((option, index) => (
|
||||
<div
|
||||
className="option"
|
||||
key={index}
|
||||
onClick={() => handleOptionClick(option)}
|
||||
>
|
||||
{option}
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<div className="no-options">No options found</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -81,12 +81,6 @@ const DropDownList: React.FC<DropDownListProps> = ({
|
||||
showAddIcon={false}
|
||||
items={[]}
|
||||
/>
|
||||
<DropDownList
|
||||
value="Paths"
|
||||
showKebabMenu={false}
|
||||
showAddIcon={false}
|
||||
items={[]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user