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