UNPKG

@discoveryjs/discovery

Version:

Frontend framework for rapid data (JSON) analysis, shareable serverless reports and dashboards

154 lines (153 loc) 4.48 kB
import { createElement, createFragment } from "../core/utils/dom.js"; import { ContentRect } from "../core/utils/size.js"; import { version } from "../version.js"; export class NavItemArray { items; host; baseConfig; constructor(host, baseConfig) { this.host = host; this.baseConfig = baseConfig; this.items = []; } insert(config, position, ref) { switch (position) { case "after": position = this.items.findIndex((item) => item.name === ref); if (position === -1) { position = this.items.length; } else { position++; } break; case "before": position = this.items.findIndex((item) => item.name === ref); if (position === -1) { position = this.items.length; } break; default: if (position === void 0 || isNaN(position) || !isFinite(position)) { position = this.items.length; } } position = Math.max(0, Math.min(this.items.length, position)); const composedConfig = this.host.view.composeConfig(this.baseConfig, config); this.items.splice(position, 0, composedConfig); } prepend(config) { this.insert(config, 0); } append(config) { this.insert(config); } before(name, config) { this.insert(config, "before", name); } after(name, config) { this.insert(config, "after", name); } replace(name, config) { const position = this.items.findIndex((item) => item.name === name); if (position !== -1) { this.items[position] = this.host.view.composeConfig(this.baseConfig, config); } else { this.insert(config); } } remove(name) { const position = this.items.findIndex((item) => item.name === name); if (position !== -1) { return this.items.splice(position, 1)[0]; } } } export * as buttons from "./buttons.js"; export class ViewModelNavigation extends NavItemArray { host; popup; data; context; config; primary; secondary; menu; contentRect; constructor(host, baseConfig = "nav-button") { super(host, baseConfig); const poweredByDiscovery = createElement("div", "powered-by-discoveryjs", [ "powered by ", createElement("a", { class: "view-link", href: "https://github.com/discoveryjs/discovery", target: "_blank" }, "Discovery.js"), ` ${version}` ]); this.host = host; this.popup = null; this.data = null; this.context = null; this.primary = new NavItemArray(host, "nav-button"); this.secondary = this; this.menu = new NavItemArray(host, "menu-item"); this.config = [ this.secondary.items, { view: "nav-button", name: "burger", whenData: true, data: async () => { const fragment = createFragment(); await this.host.view.render(fragment, this.menu.items, this.host.data, { ...this.context, hide: () => this.popup?.hide() }); return [...fragment.childNodes].filter((node) => node.nodeType === 1 || node.nodeType === 3); }, onClick: (el, nodes) => { const popup = this.popup || new this.host.view.Popup({ className: "discovery-nav-popup" }); if (!this.popup) { this.popup = popup; popup.el.addEventListener("click", ({ target }) => { if (target.closest("a[href]")) { setTimeout(() => popup.hide(), 50); } }, true); } popup.toggle(el, (el2) => el2.append(...nodes, poweredByDiscovery)); } }, this.primary.items ]; this.contentRect = new ContentRect(); this.contentRect.subscribe((size) => { const { container } = host.dom; if (container && size) { const { width, height } = size; container.style.setProperty("--discovery-nav-width", width + "px"); container.style.setProperty("--discovery-nav-height", height + "px"); } }); } render(el, data, context) { this.contentRect.observe(el); if (el) { this.data = data; this.context = { ...context, widget: this.host }; this.host.view.setViewRoot(el, "nav", { config: this.config, data: this.data, context: this.context }); el.innerHTML = ""; this.host.view.render(el, this.config, this.data, this.context); } } } ;