Components
Hooks
Utils
useHeadlessSelectHook
The useHeadlessSelectHook
is a custom hook that provides a set of state variables and functions for managing the behavior of a headless select component in React applications.
Parameters
The useHeadlessSelectHook
accepts an options object with the following properties:
options
(array): An array of options for the select. Each option is an object with key-value pairs representing the option's properties.valueKey
(string): The key in each option object that represents the unique identifier for the option. It is used to determine if an option is selected or not.onChange
(function): An optional callback function invoked when the selected option(s) change. It receives the selected option(s) as an argument.filterFunction
(function): An optional custom filter function used to filter the options based on the query entered by the user. It takes an option object and the query as arguments and should return a boolean indicating whether the option matches the query or not.clearQuery
(boolean): If set totrue
, the query is cleared when the select is closed.defaultSelected
(array): An optional array of option objects representing the initially selected option(s). This value is used as the initial state forselectedValues
.defaultOpen
(boolean): An optional boolean indicating whether the select should be initially open or not.defaultQuery
(string): An optional string representing the initial query value for filtering the options.refresh
(any): An optional value used to trigger a refresh of the select options or behavior when it changes.
Return Value
The useHeadlessSelectHook
returns an object with the following properties and functions:
open
(boolean): A boolean representing the current open/close state of the select.setOpen
(function): A function to update the open/close state of the select.query
(string): The current query value for filtering the options.setQuery
(function): A function to update the query value.selectedValues
(array): An array of option objects representing the currently selected option(s).setSelectedValues
(function): A function to update the selected option(s).filteredOptions
(array): An array of option objects representing the filtered options based on the current query.
Usage
To use the useHeadlessSelectHook
, import it and invoke it within a functional component. It returns an object containing the state variables and functions needed to control the headless select component.
Example usage:
import { useHeadlessSelectHook } from './hooks';
// Define options for the select
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
// ...
];
// Define a change handler function
const handleChange = (selectedOption) => {
console.log('Selected option:', selectedOption);
};
// Use the useHeadlessSelectHook
const MyComponent = () => {
const {
open,
setOpen,
query,
setQuery,
selectedValues,
setSelectedValues,
filteredOptions,
setFilteredOptions,
addOrRemove,
outsideClickRef,
} = useHeadlessSelectHook({
options,
valueKey: 'value',
onChange: handleChange,
defaultSelected: [],
defaultOpen: false,
defaultQuery: '',
refresh: '',
});
// ... render the select component and use the hook values and functions ...
};
Ten, Three
import React from "react";
import { useHeadlessSelectHook } from "@locoworks/reusejs-toolkit-react-hooks";
const NoOptionsRenderer = () => {
return <div className="flex justify-center my-2">No Options found</div>;
};
export interface SelectedOptionProps {
index: any;
filteredOptions: any;
addOrRemove: any;
multiple: boolean;
option: any;
}
const SelectedOption: React.FC<SelectedOptionProps> = ({
index,
filteredOptions,
addOrRemove,
multiple,
option,
}) => {
return (
<div
className={
"bg-green-100 hover:bg-green-500 hover:text-white hover:font-bold px-2 py-1 flex justify-between w-full" +
(index === filteredOptions.length - 1
? ""
: "border-b border-slate-300")
}
onClick={() => addOrRemove(multiple, option)}
key={"selected" + option.label + option.value}
>
<label>{option.label}</label>
<label className="font-bold">{option.value}</label>
</div>
);
};
const MemoizedSelectedOption = React.memo(SelectedOption);
const UnSelectedOption: React.FC<SelectedOptionProps> = ({
index,
filteredOptions,
addOrRemove,
multiple,
option,
}) => {
return (
<div
className={
"hover:bg-blue-500 hover:text-white hover:font-bold px-2 py-1 flex justify-between w-full" +
(index === filteredOptions.length - 1
? ""
: "border-b border-slate-300")
}
key={option.value + option.label}
onClick={() => addOrRemove(multiple, option)}
>
<label>{option.label}</label>
<label className="font-bold">{option.value}</label>
</div>
);
};
const MemoizedUnSelectedOption = React.memo(UnSelectedOption);
const HeadlessSelectSample: React.FC = () => {
const options = [
{ label: "One", value: "1" },
{ label: "Two", value: "2" },
{ label: "Three", value: "3" },
{ label: "Four", value: "4" },
{ label: "Five", value: "5" },
{ label: "Six", value: "6" },
{ label: "Seven", value: "7" },
{ label: "Eight", value: "8" },
{ label: "Nine", value: "9" },
{ label: "Ten", value: "10" },
];
const valueKey = "value";
const multiple = true;
const filterFunction = (ele: any, query: string) => {
return ele.label.toLowerCase().includes(query.toLowerCase());
};
const {
open,
setOpen,
query,
setQuery,
selectedValues,
// setSelectedValues,
filteredOptions,
// setFilteredOptions,
addOrRemove,
outsideClickRef,
} = useHeadlessSelectHook({
options,
valueKey,
// onChange,
filterFunction,
clearQuery: true,
defaultSelected: [
{ label: "Ten", value: "10" },
{ label: "Three", value: "3" },
],
// defaultOpen,
// defaultQuery,
});
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<div className="flex flex-col w-full px-4">
{/* {header && header} */}
<div>Select</div>
<div className="relative" ref={outsideClickRef}>
{!open ? (
<div
className="bg-white border border-black rounded px-4 flex items-center w-48 h-10 cursor-pointer"
onClick={() => {
setOpen((prev: any) => !prev);
}}
>
<p className="overflow-hidden text-ellipsis whitespace-nowrap">
{selectedValues?.length !== 0
? selectedValues.map((option: any) => option.label).join(", ")
: "Open Dropdown"}
</p>
</div>
) : (
<input
className="form-input bg-white border border-black rounded px-4 flex items-center w-48 h-10 cursor-pointer"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
)}
{open && (
<div className="absolute top-10 bg-white rounded px-3 py-2 border border-slate-100 w-1/2 max-h-48 overflow-scroll">
{/* {searchFilter && (
<input
className=" sticky top-0 w-full rounded bg-slate-200 px-2"
value={query}
onChange={(e) => setQuery(e.target.value)}
/>
)} */}
{filteredOptions?.map((option: any, index: number) => {
if (
selectedValues
.map((val: any) => val[valueKey])
.includes(option[valueKey])
) {
return (
<MemoizedSelectedOption
key={"selected" + index}
index={index}
filteredOptions={filteredOptions}
addOrRemove={addOrRemove}
multiple={multiple}
option={option}
/>
);
}
return (
<MemoizedUnSelectedOption
key={"selected" + index}
index={index}
filteredOptions={filteredOptions}
addOrRemove={addOrRemove}
multiple={multiple}
option={option}
/>
);
})}
{filteredOptions.length === 0 && <NoOptionsRenderer />}
</div>
)}
</div>
</div>
</div>
);
};
export default HeadlessSelectSample;
ReuseSample
ReuseSelectDropDown
The ReuseSelectDropDown
component is a reusable dropdown select component in React that provides a customizable and headless dropdown select functionality.
Props
The ReuseSelectDropDown
component accepts the following props:
-
options
(required, array): An array of objects representing the selectable options for the dropdown. Each object should contain properties corresponding to the option's attributes. -
optionsRenderer
(optional, function): A custom renderer function that overrides the default rendering of the options. It receives the following parameters:selectedValues
(array): An array of selected option objects.filteredOptions
(array): An array of filtered option objects.addOrRemove
(function): A function to add or remove an option from the selected values.setQuery
(function): A function to update the query for filtering options. It accepts a new query as an argument.
The
optionsRenderer
function should return a React node representing the custom options rendering. -
noOptionsRenderer
(optional, React node): A custom component or message to display when no options are available or when the filtering does not yield any results. -
multiple
(optional, boolean): A flag indicating whether multiple options can be selected. By default, this is set tofalse
, meaning only a single option can be selected. -
defaultSelected
(optional, array): An array of objects representing the initially selected option(s). Each object should correspond to an option from theoptions
array. -
header
(optional, React node): Additional content to be displayed above the dropdown select component. -
footer
(optional, React node): Additional content to be displayed below the dropdown select component. -
onChange
(optional, function): A callback function invoked when the selected option(s) change. -
valueKey
(required, string): The key in each option object that represents the unique identifier for the option. -
displayKey
(required, string): The key in each option object that represents the value to be displayed as the option label. -
filterFunction
(optional, function): A custom filter function used to filter the options based on the query entered by the user. It takes an option object and the query as arguments and should return a boolean indicating whether the option matches the query or not. -
clearQuery
(optional, boolean): A flag indicating whether the query should be cleared when the dropdown is closed. By default, this is set totrue
. -
defaultOpen
(optional, boolean): A flag indicating whether the dropdown should be initially open. By default, this is set tofalse
. -
defaultQuery
(optional, string): The initial query value for filtering the options. -
enableSearch
(optional, boolean): A flag indicating whether to enable the search input within the dropdown. By default, this is set tofalse
. -
dropDownText
(optional, string): The text to be displayed in the dropdown button when no option is selected. By default, this is set to "Open Dropdown". -
optionsWrapper
(optional, string or CSSProperties): Additional CSS classes or inline styles to be applied to the options wrapper element. -
selectWrapper
(optional, string or CSSProperties): Additional CSS classes or inline styles to be applied to the select wrapper element. -
selectButtonStyles
(optional, string or CSSProperties): Additional CSS classes or inline styles to be applied to the select button element. -
selectButtonOverflowWrappper
(optional, string or CSSProperties): Additional CSS classes or inline styles to
be applied to the select button's overflow wrapper element.
-
inputStyles
(optional, string or CSSProperties): Additional CSS classes or inline styles to be applied to the search input element. -
refresh
(optional, any): A value used to trigger a refresh of the dropdown options or behavior when it changes.
Usage
import ReuseSelectDropDown from "./ReuseSelectDropDown";
// Example options array
const options = [
{ value: 'option1', label: 'Option 1' },
{ value: 'option2', label: 'Option 2' },
// ...
];
// Example usage
const MyComponent = () => {
const handleChange = () => {
// Handle selected options change
};
return (
<ReuseSelectDropDown
options={options}
optionsRenderer={(selectedValues, filteredOptions, addOrRemove, setQuery) => {
// Custom options rendering logic
return (
// Return the custom options rendering
);
}}
// Other props...
/>
);
};
This is a basic usage example of the ReuseSelectDropDown
component. You can customize the appearance and behavior of the component by providing different props and using the available customization options.
Open Dropdown
import React, { useState } from "react";
import { ReuseSelectDropdown } from "@locoworks/reusejs-react-select-dropdown";
const ReuseSample = () => {
const option3 = [
{
fname: "John",
lname: "Doe",
id: "1001",
age: "25",
},
{
fname: "Alice",
lname: "Smith",
id: "1002",
age: "30",
},
{
fname: "Michael",
lname: "Johnson",
id: "1003",
age: "40",
},
{
fname: "Emily",
lname: "Brown",
id: "1004",
age: "22",
},
{
fname: "David",
lname: "Miller",
id: "1005",
age: "35",
},
{
fname: "Sophia",
lname: "Wilson",
id: "1006",
age: "28",
},
{
fname: "Jacob",
lname: "Taylor",
id: "1007",
age: "31",
},
{
fname: "Olivia",
lname: "Anderson",
id: "1008",
age: "27",
},
{
fname: "Ethan",
lname: "Clark",
id: "1009",
age: "33",
},
{
fname: "Ava",
lname: "White",
id: "1010",
age: "29",
},
];
const optionsChanged = option3.map((ele) => {
return { ...ele, label: ele.fname + " " + ele.lname, value: ele.id };
});
const [refresher, setRefresher] = useState(new Date());
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<button
onClick={() => {
setRefresher(new Date());
}}
>
Switch
</button>
<ReuseSelectDropdown
options={optionsChanged}
valueKey={"id"}
displayKey={"fname"}
multiple
enableSearch
refresh={refresher}
onChange={(selected) => {
console.log("Selected Values Are>>>", selected);
}}
/>
</div>
);
};
export default ReuseSample;
ForwardRefSelectDropdown
Open Dropdown
import React, { useEffect, useRef, useState, Ref } from "react";
import { ReuseSelectDropdown } from "@locoworks/reusejs-react-select-dropdown";
const ForwardRefInputGroup = () => {
const selectRef: any = useRef<Ref<HTMLInputElement> | undefined>(null);
useEffect(() => {
if (selectRef.current) {
const current = selectRef.current;
const inputElement = current.childNodes[0]
.childNodes[0] as HTMLInputElement;
inputElement.style.border = "solid blue 3px";
}
}, []);
const option3 = [
{
fname: "John",
lname: "Doe",
id: "1001",
age: "25",
},
{
fname: "Alice",
lname: "Smith",
id: "1002",
age: "30",
},
{
fname: "Michael",
lname: "Johnson",
id: "1003",
age: "40",
},
{
fname: "Emily",
lname: "Brown",
id: "1004",
age: "22",
},
{
fname: "David",
lname: "Miller",
id: "1005",
age: "35",
},
{
fname: "Sophia",
lname: "Wilson",
id: "1006",
age: "28",
},
{
fname: "Jacob",
lname: "Taylor",
id: "1007",
age: "31",
},
{
fname: "Olivia",
lname: "Anderson",
id: "1008",
age: "27",
},
{
fname: "Ethan",
lname: "Clark",
id: "1009",
age: "33",
},
{
fname: "Ava",
lname: "White",
id: "1010",
age: "29",
},
];
const optionsChanged = option3.map((ele) => {
return { ...ele, label: ele.fname + " " + ele.lname, value: ele.id };
});
const [refresher, setRefresher] = useState(new Date());
return (
<div className="flex flex-col items-center gap-x-3 justify-center py-10 mt-10 border rounded bg-gray-50">
<button
onClick={() => {
setRefresher(new Date());
}}
>
Switch
</button>
<ReuseSelectDropdown
ref={selectRef}
options={optionsChanged}
valueKey={"id"}
displayKey={"fname"}
multiple
enableSearch
refresh={refresher}
/>
</div>
);
};
export default ForwardRefInputGroup;