Implement Input component with dynamic features
This commit is contained in:
77
src/components/Input.js
Normal file
77
src/components/Input.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { $, $html } from "sigpro";
|
||||||
|
import { val, joinClass } from "../core/utils.js";
|
||||||
|
import { tt } from "../core/i18n.js";
|
||||||
|
import {
|
||||||
|
iconAbc,
|
||||||
|
iconLock,
|
||||||
|
iconCalendar,
|
||||||
|
icon123,
|
||||||
|
iconMail,
|
||||||
|
iconShow,
|
||||||
|
iconHide
|
||||||
|
} from "../core/icons.js";
|
||||||
|
|
||||||
|
/** INPUT */
|
||||||
|
export const Input = (props) => {
|
||||||
|
const { label, tip, value, error, isSearch, icon, type = "text", ...rest } = props;
|
||||||
|
const isPassword = type === "password";
|
||||||
|
const visible = $(false);
|
||||||
|
|
||||||
|
const iconsByType = {
|
||||||
|
text: iconAbc,
|
||||||
|
password: iconLock,
|
||||||
|
date: iconCalendar,
|
||||||
|
number: icon123,
|
||||||
|
email: iconMail,
|
||||||
|
};
|
||||||
|
|
||||||
|
const inputEl = $html("input", {
|
||||||
|
...rest,
|
||||||
|
type: () => (isPassword ? (visible() ? "text" : "password") : type),
|
||||||
|
placeholder: props.placeholder || label || (isSearch ? tt("search")() : " "),
|
||||||
|
class: joinClass("grow order-2 focus:outline-none", props.class),
|
||||||
|
value: value,
|
||||||
|
oninput: (e) => props.oninput?.(e),
|
||||||
|
disabled: () => val(props.disabled),
|
||||||
|
});
|
||||||
|
|
||||||
|
const leftIcon = icon ? icon : iconsByType[type] ? $html("img", { src: iconsByType[type], class: "opacity-50", alt: type }) : null;
|
||||||
|
|
||||||
|
return $html(
|
||||||
|
"label",
|
||||||
|
{
|
||||||
|
class: () => joinClass("input input-bordered floating-label flex items-center gap-2 w-full relative", val(error) ? "input-error" : ""),
|
||||||
|
},
|
||||||
|
[
|
||||||
|
leftIcon ? $html("div", { class: "order-1 shrink-0" }, leftIcon) : null,
|
||||||
|
label ? $html("span", { class: "text-base-content/60 order-0" }, label) : null,
|
||||||
|
inputEl,
|
||||||
|
isPassword
|
||||||
|
? $html(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
type: "button",
|
||||||
|
class: "order-3 btn btn-ghost btn-xs btn-circle opacity-50 hover:opacity-100",
|
||||||
|
onclick: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
visible(!visible());
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() =>
|
||||||
|
$html("img", {
|
||||||
|
class: "w-5 h-5",
|
||||||
|
src: visible() ? iconShow : iconHide,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
tip
|
||||||
|
? $html(
|
||||||
|
"div",
|
||||||
|
{ class: "tooltip tooltip-left order-4", "data-tip": tip },
|
||||||
|
$html("span", { class: "badge badge-ghost badge-xs cursor-help" }, "?"),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
() => (val(error) ? $html("span", { class: "text-error text-[10px] absolute -bottom-5 left-2" }, val(error)) : null),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user