Tabs Con pestañas cerrables
This commit is contained in:
110
docs/sigpro-ui.min.js
vendored
110
docs/sigpro-ui.min.js
vendored
@@ -33,7 +33,7 @@
|
||||
val: () => val,
|
||||
ui: () => ui,
|
||||
tt: () => tt,
|
||||
getIcon: () => getIcon,
|
||||
getIcon: () => getIcon2,
|
||||
Watch: () => Watch2,
|
||||
Tooltip: () => Tooltip,
|
||||
Toast: () => Toast,
|
||||
@@ -645,11 +645,11 @@
|
||||
__export(exports_utils, {
|
||||
val: () => val,
|
||||
ui: () => ui,
|
||||
getIcon: () => getIcon
|
||||
getIcon: () => getIcon2
|
||||
});
|
||||
var val = (t) => typeof t === "function" ? t() : t;
|
||||
var ui = (baseClass, additionalClassOrFn) => typeof additionalClassOrFn === "function" ? () => `${baseClass} ${additionalClassOrFn() || ""}`.trim() : `${baseClass} ${additionalClassOrFn || ""}`.trim();
|
||||
var getIcon = (icon) => {
|
||||
var getIcon2 = (icon) => {
|
||||
if (!icon)
|
||||
return null;
|
||||
if (typeof icon === "function") {
|
||||
@@ -710,7 +710,7 @@
|
||||
role: "alert",
|
||||
class: ui("alert", allClasses)
|
||||
}, () => [
|
||||
getIcon(iconMap[type]),
|
||||
getIcon2(iconMap[type]),
|
||||
Tag("div", { class: "flex-1" }, [
|
||||
Tag("span", {}, [typeof content === "function" ? content() : content])
|
||||
]),
|
||||
@@ -779,8 +779,8 @@
|
||||
tel: "icon-[lucide--phone]",
|
||||
url: "icon-[lucide--link]"
|
||||
};
|
||||
const leftIcon = icon ? getIcon(icon) : iconMap[type] ? getIcon(iconMap[type]) : null;
|
||||
const getPasswordIcon = () => getIcon(visible() ? "icon-[lucide--eye-off]" : "icon-[lucide--eye]");
|
||||
const leftIcon = icon ? getIcon2(icon) : iconMap[type] ? getIcon2(iconMap[type]) : null;
|
||||
const getPasswordIcon = () => getIcon2(visible() ? "icon-[lucide--eye-off]" : "icon-[lucide--eye]");
|
||||
const paddingLeft = leftIcon ? "pl-10" : "";
|
||||
const paddingRight = isPassword ? "pr-10" : "";
|
||||
const buttonSize = () => {
|
||||
@@ -937,7 +937,7 @@
|
||||
});
|
||||
var Button = (props, children) => {
|
||||
const { class: className, loading, icon, ...rest } = props;
|
||||
const iconEl = getIcon(icon);
|
||||
const iconEl = getIcon2(icon);
|
||||
return Tag("button", {
|
||||
...rest,
|
||||
class: ui("btn", className),
|
||||
@@ -1133,7 +1133,7 @@
|
||||
placeholder: placeholder || (isRangeMode() ? "Seleccionar rango..." : "Seleccionar fecha..."),
|
||||
value: displayValue,
|
||||
readonly: true,
|
||||
icon: getIcon("icon-[lucide--calendar]"),
|
||||
icon: getIcon2("icon-[lucide--calendar]"),
|
||||
onclick: (e) => {
|
||||
e.stopPropagation();
|
||||
isOpen(!isOpen());
|
||||
@@ -1146,15 +1146,15 @@
|
||||
}, [
|
||||
Tag("div", { class: "flex justify-between items-center mb-4 gap-1" }, [
|
||||
Tag("div", { class: "flex gap-0.5" }, [
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, getIcon("icon-[lucide--chevrons-left]")),
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => move(-1) }, getIcon("icon-[lucide--chevron-left]"))
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(-1) }, getIcon2("icon-[lucide--chevrons-left]")),
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => move(-1) }, getIcon2("icon-[lucide--chevron-left]"))
|
||||
]),
|
||||
Tag("span", { class: "font-bold uppercase flex-1 text-center" }, [
|
||||
() => internalDate().toLocaleString("es-ES", { month: "short", year: "numeric" })
|
||||
]),
|
||||
Tag("div", { class: "flex gap-0.5" }, [
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => move(1) }, getIcon("icon-[lucide--chevron-right]")),
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(1) }, getIcon("icon-[lucide--chevrons-right]"))
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => move(1) }, getIcon2("icon-[lucide--chevron-right]")),
|
||||
Tag("button", { type: "button", class: "btn btn-ghost btn-xs px-1", onclick: () => moveYear(1) }, getIcon2("icon-[lucide--chevrons-right]"))
|
||||
])
|
||||
]),
|
||||
Tag("div", { class: "grid grid-cols-7 gap-1", onmouseleave: () => hoverDate(null) }, [
|
||||
@@ -1362,7 +1362,7 @@
|
||||
role: "button",
|
||||
class: "btn btn-lg btn-circle btn-primary shadow-2xl"
|
||||
}, [
|
||||
icon ? getIcon(icon) : null,
|
||||
icon ? getIcon2(icon) : null,
|
||||
!icon && label ? label : null
|
||||
]),
|
||||
...val(actions).map((act) => Tag("div", { class: "flex items-center gap-3 transition-all duration-300" }, [
|
||||
@@ -1374,7 +1374,7 @@
|
||||
e.stopPropagation();
|
||||
act.onclick?.(e);
|
||||
}
|
||||
}, [act.icon ? getIcon(act.icon) : act.text || ""])
|
||||
}, [act.icon ? getIcon2(act.icon) : act.text || ""])
|
||||
]))
|
||||
]);
|
||||
};
|
||||
@@ -1449,7 +1449,7 @@
|
||||
}
|
||||
}, [
|
||||
Tag("div", { class: "flex items-center gap-3 w-full" }, [
|
||||
getIcon("icon-[lucide--upload]"),
|
||||
getIcon2("icon-[lucide--upload]"),
|
||||
Tag("span", { class: "text-sm opacity-70 truncate grow text-left" }, "Arrastra o selecciona archivos..."),
|
||||
Tag("span", { class: "text-[10px] opacity-40 shrink-0" }, `Máx ${max}MB`)
|
||||
]),
|
||||
@@ -1478,7 +1478,7 @@
|
||||
e.stopPropagation();
|
||||
removeFile(index);
|
||||
}
|
||||
}, [getIcon("icon-[lucide--x]")])
|
||||
}, [getIcon2("icon-[lucide--x]")])
|
||||
]), (file) => file.name + file.lastModified)
|
||||
]))
|
||||
]);
|
||||
@@ -1830,18 +1830,57 @@
|
||||
const itemsSignal = typeof items === "function" ? items : () => items || [];
|
||||
const activeIndex = $(0);
|
||||
Watch(() => {
|
||||
const idx = itemsSignal().findIndex((it) => val(it.active) === true);
|
||||
if (idx !== -1 && idx !== activeIndex())
|
||||
const list = itemsSignal();
|
||||
const idx = list.findIndex((it) => val(it.active) === true);
|
||||
if (idx !== -1 && activeIndex() !== idx) {
|
||||
activeIndex(idx);
|
||||
}
|
||||
});
|
||||
const removeTab = (indexToRemove, item) => {
|
||||
if (item.onClose)
|
||||
item.onClose();
|
||||
const currentItems = itemsSignal();
|
||||
const newItems = currentItems.filter((_, idx) => idx !== indexToRemove);
|
||||
const isWritableSignal = typeof items === "function" && !items._isComputed;
|
||||
if (!isWritableSignal) {
|
||||
console.warn("Tabs: items must be a writable signal to support closable tabs");
|
||||
return;
|
||||
}
|
||||
items(newItems);
|
||||
if (newItems.length === 0)
|
||||
return;
|
||||
let newActive = activeIndex();
|
||||
if (indexToRemove < newActive)
|
||||
newActive--;
|
||||
else if (indexToRemove === newActive)
|
||||
newActive = Math.min(newActive, newItems.length - 1);
|
||||
activeIndex(newActive);
|
||||
};
|
||||
return Tag("div", { ...rest, class: ui("tabs", className) }, () => {
|
||||
const list = itemsSignal();
|
||||
const elements = [];
|
||||
for (let i = 0;i < list.length; i++) {
|
||||
const item = list[i];
|
||||
const isActive = () => activeIndex() === i;
|
||||
const label = val(item.label);
|
||||
const labelNode = label instanceof Node ? label : document.createTextNode(String(label));
|
||||
const buttonChildren = [];
|
||||
if (item.closable) {
|
||||
const closeIcon = getIcon("icon-[lucide--x]");
|
||||
closeIcon.classList.add("w-3.5", "h-3.5", "ml-2", "cursor-pointer", "hover:opacity-70");
|
||||
closeIcon.onclick = (e) => {
|
||||
e.stopPropagation();
|
||||
removeTab(i, item);
|
||||
};
|
||||
const wrapper = Tag("span", { class: "flex items-center" }, [labelNode, closeIcon]);
|
||||
buttonChildren.push(wrapper);
|
||||
} else {
|
||||
buttonChildren.push(labelNode);
|
||||
}
|
||||
const button = Tag("button", {
|
||||
class: () => ui("tab", isActive() ? "tab-active" : ""),
|
||||
class: () => {
|
||||
const isActive = activeIndex() === i;
|
||||
return ui("tab", isActive ? "tab-active" : "");
|
||||
},
|
||||
onclick: (e) => {
|
||||
e.preventDefault();
|
||||
if (!val(item.disabled)) {
|
||||
@@ -1849,21 +1888,24 @@
|
||||
item.onclick();
|
||||
activeIndex(i);
|
||||
}
|
||||
}
|
||||
});
|
||||
const label = val(item.label);
|
||||
if (label instanceof Node) {
|
||||
button.replaceChildren(label);
|
||||
} else {
|
||||
button.textContent = String(label);
|
||||
}
|
||||
},
|
||||
title: item.tip || ""
|
||||
}, buttonChildren);
|
||||
elements.push(button);
|
||||
let contentNode;
|
||||
const rawContent = val(item.content);
|
||||
if (typeof rawContent === "function") {
|
||||
contentNode = rawContent();
|
||||
} else if (rawContent instanceof Node) {
|
||||
contentNode = rawContent;
|
||||
} else {
|
||||
contentNode = document.createTextNode(String(rawContent));
|
||||
}
|
||||
const inner = Tag("div", { class: "tab-content-inner" }, contentNode);
|
||||
const panel = Tag("div", {
|
||||
class: "tab-content bg-base-100 border-base-300 p-6",
|
||||
style: () => isActive() ? "display: block" : "display: none"
|
||||
}, [
|
||||
Tag("div", { class: "tab-content-inner" }, () => val(item.content))
|
||||
]);
|
||||
style: () => activeIndex() === i ? "display: block" : "display: none"
|
||||
}, inner);
|
||||
elements.push(panel);
|
||||
}
|
||||
return elements;
|
||||
@@ -1899,7 +1941,7 @@
|
||||
!isFirst ? Tag("hr", { class: () => prevCompleted() ? "bg-primary" : "" }) : null,
|
||||
Tag("div", { class: "timeline-start" }, [() => renderSlot(item.title)]),
|
||||
Tag("div", { class: "timeline-middle" }, [
|
||||
() => item.icon ? getIcon(item.icon) : getIcon(iconMap[itemType] || iconMap.success)
|
||||
() => item.icon ? getIcon2(item.icon) : getIcon2(iconMap[itemType] || iconMap.success)
|
||||
]),
|
||||
Tag("div", { class: "timeline-end timeline-box shadow-sm" }, [() => renderSlot(item.detail)]),
|
||||
!isLast ? Tag("hr", { class: () => isCompleted() ? "bg-primary" : "" }) : null
|
||||
@@ -1942,7 +1984,7 @@
|
||||
}
|
||||
};
|
||||
const ToastComponent = () => {
|
||||
const closeIcon = getIcon("icon-[lucide--x]");
|
||||
const closeIcon = getIcon2("icon-[lucide--x]");
|
||||
const el = Tag("div", {
|
||||
class: `alert alert-soft ${type} shadow-lg transition-all duration-300 translate-x-10 opacity-0 pointer-events-auto`
|
||||
}, [
|
||||
|
||||
Reference in New Issue
Block a user