UNPKG

@bokeh/bokehjs

Version:

Interactive, novel data visualization

191 lines 5.51 kB
import { View } from "./view"; import { create_element, empty, InlineStyleSheet, ClassList } from "./dom"; import { isString } from "./util/types"; import { assert } from "./util/assert"; import base_css from "../styles/base.css"; export class DOMView extends View { static __name__ = "DOMView"; static tag_name = "div"; el; shadow_el; get bbox() { return undefined; } serializable_state() { const state = super.serializable_state(); const { bbox } = this; return bbox != null ? { ...state, bbox: bbox.round() } : state; } get children_el() { return this.shadow_el ?? this.el; } initialize() { super.initialize(); this.el = this._create_element(); } remove() { this.el.remove(); super.remove(); } stylesheets() { return []; } css_classes() { return []; } rerender() { this.render(); this.r_after_render(); } render_to(target) { this.render(); target.appendChild(this.el); } after_render() { this.reposition(); } r_after_render() { for (const child_view of this.children()) { if (child_view instanceof DOMView) { child_view.r_after_render(); } } this.after_render(); this._was_built = true; } _create_element() { return create_element(this.constructor.tag_name, {}); } reposition(_displayed) { } _was_built = false; /** * Build a top-level DOM view (e.g. during embedding). */ build(target) { assert(this.is_root); this.render_to(target); this.r_after_render(); this.notify_finished(); } /** * Define where to render this element or let the parent decide. * * This is useful when creating "floating" components or adding * components to canvas' layers. */ rendering_target() { return null; } } export class DOMElementView extends DOMView { static __name__ = "DOMElementView"; class_list; initialize() { super.initialize(); this.class_list = new ClassList(this.el.classList); } get self_target() { return this.el; } } export class DOMComponentView extends DOMElementView { static __name__ = "DOMComponentView"; get self_target() { return this.shadow_el; } initialize() { super.initialize(); this.shadow_el = this.el.attachShadow({ mode: "open" }); } _base_style = new InlineStyleSheet(base_css, "base"); _css_vars = new InlineStyleSheet("", "vars"); stylesheets() { return [...super.stylesheets(), this._base_style]; } /** * Baseline stylesheets, e.g. imported CSS modules. */ static_stylesheets() { return this.stylesheets(); } /** * Stylesheets computed by the component. */ computed_stylesheets() { return [this._css_vars]; } /** * Other stylesheets, e.g. provided by user. */ user_stylesheets() { return []; } empty() { empty(this.shadow_el); this.class_list.clear(); this._applied_css_classes = []; this._applied_stylesheets = []; for (const stylesheet of this.computed_stylesheets()) { if (!stylesheet.persistent) { stylesheet.clear(); } } } render() { this.empty(); this._update_stylesheets(); this._apply_html_attributes(); } _applied_html_attributes = []; _apply_html_attributes() { this._update_css_classes(); } reposition(_displayed) { this._update_css_variables(); // TODO remove this when node invalidation is implemented } *_stylesheets() { yield* this.static_stylesheets(); yield* this.computed_stylesheets(); yield* this.user_stylesheets(); } *_css_classes() { yield `bk-${this.model.type.replace(/\./g, "-")}`; yield* this.css_classes(); } *_css_variables() { } _applied_stylesheets = []; _apply_stylesheets(stylesheets) { const resolved_stylesheets = stylesheets.map((style) => isString(style) ? new InlineStyleSheet(style) : style); this._applied_stylesheets.push(...resolved_stylesheets); resolved_stylesheets.forEach((stylesheet) => stylesheet.install(this.shadow_el)); } _applied_css_classes = []; _apply_css_classes(classes) { this._applied_css_classes.push(...classes); this.class_list.add(...classes); } _update_stylesheets() { this._applied_stylesheets.forEach((stylesheet) => stylesheet.uninstall()); this._applied_stylesheets = []; this._apply_stylesheets([...this._stylesheets()]); } _update_css_classes() { this.class_list.remove(this._applied_css_classes); this._applied_css_classes = []; this._apply_css_classes([...this._css_classes()]); } _update_css_variables() { const vars = []; for (const [name, value] of this._css_variables()) { const full_name = name.startsWith("--") ? name : `--${name}`; vars.push(`${full_name}: ${value};\n`); } if (vars.length == 0) { this._css_vars.clear(); } else { this._css_vars.replace(`:host {\n${vars}}`); } } } //# sourceMappingURL=dom_view.js.map