@smkit/ui
Version:
UI Kit of SberMarketing
106 lines (105 loc) • 3.45 kB
JavaScript
import { get, writable } from 'svelte/store';
import { getContext, onDestroy, setContext } from 'svelte';
export class Popover {
cords = writable();
show = writable();
position = writable();
trigger = writable();
level = writable({ index: 0, children: [] });
parent;
root;
dropdown;
document;
constructor({ show, position, cords, } = {}) {
this.show.set(!!show);
this.position.set(position ?? 'right');
setContext('self', this);
this.cords.set(cords);
this.parent = getContext('popover') || null;
// Инициализация уровня
if (this.parent) {
this.parent.level.update((parentLevel) => {
parentLevel.children.push(this); // Добавление текущего Popover в дочерние
this.level.set({ index: parentLevel.index + 1, children: [] }); // Установка уровня
return parentLevel;
});
}
else {
this.level.set({ index: 0, children: [] }); // Если родителя нет, создаем корневой уровень
}
setContext('popover', this);
// Удаление текущего Popover из родителя при разрушении из стора
onDestroy(() => {
if (this.parent) {
this.parent.level.update((parentLevel) => {
parentLevel.children = parentLevel.children.filter((child) => child !== this);
return parentLevel;
});
}
});
}
static getParent() {
return getContext('popover') || null;
}
hasChildren() {
let hasChildren = false;
this.level.subscribe((level) => {
hasChildren = level.children.length > 0;
})();
return hasChildren;
}
get stores() {
return { show: this.show, position: this.position, trigger: this.trigger, cords: this.cords };
}
static get self() {
return getContext('self');
}
setTrigger(node, event) {
this.trigger.set({ node, event });
}
close() {
this.show.set(false);
}
closeCascade() {
this.show.set(false);
if (this.parent) {
this.parent.closeCascade();
}
}
closeChildren(controller) {
const { children } = get(controller.level);
children.forEach((child) => {
child.close();
});
}
closeRecursive = (controller) => {
controller.close();
const { children } = get(controller.level);
if (children && children.length > 0) {
children.forEach((child) => {
child.closeRecursive(child);
child.close();
});
}
};
open() {
this.show.set(true);
if (this.parent) {
this.parent.level.update((parentLevel) => {
parentLevel.children.forEach((child) => {
if (child !== this) {
child.closeRecursive(child);
child.close();
}
});
return parentLevel;
});
}
}
spawn(x, y) {
if (this.document && this.root)
this.document.body.appendChild(this.root);
this.cords.set([x, y]);
this.open();
}
}