first commit

This commit is contained in:
2025-03-25 11:47:41 +05:30
commit 61b3c4ee2c
211 changed files with 36430 additions and 0 deletions

View 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;

View 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;

View 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;

View File

@@ -0,0 +1,76 @@
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> = ({
label,
value,
options,
activeOption,
onClick,
onChange,
editableLabel = false,
}) => {
const separatedWords = label
.split(/(?=[A-Z])/)
.map((word) => word.trim())
.toString();
const [openDropdown, setOpenDropdown] = useState(false);
return (
<div className="value-field-container">
{editableLabel ? (
<RenameInput value={label} />
) : (
<label htmlFor={separatedWords} className="label">
{label}
</label>
)}
<div className="input default" id={separatedWords}>
<input
type="text"
defaultValue={value}
onChange={(e) => {
onChange(e.target.value);
}}
/>
{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>
);
};
export default InputWithDropDown;

View 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;

View File

@@ -0,0 +1,29 @@
import React, { useState } from "react";
import RegularDropDown from "./RegularDropDown";
type LabledDropdownProps = {
defaultOption: string; // Initial active option
options: string[]; // Array of dropdown options
};
const LabledDropdown: React.FC<LabledDropdownProps> = ({ defaultOption, options }) => {
const [activeOption, setActiveOption] = useState(defaultOption); // State for active option
const handleSelect = (option: string) => {
setActiveOption(option); // Update the active option state
};
return (
<div className="value-field-container">
<div className="label">Type</div>
<RegularDropDown
header={activeOption} // Display the current active option
options={options} // Use the options from props
onSelect={handleSelect} // Handle option selection
search = {false}
/>
</div>
);
};
export default LabledDropdown;

View 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)}>&times;</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;

View File

@@ -0,0 +1,141 @@
import React, { useState, useRef, useEffect } from "react";
// Dropdown Item Component
const DropdownItem = ({
label,
href,
onClick,
}: {
label: string;
href?: string;
onClick?: () => void;
}) => (
<a
href={href || "#"}
className="dropdown-item"
onClick={(e) => {
e.preventDefault();
onClick?.();
}}
>
{label}
</a>
);
// Nested Dropdown Component
const NestedDropdown = ({
label,
children,
onSelect,
}: {
label: string;
children: React.ReactNode;
onSelect: (selectedLabel: string) => void;
}) => {
const [open, setOpen] = useState(false);
return (
<div className="nested-dropdown">
{/* Dropdown Trigger */}
<div
className={`dropdown-trigger ${open ? "open" : ""}`}
onClick={() => setOpen(!open)} // Toggle submenu on click
>
{label} <span className="icon">{open ? "▼" : "▶"}</span>
</div>
{/* Submenu */}
{open && (
<div className="submenu">
{React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
// Clone the element and pass the `onSelect` prop only if it's expected
return React.cloneElement(child as React.ReactElement<any>, { onSelect });
}
return child; // Return non-element children as-is
})}
</div>
)}
</div>
);
};
// Recursive Function to Render Nested Data
const renderNestedData = (
data: Record<string, any>,
onSelect: (selectedLabel: string) => void
) => {
return Object.entries(data).map(([key, value]) => {
if (typeof value === "object" && !Array.isArray(value)) {
// If the value is an object, render it as a nested dropdown
return (
<NestedDropdown key={key} label={key} onSelect={onSelect}>
{renderNestedData(value, onSelect)}
</NestedDropdown>
);
} else if (Array.isArray(value)) {
// If the value is an array, render each item as a dropdown item
return value.map((item, index) => (
<DropdownItem key={index} label={item} onClick={() => onSelect(item)} />
));
} else {
// If the value is a simple string, render it as a dropdown item
return (
<DropdownItem key={key} label={value} onClick={() => onSelect(value)} />
);
}
});
};
// Main Multi-Level Dropdown Component
const MultiLevelDropdown = ({ data }: { data: Record<string, any> }) => {
const [open, setOpen] = useState(false);
const [selectedLabel, setSelectedLabel] = useState("Dropdown trigger");
const dropdownRef = useRef<HTMLDivElement>(null);
// Handle outer click to close the dropdown
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
setOpen(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => {
document.removeEventListener("mousedown", handleClickOutside);
};
}, []);
// Handle selection of an item
const handleSelect = (selectedLabel: string) => {
setSelectedLabel(selectedLabel); // Update the dropdown trigger text
setOpen(false); // Close the dropdown
};
return (
<div className="multi-level-dropdown" ref={dropdownRef}>
{/* Dropdown Trigger Button */}
<button
className={`dropdown-button ${open ? "open" : ""}`}
onClick={() => setOpen(!open)} // Toggle main menu on click
>
{selectedLabel} <span className="icon"></span>
</button>
{/* Dropdown Menu */}
{open && (
<div className="dropdown-menu">
<div className="dropdown-content">
{renderNestedData(data, handleSelect)}
</div>
</div>
)}
</div>
);
};
export default MultiLevelDropdown;

View File

@@ -0,0 +1,127 @@
import React, { useState, useEffect, useRef } from "react";
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 [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);
setSearchTerm(""); // Clear the search term when the dropdown closes
setFilteredOptions(options); // Reset filtered options when the dropdown closes
}
}, [isOpen, options]);
// Reset selectedOption when the header prop changes
useEffect(() => {
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);
}
};
document.addEventListener("click", handleClickOutside);
return () => {
document.removeEventListener("click", handleClickOutside);
};
}, []);
// Toggle the dropdown
const toggleDropdown = () => {
setIsOpen((prev) => !prev);
};
// Handle option selection
const handleOptionClick = (option: string) => {
setSelectedOption(option);
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 (
<div className="regularDropdown-container" ref={dropdownRef}>
{/* Dropdown Header */}
<div className="dropdown-header flex-sb" onClick={toggleDropdown}>
<div className="key">{selectedOption || header}</div>
<div className="icon"></div>
</div>
{/* Dropdown Options */}
{isOpen && (
<div className="dropdown-options">
{/* 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>
);
};
export default RegularDropDown;

View File

@@ -0,0 +1,59 @@
import React, { useState, useRef } from "react";
interface RenameInputProps {
value: string;
onRename?: (newText: string) => void;
}
const RenameInput: React.FC<RenameInputProps> = ({ value, onRename }) => {
const [isEditing, setIsEditing] = useState(false);
const [text, setText] = useState(value);
const inputRef = useRef<HTMLInputElement | null>(null);
const handleDoubleClick = () => {
setIsEditing(true);
setTimeout(() => inputRef.current?.focus(), 0); // Focus the input after rendering
};
const handleBlur = () => {
setIsEditing(false);
if (onRename) {
onRename(text);
}
};
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setText(e.target.value);
};
const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") {
setIsEditing(false);
if (onRename) {
onRename(text);
}
}
};
return (
<>
{isEditing ? (
<input
ref={inputRef}
type="text"
value={text}
onChange={handleChange}
onBlur={handleBlur}
onKeyDown={handleKeyDown}
className="rename-input"
/>
) : (
<span onDoubleClick={handleDoubleClick} className="input-value">
{text}
</span>
)}
</>
);
};
export default RenameInput;

View File

@@ -0,0 +1,67 @@
import React, { ChangeEvent, useState } from "react";
import { CloseIcon, SearchIcon } from "../../icons/ExportCommonIcons";
interface SearchProps {
value?: string; // The current value of the search input
placeholder?: string; // Placeholder text for the input
onChange: (value: string) => void; // Callback function to handle input changes
}
const Search: React.FC<SearchProps> = ({
value = "",
placeholder = "Search",
onChange,
}) => {
// State to track the input value and focus status
const [inputValue, setInputValue] = useState(value);
const [isFocused, setIsFocused] = useState(false);
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
const newValue = event.target.value;
setInputValue(newValue);
onChange(newValue); // Call the onChange prop with the new value
};
const handleClear = () => {
setInputValue("");
onChange(""); // Clear the input value
};
const handleFocus = () => {
setIsFocused(true); // Set focus state to true
};
const handleBlur = () => {
setIsFocused(false); // Set focus state to false
};
return (
<div className="search-wrapper">
<div
className={`search-container ${
isFocused || inputValue ? "active" : ""
}`}
>
<div className="icon-container">
<SearchIcon />
</div>
<input
type="text"
className="search-input"
value={inputValue}
placeholder={placeholder}
onChange={handleInputChange}
onFocus={handleFocus}
onBlur={handleBlur}
/>
{inputValue && (
<button className="clear-button" onClick={handleClear}>
<CloseIcon />
</button>
)}
</div>
</div>
);
};
export default Search;

View File

@@ -0,0 +1,31 @@
import React from "react";
interface ToggleHeaderProps {
options: string[]; // Array of strings representing the options
activeOption: string; // The currently active option
handleClick: (option: string) => void; // Function to handle click events
}
const ToggleHeader: React.FC<ToggleHeaderProps> = ({
options,
activeOption,
handleClick,
}) => {
return (
<div className="toggle-header-container">
{options.map((option, index) => (
<div
key={index}
className={`toggle-header-item ${
option === activeOption ? "active" : ""
}`}
onClick={() => handleClick(option)} // Call handleClick when an option is clicked
>
{option}
</div>
))}
</div>
);
};
export default ToggleHeader;