ui updated
This commit is contained in:
@@ -62,7 +62,7 @@ const Profile = (params) => {
|
|||||||
}),
|
}),
|
||||||
Datepicker({ $value: miFecha, label: "Fecha", placeholder: textoInput }),
|
Datepicker({ $value: miFecha, label: "Fecha", placeholder: textoInput }),
|
||||||
Datepicker({ $value: miRango, label: "Fecha", placeholder: textoInput, range: true }),
|
Datepicker({ $value: miRango, label: "Fecha", placeholder: textoInput, range: true }),
|
||||||
Colorpicker({ label: "Color del tema", $value: colorFondo, placeholder: "Elige un color..." }),
|
Colorpicker({ show:true, label: "Color del tema", $value: colorFondo }),
|
||||||
Input({ type: "number", label: "Number" }),
|
Input({ type: "number", label: "Number" }),
|
||||||
Input({ type: "email", label: "Email" }),
|
Input({ type: "email", label: "Email" }),
|
||||||
Input({ label: "Text" }),
|
Input({ label: "Text" }),
|
||||||
|
|||||||
207
src/sigpro-ui.js
207
src/sigpro-ui.js
@@ -78,22 +78,17 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
const key = keyFn(item, index);
|
const key = keyFn(item, index);
|
||||||
newKeys.add(key);
|
newKeys.add(key);
|
||||||
|
|
||||||
if (cache.has(key)) {
|
let runtime = cache.get(key);
|
||||||
const runtime = cache.get(key);
|
if (!runtime) {
|
||||||
container.insertBefore(runtime.container, marker);
|
runtime = $.view(() => render(item, index));
|
||||||
} else {
|
|
||||||
const runtime = $.view(() => {
|
|
||||||
return $.html("div", { style: "display:contents" }, [render(item, index)]);
|
|
||||||
});
|
|
||||||
cache.set(key, runtime);
|
cache.set(key, runtime);
|
||||||
container.insertBefore(runtime.container, marker);
|
|
||||||
}
|
}
|
||||||
|
container.insertBefore(runtime.container, marker);
|
||||||
});
|
});
|
||||||
|
|
||||||
cache.forEach((runtime, key) => {
|
cache.forEach((runtime, key) => {
|
||||||
if (!newKeys.has(key)) {
|
if (!newKeys.has(key)) {
|
||||||
runtime.destroy();
|
runtime.destroy();
|
||||||
runtime.container.remove();
|
|
||||||
cache.delete(key);
|
cache.delete(key);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -152,7 +147,7 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
return { data, loading, error, success, reload: (p) => execute(p) };
|
return { data, loading, error, success, reload: (p) => execute(p) };
|
||||||
};
|
};
|
||||||
|
|
||||||
/** RES */
|
/** RESPONSE */
|
||||||
ui.Response = (reqObj, renderFn) =>
|
ui.Response = (reqObj, renderFn) =>
|
||||||
$.html("div", { class: "res-container" }, [
|
$.html("div", { class: "res-container" }, [
|
||||||
ui.If(reqObj.loading, $.html("div", { class: "flex justify-center p-4" }, $.html("span", { class: "loading loading-dots text-primary" }))),
|
ui.If(reqObj.loading, $.html("div", { class: "flex justify-center p-4" }, $.html("span", { class: "loading loading-dots text-primary" }))),
|
||||||
@@ -200,7 +195,6 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** INPUT */
|
/** INPUT */
|
||||||
|
|
||||||
ui.Input = (props) => {
|
ui.Input = (props) => {
|
||||||
const { label, tip, $value, $error, isSearch, icon, type = "text", ...rest } = props;
|
const { label, tip, $value, $error, isSearch, icon, type = "text", ...rest } = props;
|
||||||
|
|
||||||
@@ -318,11 +312,11 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const pick = (opt) => {
|
const pick = (opt) => {
|
||||||
const value = typeof opt === "string" ? opt : opt.value;
|
const valStr = typeof opt === "string" ? opt : opt.value;
|
||||||
const label = typeof opt === "string" ? opt : opt.label;
|
const labelStr = typeof opt === "string" ? opt : opt.label;
|
||||||
|
|
||||||
query(label);
|
query(labelStr);
|
||||||
$value?.(value);
|
if (typeof $value === "function") $value(valStr);
|
||||||
onSelect?.(opt);
|
onSelect?.(opt);
|
||||||
|
|
||||||
isOpen(false);
|
isOpen(false);
|
||||||
@@ -331,24 +325,19 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
|
|
||||||
const nav = (e) => {
|
const nav = (e) => {
|
||||||
const items = list();
|
const items = list();
|
||||||
|
|
||||||
if (e.key === "ArrowDown") {
|
if (e.key === "ArrowDown") {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
isOpen(true);
|
isOpen(true);
|
||||||
cursor((i) => Math.min(i + 1, items.length - 1));
|
cursor(Math.min(cursor() + 1, items.length - 1));
|
||||||
}
|
} else if (e.key === "ArrowUp") {
|
||||||
|
|
||||||
if (e.key === "ArrowUp") {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
cursor((i) => Math.max(i - 1, 0));
|
cursor(Math.max(cursor() - 1, 0));
|
||||||
}
|
} else if (e.key === "Enter" && cursor() >= 0) {
|
||||||
|
|
||||||
if (e.key === "Enter" && cursor() >= 0) {
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
pick(items[cursor()]);
|
pick(items[cursor()]);
|
||||||
|
} else if (e.key === "Escape") {
|
||||||
|
isOpen(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.key === "Escape") isOpen(false);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return $.html("div", { class: "relative w-full" }, [
|
return $.html("div", { class: "relative w-full" }, [
|
||||||
@@ -360,13 +349,14 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
onblur: () => setTimeout(() => isOpen(false), 150),
|
onblur: () => setTimeout(() => isOpen(false), 150),
|
||||||
onkeydown: nav,
|
onkeydown: nav,
|
||||||
oninput: (e) => {
|
oninput: (e) => {
|
||||||
query(e.target.value);
|
const v = e.target.value;
|
||||||
|
query(v);
|
||||||
|
if (typeof $value === "function") $value(v);
|
||||||
isOpen(true);
|
isOpen(true);
|
||||||
cursor(-1);
|
cursor(-1);
|
||||||
},
|
},
|
||||||
...rest,
|
...rest,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
$.html(
|
$.html(
|
||||||
"ul",
|
"ul",
|
||||||
{
|
{
|
||||||
@@ -390,23 +380,19 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
]),
|
]),
|
||||||
(opt, i) => (typeof opt === "string" ? opt : opt.value) + i,
|
(opt, i) => (typeof opt === "string" ? opt : opt.value) + i,
|
||||||
),
|
),
|
||||||
|
() => (list().length ? null : $.html("li", { class: "p-2 text-center opacity-50" }, "No results")),
|
||||||
() => (!list().length ? $.html("li", { class: "p-2 text-center opacity-50" }, "No results") : null),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** DATEPICKER */
|
/** DATEPICKER */
|
||||||
|
|
||||||
ui.Datepicker = (props) => {
|
ui.Datepicker = (props) => {
|
||||||
const { $value, range, label, placeholder, ...rest } = props;
|
const { $value, range, label, placeholder, ...rest } = props;
|
||||||
|
|
||||||
const isOpen = $(false);
|
const isOpen = $(false);
|
||||||
const internalDate = $(new Date());
|
const internalDate = $(new Date());
|
||||||
const hoverDate = $(null);
|
const hoverDate = $(null);
|
||||||
|
|
||||||
// Determinamos si es rango (si no se pasa nada, por defecto es falso para fecha única)
|
|
||||||
const isRangeMode = () => val(range) === true;
|
const isRangeMode = () => val(range) === true;
|
||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
@@ -424,17 +410,17 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
const current = val($value);
|
const current = val($value);
|
||||||
|
|
||||||
if (isRangeMode()) {
|
if (isRangeMode()) {
|
||||||
// MODO RANGO
|
|
||||||
if (!current?.start || (current.start && current.end)) {
|
if (!current?.start || (current.start && current.end)) {
|
||||||
$value({ start: dateStr, end: null });
|
if (typeof $value === "function") $value({ start: dateStr, end: null });
|
||||||
} else {
|
} else {
|
||||||
const start = current.start;
|
const start = current.start;
|
||||||
|
if (typeof $value === "function") {
|
||||||
$value(dateStr < start ? { start: dateStr, end: start } : { start, end: dateStr });
|
$value(dateStr < start ? { start: dateStr, end: start } : { start, end: dateStr });
|
||||||
|
}
|
||||||
isOpen(false);
|
isOpen(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// MODO FECHA ÚNICA
|
if (typeof $value === "function") $value(dateStr);
|
||||||
$value(dateStr);
|
|
||||||
isOpen(false);
|
isOpen(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -442,19 +428,17 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
const displayValue = $(() => {
|
const displayValue = $(() => {
|
||||||
const v = val($value);
|
const v = val($value);
|
||||||
if (!v) return "";
|
if (!v) return "";
|
||||||
// Si es un string (fecha única)
|
|
||||||
if (typeof v === "string") return v;
|
if (typeof v === "string") return v;
|
||||||
// Si es un objeto (rango)
|
|
||||||
if (v.start && v.end) return `${v.start} - ${v.end}`;
|
if (v.start && v.end) return `${v.start} - ${v.end}`;
|
||||||
if (v.start) return `${v.start}...`;
|
if (v.start) return `${v.start}...`;
|
||||||
return "";
|
return "";
|
||||||
});
|
});
|
||||||
|
|
||||||
// ... resto del move, moveYear ...
|
|
||||||
const move = (m) => {
|
const move = (m) => {
|
||||||
const d = internalDate();
|
const d = internalDate();
|
||||||
internalDate(new Date(d.getFullYear(), d.getMonth() + m, 1));
|
internalDate(new Date(d.getFullYear(), d.getMonth() + m, 1));
|
||||||
};
|
};
|
||||||
|
|
||||||
const moveYear = (y) => {
|
const moveYear = (y) => {
|
||||||
const d = internalDate();
|
const d = internalDate();
|
||||||
internalDate(new Date(d.getFullYear() + y, d.getMonth(), 1));
|
internalDate(new Date(d.getFullYear() + y, d.getMonth(), 1));
|
||||||
@@ -482,7 +466,6 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
onclick: (e) => e.stopPropagation(),
|
onclick: (e) => e.stopPropagation(),
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
// Header (Igual que el tuyo)
|
|
||||||
$.html("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
$.html("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
||||||
$.html("div", { class: "flex gap-0.5" }, [
|
$.html("div", { class: "flex gap-0.5" }, [
|
||||||
$.html("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, "<<"),
|
$.html("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, "<<"),
|
||||||
@@ -497,7 +480,6 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
]),
|
]),
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// Grid
|
|
||||||
$.html("div", { class: "grid grid-cols-7 gap-1", onmouseleave: () => hoverDate(null) }, [
|
$.html("div", { class: "grid grid-cols-7 gap-1", onmouseleave: () => hoverDate(null) }, [
|
||||||
...["L", "M", "X", "J", "V", "S", "D"].map((d) => $.html("div", { class: "text-[10px] opacity-40 font-bold text-center" }, d)),
|
...["L", "M", "X", "J", "V", "S", "D"].map((d) => $.html("div", { class: "text-[10px] opacity-40 font-bold text-center" }, d)),
|
||||||
() => {
|
() => {
|
||||||
@@ -523,30 +505,31 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
class: () => {
|
class: () => {
|
||||||
const v = val($value);
|
const v = val($value);
|
||||||
const h = hoverDate();
|
const h = hoverDate();
|
||||||
const isToday = dStr === todayStr;
|
|
||||||
|
|
||||||
// Lógica de selección según el tipo de dato
|
|
||||||
const isStart = typeof v === "string" ? v === dStr : v?.start === dStr;
|
const isStart = typeof v === "string" ? v === dStr : v?.start === dStr;
|
||||||
const isEnd = v?.end === dStr;
|
const isEnd = v?.end === dStr;
|
||||||
|
|
||||||
let inRange = false;
|
let inRange = false;
|
||||||
// Solo calculamos sombreado si estamos en modo rango
|
|
||||||
if (isRangeMode()) {
|
if (isRangeMode() && v?.start) {
|
||||||
if (v?.start && !v.end && h) {
|
const start = v.start;
|
||||||
inRange = (dStr > v.start && dStr <= h) || (dStr < v.start && dStr >= h);
|
if (!v.end && h) {
|
||||||
} else if (v?.start && v?.end) {
|
inRange = (dStr > start && dStr <= h) || (dStr < start && dStr >= h);
|
||||||
inRange = dStr > v.start && dStr < v.end;
|
} else if (v.end) {
|
||||||
|
inRange = dStr > start && dStr < v.end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return `btn btn-xs p-0 aspect-square min-h-0 h-auto font-normal relative
|
const base = "btn btn-xs p-0 aspect-square min-h-0 h-auto font-normal relative";
|
||||||
${isStart || isEnd ? "btn-primary z-10" : inRange ? "bg-primary/20 border-none rounded-none" : "btn-ghost"}
|
const state = isStart || isEnd ? "btn-primary z-10" : inRange ? "bg-primary/20 border-none rounded-none" : "btn-ghost";
|
||||||
${isToday ? "ring-1 ring-primary ring-inset font-black text-primary" : ""}`;
|
const today = dStr === todayStr ? "ring-1 ring-primary ring-inset font-black text-primary" : "";
|
||||||
|
|
||||||
|
return `${base} ${state} ${today}`;
|
||||||
|
},
|
||||||
|
onmouseenter: () => {
|
||||||
|
if (isRangeMode()) hoverDate(dStr);
|
||||||
},
|
},
|
||||||
onmouseenter: () => isRangeMode() && hoverDate(dStr),
|
|
||||||
onclick: () => selectDate(date),
|
onclick: () => selectDate(date),
|
||||||
},
|
},
|
||||||
i.toString(),
|
[i.toString()],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -563,40 +546,42 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
|
|
||||||
/** COLORPICKER */
|
/** COLORPICKER */
|
||||||
ui.Colorpicker = (props) => {
|
ui.Colorpicker = (props) => {
|
||||||
const { $value, label, placeholder, ...rest } = props;
|
const { $value, label, ...rest } = props;
|
||||||
const isOpen = $(false);
|
const isOpen = $(false);
|
||||||
|
|
||||||
const p1 = ["#000", "#1A1A1A", "#333", "#4D4D4D", "#666", "#808080", "#B3B3B3", "#FFF"];
|
const palette = [
|
||||||
const p2 = ["#450a0a", "#7f1d1d", "#991b1b", "#b91c1c", "#dc2626", "#ef4444", "#f87171", "#fca5a5"];
|
...["#000", "#1A1A1A", "#333", "#4D4D4D", "#666", "#808080", "#B3B3B3", "#FFF"],
|
||||||
const p3 = ["#431407", "#7c2d12", "#9a3412", "#c2410c", "#ea580c", "#f97316", "#fb923c", "#ffedd5"];
|
...["#450a0a", "#7f1d1d", "#991b1b", "#b91c1c", "#dc2626", "#ef4444", "#f87171", "#fca5a5"],
|
||||||
const p4 = ["#713f12", "#a16207", "#ca8a04", "#eab308", "#facc15", "#fde047", "#fef08a", "#fff9c4"];
|
...["#431407", "#7c2d12", "#9a3412", "#c2410c", "#ea580c", "#f97316", "#fb923c", "#ffedd5"],
|
||||||
const p5 = ["#064e3b", "#065f46", "#059669", "#10b981", "#34d399", "#4ade80", "#84cc16", "#d9f99d"];
|
...["#713f12", "#a16207", "#ca8a04", "#eab308", "#facc15", "#fde047", "#fef08a", "#fff9c4"],
|
||||||
const p6 = ["#082f49", "#075985", "#0284c7", "#0ea5e9", "#38bdf8", "#7dd3fc", "#22d3ee", "#cffafe"];
|
...["#064e3b", "#065f46", "#059669", "#10b981", "#34d399", "#4ade80", "#84cc16", "#d9f99d"],
|
||||||
const p7 = ["#1e1b4b", "#312e81", "#4338ca", "#4f46e5", "#6366f1", "#818cf8", "#a5b4fc", "#e0e7ff"];
|
...["#082f49", "#075985", "#0284c7", "#0ea5e9", "#38bdf8", "#7dd3fc", "#22d3ee", "#cffafe"],
|
||||||
const p8 = ["#2e1065", "#4c1d95", "#6d28d9", "#7c3aed", "#8b5cf6", "#a855f7", "#d946ef", "#fae8ff"];
|
...["#1e1b4b", "#312e81", "#4338ca", "#4f46e5", "#6366f1", "#818cf8", "#a5b4fc", "#e0e7ff"],
|
||||||
|
...["#2e1065", "#4c1d95", "#6d28d9", "#7c3aed", "#8b5cf6", "#a855f7", "#d946ef", "#fae8ff"],
|
||||||
const palette = [...p1, ...p2, ...p3, ...p4, ...p5, ...p6, ...p7, ...p8];
|
];
|
||||||
|
|
||||||
const getColor = () => val($value) || "#000000";
|
const getColor = () => val($value) || "#000000";
|
||||||
|
|
||||||
return $.html("div", { class: "relative w-full" }, [
|
return $.html("div", { class: "relative w-fit" }, [
|
||||||
ui.Input({
|
$.html(
|
||||||
label,
|
"button",
|
||||||
$value,
|
{
|
||||||
readonly: true,
|
type: "button",
|
||||||
placeholder: placeholder || "#000000",
|
class: "btn px-3 bg-base-100 border-base-300 hover:border-primary/50 flex items-center gap-2 shadow-sm font-normal normal-case",
|
||||||
class: "cursor-pointer font-mono uppercase",
|
|
||||||
onclick: (e) => {
|
onclick: (e) => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
isOpen(!isOpen());
|
isOpen(!isOpen());
|
||||||
},
|
},
|
||||||
icon: () =>
|
|
||||||
$.html("div", {
|
|
||||||
class: "size-5 rounded shadow-inner border border-base-content/10 transition-colors",
|
|
||||||
style: `background-color: ${getColor()}`,
|
|
||||||
}),
|
|
||||||
...rest,
|
...rest,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
$.html("div", {
|
||||||
|
class: "size-5 rounded-sm shadow-inner border border-black/10 shrink-0",
|
||||||
|
style: () => `background-color: ${getColor()}`,
|
||||||
}),
|
}),
|
||||||
|
label ? $.html("span", { class: "opacity-80" }, label) : null,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
ui.If(isOpen, () =>
|
ui.If(isOpen, () =>
|
||||||
$.html(
|
$.html(
|
||||||
@@ -624,7 +609,7 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -644,7 +629,7 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
const checkEl = $.html("input", {
|
const checkEl = $.html("input", {
|
||||||
...rest,
|
...rest,
|
||||||
type: "checkbox",
|
type: "checkbox",
|
||||||
class: () => (toggle() ? "toggle" : "checkbox"),
|
class: () => (val(toggle) ? "toggle" : "checkbox"),
|
||||||
$checked: $value,
|
$checked: $value,
|
||||||
onchange: (e) => $value?.(e.target.checked),
|
onchange: (e) => $value?.(e.target.checked),
|
||||||
});
|
});
|
||||||
@@ -709,8 +694,11 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
$.html("dialog", { ...rest, class: "modal modal-open" }, [
|
$.html("dialog", { ...rest, class: "modal modal-open" }, [
|
||||||
$.html("div", { class: "modal-box" }, [
|
$.html("div", { class: "modal-box" }, [
|
||||||
title ? $.html("h3", { class: "text-lg font-bold mb-4" }, title) : null,
|
title ? $.html("h3", { class: "text-lg font-bold mb-4" }, title) : null,
|
||||||
children,
|
typeof children === "function" ? children() : children,
|
||||||
$.html("div", { class: "modal-action flex gap-2" }, [buttons, ui.Button({ onclick: close }, tt("close"))]),
|
$.html("div", { class: "modal-action flex gap-2" }, [
|
||||||
|
...(Array.isArray(buttons) ? buttons : [buttons]).filter(Boolean),
|
||||||
|
ui.Button({ onclick: close }, tt("close")()),
|
||||||
|
]),
|
||||||
]),
|
]),
|
||||||
$.html(
|
$.html(
|
||||||
"form",
|
"form",
|
||||||
@@ -719,7 +707,7 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
class: "modal-backdrop",
|
class: "modal-backdrop",
|
||||||
onclick: (e) => (e.preventDefault(), close()),
|
onclick: (e) => (e.preventDefault(), close()),
|
||||||
},
|
},
|
||||||
$.html("button", "close"),
|
[$.html("button", {}, "close")],
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
@@ -727,23 +715,31 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
|
|
||||||
/** DROPDOWN */
|
/** DROPDOWN */
|
||||||
ui.Dropdown = (props, children) => {
|
ui.Dropdown = (props, children) => {
|
||||||
const { label, ...rest } = props;
|
const { label, icon, ...rest } = props;
|
||||||
|
|
||||||
return $.html(
|
return $.html(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
...rest,
|
...rest,
|
||||||
class: joinClass("dropdown", props.$class || props.class),
|
class: () => `dropdown ${val(props.$class) || props.class || ""}`,
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
label ? $.html("div", { tabindex: 0, role: "button", class: "btn m-1" }, label) : null,
|
|
||||||
$.html(
|
$.html(
|
||||||
"div",
|
"div",
|
||||||
{
|
{
|
||||||
tabindex: 0,
|
tabindex: 0,
|
||||||
class: "dropdown-content z-[50] p-2 shadow bg-base-100 rounded-box min-w-max",
|
role: "button",
|
||||||
|
class: "btn m-1 flex items-center gap-2",
|
||||||
},
|
},
|
||||||
children,
|
[icon ? (typeof icon === "function" ? icon() : icon) : null, label ? (typeof label === "function" ? label() : label) : null],
|
||||||
|
),
|
||||||
|
$.html(
|
||||||
|
"ul",
|
||||||
|
{
|
||||||
|
tabindex: 0,
|
||||||
|
class: "dropdown-content z-[50] menu p-2 shadow bg-base-100 rounded-box min-w-max border border-base-300",
|
||||||
|
},
|
||||||
|
[typeof children === "function" ? children() : children],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -904,21 +900,35 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
ui.Toast = (message, type = "alert-success", duration = 3500) => {
|
ui.Toast = (message, type = "alert-success", duration = 3500) => {
|
||||||
let container = document.getElementById("sigpro-toast-container");
|
let container = document.getElementById("sigpro-toast-container");
|
||||||
if (!container) {
|
if (!container) {
|
||||||
container = $.html("div", { id: "sigpro-toast-container", class: "fixed top-0 right-0 z-[9999] p-4 flex flex-col gap-2" });
|
container = $.html("div", {
|
||||||
|
id: "sigpro-toast-container",
|
||||||
|
class: "fixed top-0 right-0 z-[9999] p-4 flex flex-col gap-2",
|
||||||
|
});
|
||||||
document.body.appendChild(container);
|
document.body.appendChild(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
const runtime = $.view(() => {
|
const runtime = $.view(() => {
|
||||||
const el = $.html("div", { class: `alert alert-soft ${type} shadow-lg transition-all duration-300 translate-x-10 opacity-0` }, [
|
const el = $.html(
|
||||||
$.html("span", message),
|
"div",
|
||||||
ui.Button({ class: "btn-xs btn-circle btn-ghost", onclick: () => remove() }, "✕"),
|
{
|
||||||
]);
|
class: `alert alert-soft ${type} shadow-lg transition-all duration-300 translate-x-10 opacity-0`,
|
||||||
|
},
|
||||||
|
[
|
||||||
|
$.html("span", typeof message === "function" ? message() : message),
|
||||||
|
ui.Button(
|
||||||
|
{
|
||||||
|
class: "btn-xs btn-circle btn-ghost",
|
||||||
|
onclick: () => remove(),
|
||||||
|
},
|
||||||
|
"✕",
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
const remove = () => {
|
const remove = () => {
|
||||||
el.classList.add("translate-x-full", "opacity-0");
|
el.classList.add("translate-x-full", "opacity-0");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
runtime.destroy();
|
runtime.destroy();
|
||||||
el.remove();
|
|
||||||
if (!container.hasChildNodes()) container.remove();
|
if (!container.hasChildNodes()) container.remove();
|
||||||
}, 300);
|
}, 300);
|
||||||
};
|
};
|
||||||
@@ -928,7 +938,10 @@ export const UI = ($, defaultLang = "es") => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
container.appendChild(runtime.container);
|
container.appendChild(runtime.container);
|
||||||
requestAnimationFrame(() => runtime.container.firstChild.classList.remove("translate-x-10", "opacity-0"));
|
requestAnimationFrame(() => {
|
||||||
|
const el = runtime.container.firstElementChild;
|
||||||
|
if (el) el.classList.remove("translate-x-10", "opacity-0");
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/** LOADING */
|
/** LOADING */
|
||||||
|
|||||||
Reference in New Issue
Block a user