Files
sigpro-ui/src/components/Tabs.js
2026-04-13 12:09:35 +02:00

65 lines
1.9 KiB
JavaScript

// components/Tabs.js
// import { $, Tag, For } from "../sigpro.js";
import { val, ui } from "../core/utils.js";
/**
* Tabs component
*
* daisyUI classes used:
* - tabs, tabs-box, tabs-lift, tabs-border
* - tab, tab-content
* - bg-base-100, border-base-300, p-6
*/
export const Tabs = (props) => {
const { items, class: className, ...rest } = props;
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()) activeIndex(idx);
});
// Contenedor principal con las clases de DaisyUI
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;
// Botón (tab)
const button = Tag("button", {
class: () => ui("tab", isActive() ? "tab-active" : ""),
onclick: (e) => {
e.preventDefault();
if (!val(item.disabled)) {
if (item.onclick) item.onclick();
activeIndex(i);
}
}
});
// Asignar etiqueta (puede ser texto o nodo)
const label = val(item.label);
if (label instanceof Node) {
button.replaceChildren(label);
} else {
button.textContent = String(label);
}
elements.push(button);
// Contenido (tab-content) - borde exterior estático
const panel = Tag("div", {
class: "tab-content bg-base-100 border-base-300 p-6",
style: () => isActive() ? "display: block" : "display: none"
}, [
// Contenedor interno con animación
Tag("div", { class: "tab-content-inner" }, () => val(item.content))
]);
elements.push(panel);
}
return elements;
});
};