78 lines
2.3 KiB
JavaScript
78 lines
2.3 KiB
JavaScript
// components/Dropdown.js
|
|
// import { Tag, For, Watch } from "../sigpro.js";
|
|
import { ui } from "../core/utils.js";
|
|
|
|
/**
|
|
* Dropdown component - Solo soporta menús (items)
|
|
*
|
|
* daisyUI classes used:
|
|
* - dropdown, dropdown-content, dropdown-end, dropdown-top, dropdown-bottom
|
|
* - menu, btn
|
|
* - bg-base-100, shadow, rounded-box, border
|
|
* - z-50, p-2, w-52
|
|
* - m-1, flex, items-center, gap-2
|
|
*/
|
|
|
|
let currentOpen = null;
|
|
|
|
if (typeof window !== 'undefined' && !window.__dropdownHandlerRegistered) {
|
|
window.addEventListener('click', (e) => {
|
|
if (currentOpen && !currentOpen.contains(e.target)) {
|
|
currentOpen.open = false;
|
|
currentOpen = null;
|
|
}
|
|
});
|
|
window.__dropdownHandlerRegistered = true;
|
|
}
|
|
|
|
export const Dropdown = (props) => {
|
|
const { class: className, label, icon, items, ...rest } = props;
|
|
|
|
return Tag("details", {
|
|
...rest,
|
|
class: ui('dropdown', className),
|
|
}, [
|
|
Tag("summary", {
|
|
class: "btn m-1 flex items-center gap-2 list-none cursor-pointer",
|
|
style: "display: inline-flex;",
|
|
onclick: (e) => {
|
|
const details = e.currentTarget.closest('details');
|
|
if (currentOpen && currentOpen !== details) {
|
|
currentOpen.open = false;
|
|
}
|
|
setTimeout(() => {
|
|
currentOpen = details.open ? details : null;
|
|
}, 0);
|
|
}
|
|
}, [
|
|
() => icon ? (typeof icon === "function" ? icon() : icon) : null,
|
|
() => label ? (typeof label === "function" ? label() : label) : null
|
|
]),
|
|
Tag("ul", {
|
|
tabindex: "-1",
|
|
class: "dropdown-content z-[50] menu p-2 shadow bg-base-100 rounded-box w-52 border border-base-300"
|
|
}, [
|
|
() => {
|
|
const currentItems = typeof items === "function" ? items() : (items || []);
|
|
return currentItems.map(item =>
|
|
Tag("li", {}, [
|
|
Tag("a", {
|
|
class: item.class || "",
|
|
onclick: (e) => {
|
|
if (item.onclick) item.onclick(e);
|
|
const details = e.currentTarget.closest('details');
|
|
if (details) {
|
|
details.open = false;
|
|
if (currentOpen === details) currentOpen = null;
|
|
}
|
|
}
|
|
}, [
|
|
item.icon ? Tag("span", {}, item.icon) : null,
|
|
Tag("span", {}, item.label)
|
|
])
|
|
])
|
|
);
|
|
}
|
|
])
|
|
]);
|
|
}; |