Mejorados componentes Datepicker, Autocomplete y eliminado fx
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
All checks were successful
Deploy Docs to Synology / deploy (push) Successful in 3s
This commit is contained in:
40
dist/sigpro-ui.css
vendored
40
dist/sigpro-ui.css
vendored
@@ -3293,6 +3293,9 @@
|
|||||||
.mt-4 {
|
.mt-4 {
|
||||||
margin-top: calc(var(--spacing) * 4);
|
margin-top: calc(var(--spacing) * 4);
|
||||||
}
|
}
|
||||||
|
.-mr-2 {
|
||||||
|
margin-right: calc(var(--spacing) * -2);
|
||||||
|
}
|
||||||
.mr-1 {
|
.mr-1 {
|
||||||
margin-right: calc(var(--spacing) * 1);
|
margin-right: calc(var(--spacing) * 1);
|
||||||
}
|
}
|
||||||
@@ -4197,9 +4200,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.transform {
|
|
||||||
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
|
||||||
}
|
|
||||||
.skeleton {
|
.skeleton {
|
||||||
@layer daisyui.l1.l2.l3 {
|
@layer daisyui.l1.l2.l3 {
|
||||||
border-radius: var(--radius-box);
|
border-radius: var(--radius-box);
|
||||||
@@ -4861,10 +4861,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.blur {
|
|
||||||
--tw-blur: blur(8px);
|
|
||||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
|
||||||
}
|
|
||||||
.blur-3xl {
|
.blur-3xl {
|
||||||
--tw-blur: blur(var(--blur-3xl));
|
--tw-blur: blur(var(--blur-3xl));
|
||||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||||
@@ -4877,11 +4873,6 @@
|
|||||||
.filter {
|
.filter {
|
||||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||||
}
|
}
|
||||||
.transition {
|
|
||||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
|
|
||||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
|
||||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
|
||||||
}
|
|
||||||
.transition-all {
|
.transition-all {
|
||||||
transition-property: all;
|
transition-property: all;
|
||||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||||
@@ -5646,26 +5637,6 @@
|
|||||||
inherits: false;
|
inherits: false;
|
||||||
initial-value: 1;
|
initial-value: 1;
|
||||||
}
|
}
|
||||||
@property --tw-rotate-x {
|
|
||||||
syntax: "*";
|
|
||||||
inherits: false;
|
|
||||||
}
|
|
||||||
@property --tw-rotate-y {
|
|
||||||
syntax: "*";
|
|
||||||
inherits: false;
|
|
||||||
}
|
|
||||||
@property --tw-rotate-z {
|
|
||||||
syntax: "*";
|
|
||||||
inherits: false;
|
|
||||||
}
|
|
||||||
@property --tw-skew-x {
|
|
||||||
syntax: "*";
|
|
||||||
inherits: false;
|
|
||||||
}
|
|
||||||
@property --tw-skew-y {
|
|
||||||
syntax: "*";
|
|
||||||
inherits: false;
|
|
||||||
}
|
|
||||||
@property --tw-space-y-reverse {
|
@property --tw-space-y-reverse {
|
||||||
syntax: "*";
|
syntax: "*";
|
||||||
inherits: false;
|
inherits: false;
|
||||||
@@ -5866,11 +5837,6 @@
|
|||||||
--tw-scale-x: 1;
|
--tw-scale-x: 1;
|
||||||
--tw-scale-y: 1;
|
--tw-scale-y: 1;
|
||||||
--tw-scale-z: 1;
|
--tw-scale-z: 1;
|
||||||
--tw-rotate-x: initial;
|
|
||||||
--tw-rotate-y: initial;
|
|
||||||
--tw-rotate-z: initial;
|
|
||||||
--tw-skew-x: initial;
|
|
||||||
--tw-skew-y: initial;
|
|
||||||
--tw-space-y-reverse: 0;
|
--tw-space-y-reverse: 0;
|
||||||
--tw-border-style: solid;
|
--tw-border-style: solid;
|
||||||
--tw-gradient-position: initial;
|
--tw-gradient-position: initial;
|
||||||
|
|||||||
150
dist/sigpro-ui.esm.js
vendored
150
dist/sigpro-ui.esm.js
vendored
@@ -526,46 +526,6 @@ var isFn = (f) => typeof f === "function";
|
|||||||
var filterBy = (items, query, field = "label", q2 = String(query).toLowerCase()) => !query ? get(items) : get(items).filter((item) => String(item && typeof item === "object" ? item[field] : item).toLowerCase().includes(q2));
|
var filterBy = (items, query, field = "label", q2 = String(query).toLowerCase()) => !query ? get(items) : get(items).filter((item) => String(item && typeof item === "object" ? item[field] : item).toLowerCase().includes(q2));
|
||||||
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
||||||
var close = () => document.activeElement?.blur();
|
var close = () => document.activeElement?.blur();
|
||||||
var listKey = (items, isOpen) => {
|
|
||||||
const cursor = $(-1);
|
|
||||||
const onKey = (e, select) => {
|
|
||||||
const list = get(items), i = cursor(), len = list.length;
|
|
||||||
if (!len)
|
|
||||||
return;
|
|
||||||
const k2 = e.key;
|
|
||||||
k2 === "ArrowDown" ? (e.preventDefault(), isOpen(true), cursor(Math.min(i + 1, len - 1))) : k2 === "ArrowUp" ? (e.preventDefault(), cursor(Math.max(i - 1, 0))) : k2 === "Enter" ? i >= 0 && (e.preventDefault(), select(list[i])) : k2 === "Escape" && (isOpen(false), cursor(-1));
|
|
||||||
};
|
|
||||||
return { cursor, onKey };
|
|
||||||
};
|
|
||||||
var fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
|
||||||
const el = typeof child === "function" ? child() : child;
|
|
||||||
if (!(el instanceof Node))
|
|
||||||
return el;
|
|
||||||
if (name) {
|
|
||||||
el.style.animation = `${name}-in ${duration}ms`;
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
const hasTransform = scale || slide || rotate || blur;
|
|
||||||
const initialTransform = [
|
|
||||||
scale ? "scale(0.95)" : "",
|
|
||||||
slide ? "translateY(-10px)" : "",
|
|
||||||
rotate ? "rotate(-2deg)" : ""
|
|
||||||
].filter(Boolean).join(" ");
|
|
||||||
el.style.transition = `all ${duration}ms ease`;
|
|
||||||
el.style.opacity = "0";
|
|
||||||
if (hasTransform)
|
|
||||||
el.style.transform = initialTransform;
|
|
||||||
if (blur)
|
|
||||||
el.style.filter = "blur(4px)";
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
el.style.opacity = "1";
|
|
||||||
if (hasTransform)
|
|
||||||
el.style.transform = "none";
|
|
||||||
if (blur)
|
|
||||||
el.style.filter = "none";
|
|
||||||
});
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-components.js
|
||||||
var Accordion = (p2) => {
|
var Accordion = (p2) => {
|
||||||
@@ -579,11 +539,9 @@ var Accordion = (p2) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
var Alert = (p2, c) => O("div", { ...p2, class: cls("alert", p2.class) }, c);
|
var Alert = (p2, c) => O("div", { ...p2, class: cls("alert", p2.class) }, c);
|
||||||
var Autocomplete = ({ items, value, onselect, placeholder = "Buscar...", ...props }) => {
|
var Autocomplete = ({ items, value, onselect, placeholder = "...", ...props }) => {
|
||||||
const query = S(get(value) || "");
|
const query = S(get(value) || "");
|
||||||
const isOpen = S(false);
|
|
||||||
const filtered = S(() => filterBy(items, query()));
|
const filtered = S(() => filterBy(items, query()));
|
||||||
const { cursor, onKey } = listKey(filtered, isOpen);
|
|
||||||
const pick = (item) => {
|
const pick = (item) => {
|
||||||
const display = getBy(item);
|
const display = getBy(item);
|
||||||
const actual = typeof item === "string" ? item : item.value;
|
const actual = typeof item === "string" ? item : item.value;
|
||||||
@@ -591,12 +549,11 @@ var Autocomplete = ({ items, value, onselect, placeholder = "Buscar...", ...prop
|
|||||||
if (isFn(value))
|
if (isFn(value))
|
||||||
value(actual);
|
value(actual);
|
||||||
onselect?.(item);
|
onselect?.(item);
|
||||||
isOpen(false);
|
close();
|
||||||
};
|
};
|
||||||
return O("div", { class: "relative w-full" }, [
|
return Dropdown({ class: "w-full" }, [
|
||||||
Input({
|
O("div", { tabindex: "0", role: "button", class: "w-full" }, Input({
|
||||||
...props,
|
...props,
|
||||||
type: "text",
|
|
||||||
placeholder,
|
placeholder,
|
||||||
value: query,
|
value: query,
|
||||||
left: O("span", { class: "icon-[lucide--search]" }),
|
left: O("span", { class: "icon-[lucide--search]" }),
|
||||||
@@ -604,28 +561,17 @@ var Autocomplete = ({ items, value, onselect, placeholder = "Buscar...", ...prop
|
|||||||
query(e.target.value);
|
query(e.target.value);
|
||||||
if (isFn(value))
|
if (isFn(value))
|
||||||
value(e.target.value);
|
value(e.target.value);
|
||||||
isOpen(true);
|
}
|
||||||
},
|
})),
|
||||||
onfocus: () => isOpen(true),
|
DropdownContent({ class: "p-2 bg-base-100 rounded-box shadow-xl w-full max-h-60 overflow-y-auto border border-base-300 z-50" }, O("ul", { class: "menu flex-col flex-nowrap w-full p-0" }, [
|
||||||
onblur: () => setTimeout(() => {
|
K(filtered, (item) => O("li", {}, [
|
||||||
isOpen(false);
|
|
||||||
cursor(-1);
|
|
||||||
}, 150),
|
|
||||||
onkeydown: (e) => onKey(e, pick)
|
|
||||||
}),
|
|
||||||
z(isOpen, () => fx({ duration: 200, slide: true }, O("ul", {
|
|
||||||
class: "absolute left-0 w-full menu bg-base-100 rounded-box mt-1 p-2 shadow-xl max-h-60 overflow-y-auto border border-base-300 z-50 flex-col flex-nowrap"
|
|
||||||
}, [
|
|
||||||
K(filtered, (item, idx) => O("li", {}, [
|
|
||||||
O("a", {
|
O("a", {
|
||||||
class: () => cursor() === idx ? "active bg-primary text-primary-content" : "",
|
|
||||||
onmousedown: (e) => e.preventDefault(),
|
onmousedown: (e) => e.preventDefault(),
|
||||||
onclick: () => pick(item),
|
onclick: () => pick(item)
|
||||||
onmouseenter: () => cursor(idx)
|
|
||||||
}, getBy(item))
|
}, getBy(item))
|
||||||
]), (item, idx) => getBy(item) + idx),
|
]), (item) => getBy(item)),
|
||||||
() => filtered().length === 0 ? O("li", { class: "p-4 opacity-50 text-center" }, "Sin resultados") : null
|
() => filtered().length === 0 ? O("li", { class: "p-4 opacity-50 text-center" }, "Sin resultados") : null
|
||||||
])))
|
]))
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Badge = (p2, c) => O("span", { ...p2, class: cls("badge", p2.class) }, c);
|
var Badge = (p2, c) => O("span", { ...p2, class: cls("badge", p2.class) }, c);
|
||||||
@@ -673,7 +619,9 @@ var Calendar = (p2) => {
|
|||||||
O("span", { class: "text-sm font-mono min-w-[48px] text-center" }, () => String(get(hVal)).padStart(2, "0") + ":00")
|
O("span", { class: "text-sm font-mono min-w-[48px] text-center" }, () => String(get(hVal)).padStart(2, "0") + ":00")
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
return O("div", { class: cls("p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none", p2.class) }, [
|
return O("div", {
|
||||||
|
class: cls("p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none", p2.class)
|
||||||
|
}, [
|
||||||
O("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
O("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
||||||
O("div", { class: "flex gap-0.5" }, [
|
O("div", { class: "flex gap-0.5" }, [
|
||||||
O("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, O("span", { class: "icon-[lucide--chevrons-left]" })),
|
O("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, O("span", { class: "icon-[lucide--chevrons-left]" })),
|
||||||
@@ -723,12 +671,7 @@ var Calendar = (p2) => {
|
|||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
p2.hour ? O("div", { class: "mt-3 pt-2 border-t border-base-300" }, rangeMode() ? O("div", { class: "flex gap-4" }, [HourSlider({ value: startHour, onChange: (h) => startHour(h) }), HourSlider({ value: endHour, onChange: (h) => endHour(h) })]) : HourSlider({ value: startHour, onChange: (h) => startHour(h) })) : null,
|
p2.hour ? O("div", { class: "mt-3 pt-2 border-t border-base-300" }, rangeMode() ? O("div", { class: "flex gap-4" }, [HourSlider({ value: startHour, onChange: (h) => startHour(h) }), HourSlider({ value: endHour, onChange: (h) => endHour(h) })]) : HourSlider({ value: startHour, onChange: (h) => startHour(h) })) : null
|
||||||
O("button", {
|
|
||||||
type: "button",
|
|
||||||
class: "btn btn-xs w-full",
|
|
||||||
onclick: () => close()
|
|
||||||
}, Icon("icon-[lucide--x]"))
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Card = (p2, c) => O("div", { ...p2, class: cls("card", p2.class) }, c);
|
var Card = (p2, c) => O("div", { ...p2, class: cls("card", p2.class) }, c);
|
||||||
@@ -824,22 +767,18 @@ var ColorPalette = (p2) => {
|
|||||||
"#fae8ff"
|
"#fae8ff"
|
||||||
];
|
];
|
||||||
const pick = (c) => isFn(p2.value) ? p2.value(c) : p2.onchange?.(c);
|
const pick = (c) => isFn(p2.value) ? p2.value(c) : p2.onchange?.(c);
|
||||||
return [
|
return O("div", { class: "grid grid-cols-8 gap-1" }, palette.map((c) => O("button", {
|
||||||
O("div", { class: "grid grid-cols-8 gap-1" }, palette.map((c) => O("button", {
|
|
||||||
type: "button",
|
type: "button",
|
||||||
style: `background-color: ${c}`,
|
style: `background-color: ${c}`,
|
||||||
class: () => {
|
class: () => {
|
||||||
const act = current().toLowerCase() === c.toLowerCase();
|
const act = current().toLowerCase() === c.toLowerCase();
|
||||||
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? "ring-2 ring-offset-1 ring-primary z-10 scale-110" : ""}`;
|
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? "ring-2 ring-offset-1 ring-primary z-10 scale-110" : ""}`;
|
||||||
},
|
},
|
||||||
onclick: () => pick(c)
|
onclick: () => {
|
||||||
}))),
|
pick(c);
|
||||||
O("button", {
|
close();
|
||||||
type: "button",
|
}
|
||||||
class: "btn btn-xs w-full",
|
})));
|
||||||
onclick: () => close()
|
|
||||||
}, Icon("icon-[lucide--x]"))
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
var Datepicker = (p2) => {
|
var Datepicker = (p2) => {
|
||||||
const displayValue = S("");
|
const displayValue = S("");
|
||||||
@@ -873,26 +812,31 @@ var Datepicker = (p2) => {
|
|||||||
O("label", {
|
O("label", {
|
||||||
tabindex: "0",
|
tabindex: "0",
|
||||||
role: "button",
|
role: "button",
|
||||||
class: "input input-bordered w-full flex items-center gap-2 cursor-pointer"
|
class: "input input-bordered flex items-center gap-2 cursor-pointer"
|
||||||
}, [
|
}, [
|
||||||
O("span", { class: "icon-[lucide--calendar] shrink-0" }),
|
O("span", { class: "icon-[lucide--calendar] shrink-0" }),
|
||||||
O("span", {
|
O("span", {
|
||||||
class: () => `grow text-left truncate ${!displayValue() ? "opacity-50" : ""}`
|
class: () => `grow text-left truncate ${!displayValue() ? "opacity-50" : ""}`
|
||||||
}, () => displayValue() || p2.placeholder || (rangeMode() ? "Seleccionar rango..." : "Seleccionar fecha..."))
|
}, () => displayValue() || p2.placeholder || (rangeMode() ? "Seleccionar rango..." : "Seleccionar fecha...")),
|
||||||
|
() => displayValue() ? O("button", {
|
||||||
|
type: "button",
|
||||||
|
class: "btn btn-ghost btn-xs btn-circle -mr-2",
|
||||||
|
onmousedown: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (isFn(p2.value))
|
||||||
|
p2.value(null);
|
||||||
|
else
|
||||||
|
p2.onChange?.(null);
|
||||||
|
displayValue("");
|
||||||
|
}
|
||||||
|
}, O("span", { class: "icon-[lucide--x] opacity-50" })) : null
|
||||||
]),
|
]),
|
||||||
DropdownContent({ class: "p-0 bg-base-100 rounded-box shadow-xl" }, Calendar({
|
DropdownContent({ class: "p-0 bg-base-100 rounded-box shadow-xl" }, Calendar({
|
||||||
value: p2.value,
|
value: p2.value,
|
||||||
range: rangeMode(),
|
range: rangeMode(),
|
||||||
hour: p2.hour,
|
hour: p2.hour,
|
||||||
onChange: handleChange,
|
onChange: handleChange
|
||||||
onAccept: () => {
|
|
||||||
p2.onAccept?.();
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
p2.onCancel?.();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
@@ -984,20 +928,10 @@ var Indicator = (p2, c) => O("div", { ...p2, class: cls("indicator", p2.class) }
|
|||||||
var Input = (p2) => {
|
var Input = (p2) => {
|
||||||
const { label: label2, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p2;
|
const { label: label2, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p2;
|
||||||
const showPassword = S(false);
|
const showPassword = S(false);
|
||||||
const isFocused = S(false);
|
|
||||||
const isPassword = p2.type === "password";
|
const isPassword = p2.type === "password";
|
||||||
const pattern = rule ?? null;
|
const pattern = rule ?? null;
|
||||||
const inputType = () => isPassword ? get(showPassword) ? "text" : "password" : p2.type || "text";
|
const inputType = () => isPassword ? get(showPassword) ? "text" : "password" : p2.type || "search";
|
||||||
return O("div", {
|
return O("label", { class: float ? "floating-label" : "" }, [
|
||||||
class: "input-container",
|
|
||||||
onfocusin: () => isFocused(true),
|
|
||||||
onfocusout: (e) => {
|
|
||||||
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
||||||
isFocused(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
O("label", { class: float ? "floating-label" : "" }, [
|
|
||||||
float ? O("span", {}, label2) : null,
|
float ? O("span", {}, label2) : null,
|
||||||
O("label", { pattern, class: () => cls("input validator", p2.class) }, [
|
O("label", { pattern, class: () => cls("input validator", p2.class) }, [
|
||||||
label2 && !float ? O("span", { class: "label" }, label2) : null,
|
label2 && !float ? O("span", { class: "label" }, label2) : null,
|
||||||
@@ -1010,11 +944,7 @@ var Input = (p2) => {
|
|||||||
SwapOff({}, Icon("icon-[lucide--eye-off]"))
|
SwapOff({}, Icon("icon-[lucide--eye-off]"))
|
||||||
]) : null
|
]) : null
|
||||||
]),
|
]),
|
||||||
hint ? O("div", { class: "validator-hint" }, hint) : null,
|
hint ? O("div", { class: "validator-hint" }, hint) : null
|
||||||
z(isFocused, () => fx({ duration: 300, slide: true }, O("div", { class: "input-content", onmousedown: (e) => e.preventDefault() }, [
|
|
||||||
isFn(content) ? content(isFocused) : content
|
|
||||||
])))
|
|
||||||
])
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Kbd = (p2, c) => O("kbd", { ...p2, class: cls("kbd", p2.class) }, c);
|
var Kbd = (p2, c) => O("kbd", { ...p2, class: cls("kbd", p2.class) }, c);
|
||||||
|
|||||||
2
dist/sigpro-ui.esm.min.js
vendored
2
dist/sigpro-ui.esm.min.js
vendored
File diff suppressed because one or more lines are too long
150
dist/sigpro-ui.js
vendored
150
dist/sigpro-ui.js
vendored
@@ -557,46 +557,6 @@
|
|||||||
var filterBy = (items, query, field = "label", q2 = String(query).toLowerCase()) => !query ? get(items) : get(items).filter((item) => String(item && typeof item === "object" ? item[field] : item).toLowerCase().includes(q2));
|
var filterBy = (items, query, field = "label", q2 = String(query).toLowerCase()) => !query ? get(items) : get(items).filter((item) => String(item && typeof item === "object" ? item[field] : item).toLowerCase().includes(q2));
|
||||||
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
var rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`;
|
||||||
var close = () => document.activeElement?.blur();
|
var close = () => document.activeElement?.blur();
|
||||||
var listKey = (items, isOpen) => {
|
|
||||||
const cursor = $(-1);
|
|
||||||
const onKey = (e, select) => {
|
|
||||||
const list = get(items), i = cursor(), len = list.length;
|
|
||||||
if (!len)
|
|
||||||
return;
|
|
||||||
const k2 = e.key;
|
|
||||||
k2 === "ArrowDown" ? (e.preventDefault(), isOpen(true), cursor(Math.min(i + 1, len - 1))) : k2 === "ArrowUp" ? (e.preventDefault(), cursor(Math.max(i - 1, 0))) : k2 === "Enter" ? i >= 0 && (e.preventDefault(), select(list[i])) : k2 === "Escape" && (isOpen(false), cursor(-1));
|
|
||||||
};
|
|
||||||
return { cursor, onKey };
|
|
||||||
};
|
|
||||||
var fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
|
||||||
const el = typeof child === "function" ? child() : child;
|
|
||||||
if (!(el instanceof Node))
|
|
||||||
return el;
|
|
||||||
if (name) {
|
|
||||||
el.style.animation = `${name}-in ${duration}ms`;
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
const hasTransform = scale || slide || rotate || blur;
|
|
||||||
const initialTransform = [
|
|
||||||
scale ? "scale(0.95)" : "",
|
|
||||||
slide ? "translateY(-10px)" : "",
|
|
||||||
rotate ? "rotate(-2deg)" : ""
|
|
||||||
].filter(Boolean).join(" ");
|
|
||||||
el.style.transition = `all ${duration}ms ease`;
|
|
||||||
el.style.opacity = "0";
|
|
||||||
if (hasTransform)
|
|
||||||
el.style.transform = initialTransform;
|
|
||||||
if (blur)
|
|
||||||
el.style.filter = "blur(4px)";
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
el.style.opacity = "1";
|
|
||||||
if (hasTransform)
|
|
||||||
el.style.transform = "none";
|
|
||||||
if (blur)
|
|
||||||
el.style.filter = "none";
|
|
||||||
});
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
|
|
||||||
// sigpro-components.js
|
// sigpro-components.js
|
||||||
var Accordion = (p2) => {
|
var Accordion = (p2) => {
|
||||||
@@ -610,11 +570,9 @@
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
var Alert = (p2, c) => O("div", { ...p2, class: cls("alert", p2.class) }, c);
|
var Alert = (p2, c) => O("div", { ...p2, class: cls("alert", p2.class) }, c);
|
||||||
var Autocomplete = ({ items, value, onselect, placeholder = "Buscar...", ...props }) => {
|
var Autocomplete = ({ items, value, onselect, placeholder = "...", ...props }) => {
|
||||||
const query = S(get(value) || "");
|
const query = S(get(value) || "");
|
||||||
const isOpen = S(false);
|
|
||||||
const filtered = S(() => filterBy(items, query()));
|
const filtered = S(() => filterBy(items, query()));
|
||||||
const { cursor, onKey } = listKey(filtered, isOpen);
|
|
||||||
const pick = (item) => {
|
const pick = (item) => {
|
||||||
const display = getBy(item);
|
const display = getBy(item);
|
||||||
const actual = typeof item === "string" ? item : item.value;
|
const actual = typeof item === "string" ? item : item.value;
|
||||||
@@ -622,12 +580,11 @@
|
|||||||
if (isFn(value))
|
if (isFn(value))
|
||||||
value(actual);
|
value(actual);
|
||||||
onselect?.(item);
|
onselect?.(item);
|
||||||
isOpen(false);
|
close();
|
||||||
};
|
};
|
||||||
return O("div", { class: "relative w-full" }, [
|
return Dropdown({ class: "w-full" }, [
|
||||||
Input({
|
O("div", { tabindex: "0", role: "button", class: "w-full" }, Input({
|
||||||
...props,
|
...props,
|
||||||
type: "text",
|
|
||||||
placeholder,
|
placeholder,
|
||||||
value: query,
|
value: query,
|
||||||
left: O("span", { class: "icon-[lucide--search]" }),
|
left: O("span", { class: "icon-[lucide--search]" }),
|
||||||
@@ -635,28 +592,17 @@
|
|||||||
query(e.target.value);
|
query(e.target.value);
|
||||||
if (isFn(value))
|
if (isFn(value))
|
||||||
value(e.target.value);
|
value(e.target.value);
|
||||||
isOpen(true);
|
}
|
||||||
},
|
})),
|
||||||
onfocus: () => isOpen(true),
|
DropdownContent({ class: "p-2 bg-base-100 rounded-box shadow-xl w-full max-h-60 overflow-y-auto border border-base-300 z-50" }, O("ul", { class: "menu flex-col flex-nowrap w-full p-0" }, [
|
||||||
onblur: () => setTimeout(() => {
|
K(filtered, (item) => O("li", {}, [
|
||||||
isOpen(false);
|
|
||||||
cursor(-1);
|
|
||||||
}, 150),
|
|
||||||
onkeydown: (e) => onKey(e, pick)
|
|
||||||
}),
|
|
||||||
z(isOpen, () => fx({ duration: 200, slide: true }, O("ul", {
|
|
||||||
class: "absolute left-0 w-full menu bg-base-100 rounded-box mt-1 p-2 shadow-xl max-h-60 overflow-y-auto border border-base-300 z-50 flex-col flex-nowrap"
|
|
||||||
}, [
|
|
||||||
K(filtered, (item, idx) => O("li", {}, [
|
|
||||||
O("a", {
|
O("a", {
|
||||||
class: () => cursor() === idx ? "active bg-primary text-primary-content" : "",
|
|
||||||
onmousedown: (e) => e.preventDefault(),
|
onmousedown: (e) => e.preventDefault(),
|
||||||
onclick: () => pick(item),
|
onclick: () => pick(item)
|
||||||
onmouseenter: () => cursor(idx)
|
|
||||||
}, getBy(item))
|
}, getBy(item))
|
||||||
]), (item, idx) => getBy(item) + idx),
|
]), (item) => getBy(item)),
|
||||||
() => filtered().length === 0 ? O("li", { class: "p-4 opacity-50 text-center" }, "Sin resultados") : null
|
() => filtered().length === 0 ? O("li", { class: "p-4 opacity-50 text-center" }, "Sin resultados") : null
|
||||||
])))
|
]))
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Badge = (p2, c) => O("span", { ...p2, class: cls("badge", p2.class) }, c);
|
var Badge = (p2, c) => O("span", { ...p2, class: cls("badge", p2.class) }, c);
|
||||||
@@ -704,7 +650,9 @@
|
|||||||
O("span", { class: "text-sm font-mono min-w-[48px] text-center" }, () => String(get(hVal)).padStart(2, "0") + ":00")
|
O("span", { class: "text-sm font-mono min-w-[48px] text-center" }, () => String(get(hVal)).padStart(2, "0") + ":00")
|
||||||
])
|
])
|
||||||
]);
|
]);
|
||||||
return O("div", { class: cls("p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none", p2.class) }, [
|
return O("div", {
|
||||||
|
class: cls("p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none", p2.class)
|
||||||
|
}, [
|
||||||
O("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
O("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
||||||
O("div", { class: "flex gap-0.5" }, [
|
O("div", { class: "flex gap-0.5" }, [
|
||||||
O("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, O("span", { class: "icon-[lucide--chevrons-left]" })),
|
O("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, O("span", { class: "icon-[lucide--chevrons-left]" })),
|
||||||
@@ -754,12 +702,7 @@
|
|||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
]),
|
]),
|
||||||
p2.hour ? O("div", { class: "mt-3 pt-2 border-t border-base-300" }, rangeMode() ? O("div", { class: "flex gap-4" }, [HourSlider({ value: startHour, onChange: (h) => startHour(h) }), HourSlider({ value: endHour, onChange: (h) => endHour(h) })]) : HourSlider({ value: startHour, onChange: (h) => startHour(h) })) : null,
|
p2.hour ? O("div", { class: "mt-3 pt-2 border-t border-base-300" }, rangeMode() ? O("div", { class: "flex gap-4" }, [HourSlider({ value: startHour, onChange: (h) => startHour(h) }), HourSlider({ value: endHour, onChange: (h) => endHour(h) })]) : HourSlider({ value: startHour, onChange: (h) => startHour(h) })) : null
|
||||||
O("button", {
|
|
||||||
type: "button",
|
|
||||||
class: "btn btn-xs w-full",
|
|
||||||
onclick: () => close()
|
|
||||||
}, Icon("icon-[lucide--x]"))
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Card = (p2, c) => O("div", { ...p2, class: cls("card", p2.class) }, c);
|
var Card = (p2, c) => O("div", { ...p2, class: cls("card", p2.class) }, c);
|
||||||
@@ -855,22 +798,18 @@
|
|||||||
"#fae8ff"
|
"#fae8ff"
|
||||||
];
|
];
|
||||||
const pick = (c) => isFn(p2.value) ? p2.value(c) : p2.onchange?.(c);
|
const pick = (c) => isFn(p2.value) ? p2.value(c) : p2.onchange?.(c);
|
||||||
return [
|
return O("div", { class: "grid grid-cols-8 gap-1" }, palette.map((c) => O("button", {
|
||||||
O("div", { class: "grid grid-cols-8 gap-1" }, palette.map((c) => O("button", {
|
|
||||||
type: "button",
|
type: "button",
|
||||||
style: `background-color: ${c}`,
|
style: `background-color: ${c}`,
|
||||||
class: () => {
|
class: () => {
|
||||||
const act = current().toLowerCase() === c.toLowerCase();
|
const act = current().toLowerCase() === c.toLowerCase();
|
||||||
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? "ring-2 ring-offset-1 ring-primary z-10 scale-110" : ""}`;
|
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? "ring-2 ring-offset-1 ring-primary z-10 scale-110" : ""}`;
|
||||||
},
|
},
|
||||||
onclick: () => pick(c)
|
onclick: () => {
|
||||||
}))),
|
pick(c);
|
||||||
O("button", {
|
close();
|
||||||
type: "button",
|
}
|
||||||
class: "btn btn-xs w-full",
|
})));
|
||||||
onclick: () => close()
|
|
||||||
}, Icon("icon-[lucide--x]"))
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
var Datepicker = (p2) => {
|
var Datepicker = (p2) => {
|
||||||
const displayValue = S("");
|
const displayValue = S("");
|
||||||
@@ -904,26 +843,31 @@
|
|||||||
O("label", {
|
O("label", {
|
||||||
tabindex: "0",
|
tabindex: "0",
|
||||||
role: "button",
|
role: "button",
|
||||||
class: "input input-bordered w-full flex items-center gap-2 cursor-pointer"
|
class: "input input-bordered flex items-center gap-2 cursor-pointer"
|
||||||
}, [
|
}, [
|
||||||
O("span", { class: "icon-[lucide--calendar] shrink-0" }),
|
O("span", { class: "icon-[lucide--calendar] shrink-0" }),
|
||||||
O("span", {
|
O("span", {
|
||||||
class: () => `grow text-left truncate ${!displayValue() ? "opacity-50" : ""}`
|
class: () => `grow text-left truncate ${!displayValue() ? "opacity-50" : ""}`
|
||||||
}, () => displayValue() || p2.placeholder || (rangeMode() ? "Seleccionar rango..." : "Seleccionar fecha..."))
|
}, () => displayValue() || p2.placeholder || (rangeMode() ? "Seleccionar rango..." : "Seleccionar fecha...")),
|
||||||
|
() => displayValue() ? O("button", {
|
||||||
|
type: "button",
|
||||||
|
class: "btn btn-ghost btn-xs btn-circle -mr-2",
|
||||||
|
onmousedown: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
if (isFn(p2.value))
|
||||||
|
p2.value(null);
|
||||||
|
else
|
||||||
|
p2.onChange?.(null);
|
||||||
|
displayValue("");
|
||||||
|
}
|
||||||
|
}, O("span", { class: "icon-[lucide--x] opacity-50" })) : null
|
||||||
]),
|
]),
|
||||||
DropdownContent({ class: "p-0 bg-base-100 rounded-box shadow-xl" }, Calendar({
|
DropdownContent({ class: "p-0 bg-base-100 rounded-box shadow-xl" }, Calendar({
|
||||||
value: p2.value,
|
value: p2.value,
|
||||||
range: rangeMode(),
|
range: rangeMode(),
|
||||||
hour: p2.hour,
|
hour: p2.hour,
|
||||||
onChange: handleChange,
|
onChange: handleChange
|
||||||
onAccept: () => {
|
|
||||||
p2.onAccept?.();
|
|
||||||
close();
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
p2.onCancel?.();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
}))
|
}))
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
@@ -1015,20 +959,10 @@
|
|||||||
var Input = (p2) => {
|
var Input = (p2) => {
|
||||||
const { label: label2, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p2;
|
const { label: label2, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p2;
|
||||||
const showPassword = S(false);
|
const showPassword = S(false);
|
||||||
const isFocused = S(false);
|
|
||||||
const isPassword = p2.type === "password";
|
const isPassword = p2.type === "password";
|
||||||
const pattern = rule ?? null;
|
const pattern = rule ?? null;
|
||||||
const inputType = () => isPassword ? get(showPassword) ? "text" : "password" : p2.type || "text";
|
const inputType = () => isPassword ? get(showPassword) ? "text" : "password" : p2.type || "search";
|
||||||
return O("div", {
|
return O("label", { class: float ? "floating-label" : "" }, [
|
||||||
class: "input-container",
|
|
||||||
onfocusin: () => isFocused(true),
|
|
||||||
onfocusout: (e) => {
|
|
||||||
if (!e.currentTarget.contains(e.relatedTarget)) {
|
|
||||||
isFocused(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
O("label", { class: float ? "floating-label" : "" }, [
|
|
||||||
float ? O("span", {}, label2) : null,
|
float ? O("span", {}, label2) : null,
|
||||||
O("label", { pattern, class: () => cls("input validator", p2.class) }, [
|
O("label", { pattern, class: () => cls("input validator", p2.class) }, [
|
||||||
label2 && !float ? O("span", { class: "label" }, label2) : null,
|
label2 && !float ? O("span", { class: "label" }, label2) : null,
|
||||||
@@ -1041,11 +975,7 @@
|
|||||||
SwapOff({}, Icon("icon-[lucide--eye-off]"))
|
SwapOff({}, Icon("icon-[lucide--eye-off]"))
|
||||||
]) : null
|
]) : null
|
||||||
]),
|
]),
|
||||||
hint ? O("div", { class: "validator-hint" }, hint) : null,
|
hint ? O("div", { class: "validator-hint" }, hint) : null
|
||||||
z(isFocused, () => fx({ duration: 300, slide: true }, O("div", { class: "input-content", onmousedown: (e) => e.preventDefault() }, [
|
|
||||||
isFn(content) ? content(isFocused) : content
|
|
||||||
])))
|
|
||||||
])
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
var Kbd = (p2, c) => O("kbd", { ...p2, class: cls("kbd", p2.class) }, c);
|
var Kbd = (p2, c) => O("kbd", { ...p2, class: cls("kbd", p2.class) }, c);
|
||||||
|
|||||||
2
dist/sigpro-ui.min.css
vendored
2
dist/sigpro-ui.min.css
vendored
File diff suppressed because one or more lines are too long
2
dist/sigpro-ui.min.js
vendored
2
dist/sigpro-ui.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -94,7 +94,6 @@ const pass = $('');
|
|||||||
|
|
||||||
mount([
|
mount([
|
||||||
Input({
|
Input({
|
||||||
type: 'text',
|
|
||||||
label: 'Username',
|
label: 'Username',
|
||||||
float: true,
|
float: true,
|
||||||
value: text,
|
value: text,
|
||||||
|
|||||||
2
docs/sigpro-ui.min.css
vendored
2
docs/sigpro-ui.min.css
vendored
File diff suppressed because one or more lines are too long
2
docs/sigpro-ui.min.js
vendored
2
docs/sigpro-ui.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +1,6 @@
|
|||||||
// All base components
|
// All base components
|
||||||
import { h, each, watch, when, mount, $ } from "sigpro";
|
import { h, each, watch, when, mount, $ } from "sigpro";
|
||||||
import { get, getBy, cls, isFn, filterBy, rand, close, listKey, fx } from "./sigpro-helpers.js"
|
import { get, getBy, cls, isFn, filterBy, rand, close } from "./sigpro-helpers.js"
|
||||||
|
|
||||||
export const Accordion = (p) => {
|
export const Accordion = (p) => {
|
||||||
const name = p.name || rand('acc')
|
const name = p.name || rand('acc')
|
||||||
@@ -13,59 +13,50 @@ export const Accordion = (p) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
export const Alert = (p, c) => h("div", { ...p, class: cls("alert", p.class) }, c);
|
export const Alert = (p, c) => h("div", { ...p, class: cls("alert", p.class) }, c);
|
||||||
export const Autocomplete = ({ items, value, onselect, placeholder = 'Buscar...', ...props }) => {
|
export const Autocomplete = ({ items, value, onselect, placeholder = '...', ...props }) => {
|
||||||
const query = $(get(value) || '');
|
const query = $(get(value) || '')
|
||||||
const isOpen = $(false);
|
const filtered = $(() => filterBy(items, query()))
|
||||||
const filtered = $(() => filterBy(items, query()));
|
|
||||||
const { cursor, onKey } = listKey(filtered, isOpen);
|
|
||||||
const pick = (item) => {
|
const pick = (item) => {
|
||||||
const display = getBy(item);
|
const display = getBy(item)
|
||||||
const actual = typeof item === 'string' ? item : item.value;
|
const actual = typeof item === 'string' ? item : item.value
|
||||||
query(display);
|
query(display)
|
||||||
if (isFn(value)) value(actual);
|
if (isFn(value)) value(actual)
|
||||||
onselect?.(item);
|
onselect?.(item)
|
||||||
isOpen(false);
|
close()
|
||||||
};
|
}
|
||||||
return h('div', { class: 'relative w-full' }, [
|
|
||||||
|
return Dropdown({ class: 'w-full' }, [
|
||||||
|
h('div', { tabindex: '0', role: 'button', class: 'w-full' },
|
||||||
Input({
|
Input({
|
||||||
...props,
|
...props,
|
||||||
type: 'text',
|
|
||||||
placeholder,
|
placeholder,
|
||||||
value: query,
|
value: query,
|
||||||
left: h('span', { class: 'icon-[lucide--search]' }),
|
left: h('span', { class: 'icon-[lucide--search]' }),
|
||||||
oninput: (e) => {
|
oninput: (e) => {
|
||||||
query(e.target.value);
|
query(e.target.value)
|
||||||
if (isFn(value)) value(e.target.value);
|
if (isFn(value)) value(e.target.value)
|
||||||
isOpen(true);
|
}
|
||||||
},
|
})
|
||||||
onfocus: () => isOpen(true),
|
),
|
||||||
onblur: () => setTimeout(() => { isOpen(false); cursor(-1); }, 150),
|
DropdownContent({ class: 'p-2 bg-base-100 rounded-box shadow-xl w-full max-h-60 overflow-y-auto border border-base-300 z-50' },
|
||||||
onkeydown: (e) => onKey(e, pick)
|
h('ul', { class: 'menu flex-col flex-nowrap w-full p-0' }, [
|
||||||
}),
|
each(filtered, (item) =>
|
||||||
when(isOpen, () =>
|
|
||||||
fx({ duration: 200, slide: true },
|
|
||||||
h('ul', {
|
|
||||||
class: 'absolute left-0 w-full menu bg-base-100 rounded-box mt-1 p-2 shadow-xl max-h-60 overflow-y-auto border border-base-300 z-50 flex-col flex-nowrap'
|
|
||||||
}, [
|
|
||||||
each(filtered, (item, idx) =>
|
|
||||||
h('li', {}, [
|
h('li', {}, [
|
||||||
h('a', {
|
h('a', {
|
||||||
class: () => cursor() === idx ? 'active bg-primary text-primary-content' : '',
|
onmousedown: (e) => e.preventDefault(),
|
||||||
onmousedown: (e) => e.preventDefault(), // evita que el blur cierre antes del click
|
onclick: () => pick(item)
|
||||||
onclick: () => pick(item),
|
|
||||||
onmouseenter: () => cursor(idx)
|
|
||||||
}, getBy(item))
|
}, getBy(item))
|
||||||
]),
|
]),
|
||||||
(item, idx) => getBy(item) + idx
|
(item) => getBy(item)
|
||||||
),
|
),
|
||||||
() => filtered().length === 0
|
() => filtered().length === 0
|
||||||
? h('li', { class: 'p-4 opacity-50 text-center' }, 'Sin resultados')
|
? h('li', { class: 'p-4 opacity-50 text-center' }, 'Sin resultados')
|
||||||
: null
|
: null
|
||||||
])
|
])
|
||||||
)
|
)
|
||||||
)
|
])
|
||||||
]);
|
}
|
||||||
};
|
|
||||||
export const Badge = (p, c) => h("span", { ...p, class: cls("badge", p.class) }, c);
|
export const Badge = (p, c) => h("span", { ...p, class: cls("badge", p.class) }, c);
|
||||||
export const Button = (p, c) => h("button", { ...p, class: cls("btn", p.class) }, c);
|
export const Button = (p, c) => h("button", { ...p, class: cls("btn", p.class) }, c);
|
||||||
export const Calendar = (p) => {
|
export const Calendar = (p) => {
|
||||||
@@ -102,7 +93,9 @@ export const Calendar = (p) => {
|
|||||||
h('span', { class: 'text-sm font-mono min-w-[48px] text-center' }, () => String(get(hVal)).padStart(2, '0') + ':00')
|
h('span', { class: 'text-sm font-mono min-w-[48px] text-center' }, () => String(get(hVal)).padStart(2, '0') + ':00')
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
return h('div', { class: cls('p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none', p.class) }, [
|
return h('div', {
|
||||||
|
class: cls('p-4 bg-base-100 border border-base-300 shadow-2xl rounded-box w-80 select-none', p.class)
|
||||||
|
}, [
|
||||||
h('div', { class: 'flex justify-between items-center mb-4 gap-1' }, [
|
h('div', { class: 'flex justify-between items-center mb-4 gap-1' }, [
|
||||||
h('div', { class: 'flex gap-0.5' }, [
|
h('div', { class: 'flex gap-0.5' }, [
|
||||||
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => moveYear(-1) }, h('span', { class: 'icon-[lucide--chevrons-left]' })),
|
h('button', { type: 'button', class: 'btn btn-ghost btn-xs px-1', onclick: () => moveYear(-1) }, h('span', { class: 'icon-[lucide--chevrons-left]' })),
|
||||||
@@ -153,12 +146,7 @@ export const Calendar = (p) => {
|
|||||||
rangeMode()
|
rangeMode()
|
||||||
? h('div', { class: 'flex gap-4' }, [HourSlider({ value: startHour, onChange: h => startHour(h) }), HourSlider({ value: endHour, onChange: h => endHour(h) })])
|
? h('div', { class: 'flex gap-4' }, [HourSlider({ value: startHour, onChange: h => startHour(h) }), HourSlider({ value: endHour, onChange: h => endHour(h) })])
|
||||||
: HourSlider({ value: startHour, onChange: h => startHour(h) })
|
: HourSlider({ value: startHour, onChange: h => startHour(h) })
|
||||||
) : null,
|
) : null
|
||||||
h('button', {
|
|
||||||
type: 'button',
|
|
||||||
class: 'btn btn-xs w-full',
|
|
||||||
onclick: () => close()
|
|
||||||
}, Icon('icon-[lucide--x]'))
|
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
export const Card = (p, c) => h('div', { ...p, class: cls('card', p.class) }, c);
|
export const Card = (p, c) => h('div', { ...p, class: cls('card', p.class) }, c);
|
||||||
@@ -198,8 +186,7 @@ export const ColorPalette = (p) => {
|
|||||||
'#2e1065', '#4c1d95', '#6d28d9', '#7c3aed', '#8b5cf6', '#a855f7', '#d946ef', '#fae8ff'
|
'#2e1065', '#4c1d95', '#6d28d9', '#7c3aed', '#8b5cf6', '#a855f7', '#d946ef', '#fae8ff'
|
||||||
]
|
]
|
||||||
const pick = (c) => isFn(p.value) ? p.value(c) : p.onchange?.(c)
|
const pick = (c) => isFn(p.value) ? p.value(c) : p.onchange?.(c)
|
||||||
return [
|
return h('div', { class: 'grid grid-cols-8 gap-1' },
|
||||||
h('div', { class: 'grid grid-cols-8 gap-1' },
|
|
||||||
palette.map(c => h('button', {
|
palette.map(c => h('button', {
|
||||||
type: 'button',
|
type: 'button',
|
||||||
style: `background-color: ${c}`,
|
style: `background-color: ${c}`,
|
||||||
@@ -207,15 +194,10 @@ export const ColorPalette = (p) => {
|
|||||||
const act = current().toLowerCase() === c.toLowerCase()
|
const act = current().toLowerCase() === c.toLowerCase()
|
||||||
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? 'ring-2 ring-offset-1 ring-primary z-10 scale-110' : ''}`
|
return `size-6 rounded-sm cursor-pointer transition-all hover:scale-125 hover:z-10 active:scale-95 outline-none border border-black/5 p-0 min-h-0 ${act ? 'ring-2 ring-offset-1 ring-primary z-10 scale-110' : ''}`
|
||||||
},
|
},
|
||||||
onclick: () => pick(c)
|
onclick: () => { pick(c); close() }
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
),
|
)
|
||||||
h('button', {
|
|
||||||
type: 'button',
|
|
||||||
class: 'btn btn-xs w-full',
|
|
||||||
onclick: () => close()
|
|
||||||
}, Icon('icon-[lucide--x]'))]
|
|
||||||
}
|
}
|
||||||
export const Datepicker = (p) => {
|
export const Datepicker = (p) => {
|
||||||
const displayValue = $("")
|
const displayValue = $("")
|
||||||
@@ -246,29 +228,32 @@ export const Datepicker = (p) => {
|
|||||||
|
|
||||||
return Dropdown({ class: cls('w-full', p.class) }, [
|
return Dropdown({ class: cls('w-full', p.class) }, [
|
||||||
h('label', {
|
h('label', {
|
||||||
tabindex: '0', // ← Necesario para que funcione el dropdown
|
tabindex: '0',
|
||||||
role: 'button', // ← Necesario para que funcione el dropdown
|
role: 'button',
|
||||||
class: 'input input-bordered w-full flex items-center gap-2 cursor-pointer'
|
class: 'input input-bordered flex items-center gap-2 cursor-pointer'
|
||||||
}, [
|
}, [
|
||||||
h('span', { class: 'icon-[lucide--calendar] shrink-0' }),
|
h('span', { class: 'icon-[lucide--calendar] shrink-0' }),
|
||||||
h('span', {
|
h('span', {
|
||||||
class: () => `grow text-left truncate ${!displayValue() ? 'opacity-50' : ''}`,
|
class: () => `grow text-left truncate ${!displayValue() ? 'opacity-50' : ''}`,
|
||||||
}, () => displayValue() || p.placeholder || (rangeMode() ? 'Seleccionar rango...' : 'Seleccionar fecha...'))
|
}, () => displayValue() || p.placeholder || (rangeMode() ? 'Seleccionar rango...' : 'Seleccionar fecha...')),
|
||||||
|
() => displayValue() ? h('button', {
|
||||||
|
type: 'button',
|
||||||
|
class: 'btn btn-ghost btn-xs btn-circle -mr-2',
|
||||||
|
onmousedown: (e) => {
|
||||||
|
e.preventDefault()
|
||||||
|
e.stopPropagation()
|
||||||
|
if (isFn(p.value)) p.value(null)
|
||||||
|
else p.onChange?.(null)
|
||||||
|
displayValue("") // Forzar limpieza visual inmediata
|
||||||
|
}
|
||||||
|
}, h('span', { class: 'icon-[lucide--x] opacity-50' })) : null
|
||||||
]),
|
]),
|
||||||
DropdownContent({ class: 'p-0 bg-base-100 rounded-box shadow-xl' },
|
DropdownContent({ class: 'p-0 bg-base-100 rounded-box shadow-xl' },
|
||||||
Calendar({
|
Calendar({
|
||||||
value: p.value,
|
value: p.value,
|
||||||
range: rangeMode(),
|
range: rangeMode(),
|
||||||
hour: p.hour,
|
hour: p.hour,
|
||||||
onChange: handleChange,
|
onChange: handleChange
|
||||||
onAccept: () => {
|
|
||||||
p.onAccept?.()
|
|
||||||
close()
|
|
||||||
},
|
|
||||||
onCancel: () => {
|
|
||||||
p.onCancel?.()
|
|
||||||
close()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
])
|
])
|
||||||
@@ -355,27 +340,21 @@ export const Input = (p) => {
|
|||||||
const { label, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p;
|
const { label, icon, float, placeholder, value, left, right, rule, hint, content, ...rest } = p;
|
||||||
|
|
||||||
const showPassword = $(false);
|
const showPassword = $(false);
|
||||||
const isFocused = $(false);
|
|
||||||
const isPassword = p.type === 'password';
|
const isPassword = p.type === 'password';
|
||||||
const pattern = rule ?? null;
|
const pattern = rule ?? null;
|
||||||
|
|
||||||
const inputType = () => isPassword
|
const inputType = () => isPassword
|
||||||
? (get(showPassword) ? 'text' : 'password')
|
? (get(showPassword) ? 'text' : 'password')
|
||||||
: (p.type || 'text');
|
: (p.type || 'search');
|
||||||
return h("div", {
|
|
||||||
class: "input-container",
|
return h("label", { class: float ? 'floating-label' : '' }, [
|
||||||
onfocusin: () => isFocused(true),
|
|
||||||
onfocusout: (e) => {
|
|
||||||
if (!e.currentTarget.contains(e.relatedTarget)) { isFocused(false); }
|
|
||||||
}
|
|
||||||
}, [
|
|
||||||
h('label', { class: float ? 'floating-label' : '' }, [
|
|
||||||
float ? h("span", {}, label) : null,
|
float ? h("span", {}, label) : null,
|
||||||
h("label", { pattern: pattern, class: () => cls('input validator', p.class) },
|
h("label", { pattern: pattern, class: () => cls('input validator', p.class) },
|
||||||
[
|
[
|
||||||
label && !float ? h('span', { class: 'label' }, label) : null,
|
label && !float ? h('span', { class: 'label' }, label) : null,
|
||||||
left ?? null,
|
left ?? null,
|
||||||
h('input', { ...rest, type: inputType, class: 'grow', pattern: pattern, placeholder: placeholder || label || ' ', value: value }), right ?? null,
|
h('input', { ...rest, type: inputType, class: 'grow', pattern: pattern, placeholder: placeholder || label || ' ', value: value }),
|
||||||
|
right ?? null,
|
||||||
isPassword ? Swap({ class: 'ml-2' }, [
|
isPassword ? Swap({ class: 'ml-2' }, [
|
||||||
SwapToggle({ value: showPassword, class: "swap-rotate" }),
|
SwapToggle({ value: showPassword, class: "swap-rotate" }),
|
||||||
SwapOn({}, Icon('icon-[lucide--eye]')),
|
SwapOn({}, Icon('icon-[lucide--eye]')),
|
||||||
@@ -383,14 +362,6 @@ export const Input = (p) => {
|
|||||||
]) : null
|
]) : null
|
||||||
]),
|
]),
|
||||||
hint ? h('div', { class: "validator-hint" }, hint) : null,
|
hint ? h('div', { class: "validator-hint" }, hint) : null,
|
||||||
|
|
||||||
when(isFocused, () => fx({ duration: 300, slide: true },
|
|
||||||
h('div', { class: 'input-content', onmousedown: e => e.preventDefault() },
|
|
||||||
[
|
|
||||||
isFn(content) ? content(isFocused) : content
|
|
||||||
])
|
|
||||||
))
|
|
||||||
]),
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
export const Kbd = (p, c) => h("kbd", { ...p, class: cls("kbd", p.class) }, c);
|
export const Kbd = (p, c) => h("kbd", { ...p, class: cls("kbd", p.class) }, c);
|
||||||
|
|||||||
@@ -6,43 +6,6 @@ export const isFn = f => typeof f === "function";
|
|||||||
export const filterBy = (items, query, field = 'label', q = String(query).toLowerCase()) => !query ? get(items) : get(items).filter(item => String(item && typeof item === 'object' ? item[field] : item).toLowerCase().includes(q));
|
export const filterBy = (items, query, field = 'label', q = String(query).toLowerCase()) => !query ? get(items) : get(items).filter(item => String(item && typeof item === 'object' ? item[field] : item).toLowerCase().includes(q));
|
||||||
export const rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`
|
export const rand = (r) => `${r}-${Math.random().toString(36).slice(2, 9)}`
|
||||||
export const close = () => document.activeElement?.blur()
|
export const close = () => document.activeElement?.blur()
|
||||||
export const listKey = (items, isOpen) => {
|
|
||||||
const cursor = $(-1);
|
|
||||||
const onKey = (e, select) => {
|
|
||||||
const list = get(items), i = cursor(), len = list.length;
|
|
||||||
if (!len) return;
|
|
||||||
const k = e.key;
|
|
||||||
k === 'ArrowDown' ? (e.preventDefault(), isOpen(true), cursor(Math.min(i + 1, len - 1))) :
|
|
||||||
k === 'ArrowUp' ? (e.preventDefault(), cursor(Math.max(i - 1, 0))) :
|
|
||||||
k === 'Enter' ? (i >= 0 && (e.preventDefault(), select(list[i]))) :
|
|
||||||
k === 'Escape' ? (isOpen(false), cursor(-1)) : null;
|
|
||||||
};
|
|
||||||
return { cursor, onKey };
|
|
||||||
};
|
|
||||||
export const fx = ({ name, duration = 200, scale, slide, rotate, blur }, child) => {
|
|
||||||
const el = typeof child === "function" ? child() : child;
|
|
||||||
if (!(el instanceof Node)) return el;
|
|
||||||
if (name) {
|
|
||||||
el.style.animation = `${name}-in ${duration}ms`;
|
|
||||||
return el;
|
|
||||||
}
|
|
||||||
const hasTransform = scale || slide || rotate || blur;
|
|
||||||
const initialTransform = [
|
|
||||||
scale ? "scale(0.95)" : "",
|
|
||||||
slide ? "translateY(-10px)" : "",
|
|
||||||
rotate ? "rotate(-2deg)" : ""
|
|
||||||
].filter(Boolean).join(" ");
|
|
||||||
el.style.transition = `all ${duration}ms ease`;
|
|
||||||
el.style.opacity = "0";
|
|
||||||
if (hasTransform) el.style.transform = initialTransform;
|
|
||||||
if (blur) el.style.filter = "blur(4px)";
|
|
||||||
requestAnimationFrame(() => {
|
|
||||||
el.style.opacity = "1";
|
|
||||||
if (hasTransform) el.style.transform = "none";
|
|
||||||
if (blur) el.style.filter = "none";
|
|
||||||
});
|
|
||||||
return el;
|
|
||||||
};
|
|
||||||
export const req = ({ url, method = 'GET', headers = {} }) => {
|
export const req = ({ url, method = 'GET', headers = {} }) => {
|
||||||
const loading = $(false);
|
const loading = $(false);
|
||||||
const error = $(null);
|
const error = $(null);
|
||||||
|
|||||||
Reference in New Issue
Block a user