Input Tag คือ view ที่ใช้รับค่าชุดข้อมูลของ tag
import { useEffect, useRef, useState } from "react";
import styled, { css } from "styled-components";
import IconPlus from "../element/icon/IconPlus";
export default function InputTag({
value,
width = "100%",
onChange,
placeHolder,
design = "outline",
className,
style,
borderWidth = "1px",
borderColor = "var(--border)",
borderRadius = "8px",
backgroundColor = "var(--background-solid)",
fontSize = "16px",
label,
padding = "12px 12px 8px",
margin,
}) {
const [tags, setTags] = useState([]);
const inputRef = useRef();
useEffect(() => {
if (value && value.length >= 0) {
setTags([...value]);
}
}, [value]);
const removeTag = (i) => {
const newTags = [...tags];
newTags.splice(i, 1);
updateTags(newTags);
};
const inputKeyDown = (e) => {
const val = e.target.value;
if (e.keyCode == 32 || (e.keyCode == 13 && val)) {
if (tags.find((tag) => tag.toLowerCase() === val.toLowerCase())) {
return;
}
if (val) {
const tmpTrim = val?.trim();
updateTags([...tags, tmpTrim]);
inputRef.current.value = null;
}
}
};
const onBlurChange = (e) => {
const val = e.target.value;
if (val && tags.length == 0) {
setTags([val]);
inputRef.current.value = null;
if (onChange) {
onChange([val]);
}
} else if (val && tags.length > 0) {
const dubValue = tags.filter(
(item, index) => tags.indexOf(item) !== index
);
if (!dubValue) {
setTags([...tags, val]);
if (onChange) {
onChange([...tags, val]);
}
}
inputRef.current.value = null;
}
};
const updateTags = (tagValue) => {
if (onChange) {
onChange(tagValue);
}
setTags(tagValue);
};
return (
<Styled
className={className}
style={style}
$width={width}
$design={design}
$borderWidth={borderWidth}
$borderColor={borderColor}
$borderRadius={borderRadius}
$backgroundColor={backgroundColor}
$fontSize={fontSize}
$padding={padding}
$margin={margin}
>
{label && <small>{label}</small>}
<ul className={"tag-list"}>
{tags.map((tag, i) => (
<li key={"tag-" + i} className="li li-tag">
<span className="txt">{tag}</span>
<button
type="button"
className="remove-button"
onClick={() => {
removeTag(i);
}}
>
<IconPlus color="#fff" width="10px" />
</button>
</li>
))}
<li className={"li li-input"}>
<input
ref={inputRef}
placeholder={placeHolder || "Type Here"}
type="text"
onKeyDown={inputKeyDown}
onBlur={onBlurChange}
/>
</li>
</ul>
</Styled>
);
}
const Styled = styled.div`
${({ $design }) => designStyles($design)};
margin: ${({ $margin }) => $margin};
small {
margin-bottom: 5px;
font-weight: bold;
display: block;
}
.tag-list {
display: inline-flex;
flex-wrap: wrap;
margin: 0;
width: ${({ $width }) => $width};
border-radius: ${({ $borderRadius }) => $borderRadius};
display: flex;
flex-wrap: wrap;
padding: ${({ $padding }) => $padding};
margin-bottom: 10px;
.place_holder {
position: absolute;
font-size: ${({ $fontSize }) => $fontSize};
color: #888;
}
.li {
background-color: var(--primary);
align-items: center;
border-radius: 50px;
color: #fff;
display: flex;
font-weight: 300;
font-size: ${({ $fontSize }) => $fontSize};
list-style: none;
margin-bottom: 5px;
margin-right: 5px;
margin-left: 5px;
padding: 5px 10px;
}
.remove-button {
align-items: center;
appearance: none;
background: #333333;
border: none;
border-radius: 50%;
color: white;
cursor: pointer;
display: inline-flex;
font-size: ${({ $fontSize }) => $fontSize};
height: 15px;
justify-content: center;
line-height: 0;
margin-left: 8px;
padding: 0;
transform: rotate(45deg);
width: 15px;
line-height: 15px;
text-align: center;
}
.li-input {
background: none;
flex-grow: 1;
padding: 0;
font-size: ${({ $fontSize }) => $fontSize};
display: flex;
}
.li-input input {
font-size: ${({ $fontSize }) => $fontSize};
}
input:focus,
select:focus,
textarea:focus,
button:focus {
outline: none;
}
.txt {
padding-left: 5px;
}
.li-input input {
background-color: transparent;
border: none;
}
}
`;
const designStyles = (design) =>
({
solid: css`
.tag-list {
color: var(--txt-normal);
background-color: ${({ $backgroundColor }) => $backgroundColor};
border-style: none;
}
`,
none: css`
.tag-list {
color: var(--txt-normal);
background-color: transparent;
border-style: none;
}
`,
outline: css`
.tag-list {
color: var(--txt-normal);
background-color: transparent;
border-style: solid;
border-width: ${({ $borderWidth }) => $borderWidth};
border-color: ${({ $borderColor }) => $borderColor};
}
`,
}[design]);
import InputTag from "../../example/InputTag";
export default function TestView() {
return (
<div className="test-view">
<InputTag
design="solid"
width="600px"
onChange={(e) => console.log(JSON.stringify(e))}
/>
</div>
);
}
Property | Description | Type | Default |
---|---|---|---|
className | ใช้กำหนดลักษณะเฉพาะของ view | string | |
style | inline style ของ view | CSSProperties | |
value | ค่าเริ่มต้นชุดข้อมูลของ view | array | |
width | ความกว้างภายในเนื้อหาของ view | string | "100%" |
onChange | ฟังก์ชันจะทำงานเมื่อมีการเปลี่ยนค่า | function | |
placeHolder | ข้อความตัวอย่าง | string | |
design | รูปแบบดีไซน์ พื้นฐานของ view เช่น solid (มีสีพื้นหลัง), outline (มีเส้นขอบ) และ none (ไม่มีสีพื้นหลังและเส้นขอบ) | string | "outline" |
borderWidth | ความกว้างเส้นขอบนอกสุดของ view | string | "1px" |
borderColor | สีของเส้นขอบนอกสุดของ view | string | "var(--border)" |
borderRadius | ความโค้งมนของ view | string | "8px" |
backgroundColor | สีพื้นหลังของ view | string | "var(--background-solid)" |
fontSize | ขนาดตัวอักษรของ view | string | "16px" |
label | คำอธิบายของ view | string | |
padding | พื้นที่ว่างระหว่างเส้นขอบของ view และ เนื้อหาของ view | string | "12px 12px 8px" |
margin | พื้นที่ว่างระหว่างขอบนอกสุดของ view และ view อื่น | string |