Input Dropdown คือ View ที่ใช้ในการรับค่าจากรายการที่กำหนดไว้
import { useEffect, useState } from "react";
import styled, { css } from "styled-components";
import useOutsideClick from "../../util/useOutsideClick";
import IconChevron from "../element/icon/IconChevron";
export default function InputDropdown({
onChange,
value, //"all"
dataList, //[{text:'All',value:'all'}] or //['all','none']
design = "outline",
width,
maxHeight = 200,
className,
backgroundColor,
borderRadius = "8px",
borderColor,
borderErrorColor = "var(--danger)",
importantColor = "var(--danger)",
backgroundDisabledColor = "#f5f5f5",
style,
isError,
disabled,
placeHolder = "select",
dropDownGap = 5,
label,
fontSize = "16px",
textTransform = "capitalize",
important,
}) {
const outerRef = useOutsideClick(() => setIsFocus(false));
const [isFocus, setIsFocus] = useState(false);
const [selectValue, setSelectValue] = useState(placeHolder);
const [listPosition, setListPosition] = useState();
useEffect(() => {
if (value) {
const findInit = dataList?.find((x) => x.value === value) || value;
setSelectValue(findInit?.text || findInit);
}
}, [value]);
const handleOnChange = (item) => {
setIsFocus(false);
setSelectValue(item.text || item || "");
if (onChange) {
onChange(item.value || item || "");
}
};
const handleClickDropdown = (e) => {
setIsFocus((prev) => !prev);
const globalMousePos = { y: e.clientY || 0, x: e.clientX || 0 };
const windowSize = {
height: e.view.innerHeight || 0,
width: e.view.innerWidth || 0,
};
if (globalMousePos.y + maxHeight < windowSize.height) {
setListPosition({
...listPosition,
top: outerRef.current.clientHeight + dropDownGap,
bottom: null,
});
} else {
setListPosition({
...listPosition,
bottom: outerRef.current.clientHeight + dropDownGap,
top: null,
});
}
};
return (
<Styled
className={className}
style={style}
$backgroundColor={backgroundColor}
$isFocus={isFocus}
$borderRadius={borderRadius}
$disabled={disabled}
$borderColor={borderColor}
$borderErrorColor={borderErrorColor}
$backgroundDisabledColor={backgroundDisabledColor}
$design={design}
$width={width}
$maxHeight={maxHeight}
$listPosition={listPosition}
$fontSize={fontSize}
$textTransform={textTransform}
$importantColor={importantColor}
>
{label && <small>{label}</small>}
{important && <div className="is-important">*</div>}
<div
ref={outerRef}
className={
"dropdown-inner " +
(isError ? " input-error" : "") +
(disabled ? " input-disabled" : "")
}
>
<div className="selected-wrp" onClick={handleClickDropdown}>
<span
className={
"select-text" + (selectValue == placeHolder ? " place-item" : "")
}
>
{selectValue}
</span>
<i className="icon-dropdown">
<IconChevron degree="270" width="7" />
</i>
</div>
{!disabled && isFocus && dataList && (
<ul className="list">
{dataList.map((item, index) => (
<li
className="item-li"
key={"item-" + index}
onClick={() => handleOnChange(item)}
>
{item?.text || item || ""}
</li>
))}
</ul>
)}
</div>
</Styled>
);
}
const Styled = styled.div`
position: relative;
display: inline-flex;
.is-important {
color: ${({ $importantColor }) => $importantColor};
position: absolute;
top: -14px;
right: -10px;
}
small {
margin-bottom: 5px;
font-weight: bold;
display: block;
}
.place-item {
color: var(--txt-normal-soft);
}
.dropdown-inner {
${({ $design }) => designStyles($design)}
border-radius: ${({ $borderRadius }) => $borderRadius};
position: relative;
display: inline-flex;
flex-direction: column;
user-select: none;
cursor: pointer;
width: ${({ $width }) => $width};
min-width: 200px;
color: var(--txt-normal);
font-size: ${({ $fontSize }) => $fontSize};
.list {
position: absolute;
margin: 0;
min-width: 200px;
width: ${({ $width }) => $width};
max-height: ${({ $maxHeight }) => $maxHeight + "px"};
z-index: 999;
list-style: none;
border-radius: ${({ $borderRadius }) => $borderRadius};
padding: 0;
top: ${({ $listPosition }) =>
$listPosition?.top ? $listPosition.top + "px" : null};
bottom: ${({ $listPosition }) =>
$listPosition?.bottom ? $listPosition.bottom + "px" : null};
left: 0;
overflow-y: auto;
}
.list li {
padding: 10px 12px;
text-transform: ${({ $textTransform }) => $textTransform};
display: flex;
}
.selected-wrp {
position: relative;
width: 100%;
padding: 12px;
}
.select-text {
margin-right: 10px;
display: block;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
text-transform: ${({ $textTransform }) => $textTransform};
}
.icon-dropdown {
position: absolute;
right: 12px;
top: 10px;
svg path {
stroke: var(--txt-normal-soft);
}
}
&.input-error {
border-color: ${({ $borderErrorColor }) => $borderErrorColor};
}
&.input-error .list {
border-color: ${({ $borderErrorColor }) => $borderErrorColor};
}
&.input-disabled {
background-color: ${({ $backgroundDisabledColor }) =>
$backgroundDisabledColor};
}
}
`;
const designStyles = (design) =>
({
solid: css`
background-color: ${({ $backgroundColor }) => $backgroundColor};
.list {
background-color: ${({ $backgroundColor }) => $backgroundColor};
}
`,
outline: css`
border: 1px solid ${({ $borderColor }) => $borderColor};
background-color: ${({ $backgroundColor }) => $backgroundColor};
.list {
border: 1px solid ${({ $borderColor }) => $borderColor};
background-color: ${({ $backgroundColor }) => $backgroundColor};
}
`,
}[design]);
import { useState } from "react";
import InputDropdown from "../../example/InputDropdown";
export default function TestView() {
const [dropdownValue, setDropdownValue] = useState("A");
return (
<div>
<InputDropdown
value={dropdownValue}
dataList={["A", "B"]}
onChange={(e) => setDropdownValue(e)}
/>
</div>
);
}
Property | Description | Type | Default |
---|---|---|---|
value | ค่าปัจจุบันของ dropdown | string | |
dataList | ชุดข้อมูล | array | |
design | รูปแบบดีไซน์ พื้นฐานของ view เช่น solid (มีสีพื้นหลัง), outline (มีเส้นขอบ) และ none (ไม่มีสีพื้นหลังและเส้นขอบ) | string | "outline" |
width | ความกว้างภายในเนื้อหาของ view | string | |
maxHeight | ส่วนสูงมากที่สุดของ dropdown box | number | 200 |
className | ใช้กำหนดลักษณะเฉพาะของ view | string | |
backgroundColor | สีพื้นหลังของ view | string | "var(--background)" |
borderRadius | ความโค้งมนของ view | string | "8px" |
borderColor | สีของเส้นขอบนอกสุดของ view | string | "var(--border)" |
borderErrorColor | สีของเส้นขอบนอกสุดของ view เมื่อ error | string | "var(--danger)" |
importantColor | สีดอกจันทร์แสดงความสำคัญ | string | "var(--danger)" |
backgroundDisabledColor | สีพื้นหลังของ view เมื่อทำการ diable | string | "#f5f5f5" |
style | inline style ของ view | CSSProperties | |
isError | กำหนดค่า true เมื่อต้องการแสดงกรอบสีแดง | boolean | |
disabled | เมื่อกำหนดค่า เป็น true จะไม่สามารถทำงานฟังก์ชัน | boolean | |
placeHolder | ข้อความตัวอย่าง | string | "select" |
dropDownGap | ระยะห่างระหว่าง select กับ dropdown | number | 5 |
label | คำอธิบายของ view | string | |
fontSize | ขนาดตัวอักษรของ view | string | "16px" |
textTransform | กำหนด design ของ text ใน view | string | "capitalize" |
important | กำหนดค่าเป็น true จะแสดงสัญลักษณ์ดอกจันทร์บน view | boolean | |
onChange | ฟังก์ชันจะทำงานเมื่อทำการเปลี่ยนค่า | function |