UNPKG

@smkit/ui

Version:

UI Kit of SberMarketing

106 lines (105 loc) 3.45 kB
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(); } }