@bokeh/bokehjs
Version:
Interactive, novel data visualization
120 lines • 4.29 kB
JavaScript
import { Pane, PaneView } from "../ui/pane";
import { div, px, InlineStyleSheet } from "../../core/dom";
import { Location } from "../../core/enums";
import { UIGestures } from "../../core/ui_gestures";
import { Or, Float, CSSLength } from "../../core/kinds";
import { assert } from "../../core/util/assert";
import { isNumber } from "../../core/util/types";
import * as drawers_css from "../../styles/drawers.css";
import * as icons_css from "../../styles/icons.css";
const { max } = Math;
const CSSSize = Or(Float, CSSLength);
export class DrawerView extends PaneView {
static __name__ = "DrawerView";
constructor(options) {
super(options);
this.on_pan_start = this.on_pan_start.bind(this);
this.on_pan = this.on_pan.bind(this);
this.on_pan_end = this.on_pan_end.bind(this);
}
sizing = new InlineStyleSheet("", "sizing");
stylesheets() {
return [...super.stylesheets(), icons_css.default, drawers_css.default, this.sizing];
}
handle_el = div({ class: drawers_css.handle });
contents_el = div({ class: drawers_css.contents });
toggle_el;
ui_gestures = new UIGestures(this.handle_el, this);
connect_signals() {
super.connect_signals();
this.ui_gestures.connect_signals();
const { location, open, resizable } = this.model.properties;
this.on_change(open, () => {
this.toggle(this.model.open);
});
this.on_change(location, () => {
this.class_list.remove(drawers_css.left, drawers_css.right, drawers_css.above, drawers_css.below);
this.class_list.add(drawers_css[this.model.location]);
});
this.on_change(resizable, () => {
this.class_list.toggle(drawers_css.resizable, this.model.resizable);
});
}
get self_target() {
return this.contents_el;
}
title(open) {
return open ? "Collapse" : "Expand";
}
render() {
super.render();
const { location, open, size, resizable } = this.model;
this.class_list.add(drawers_css[location]);
this.class_list.toggle(drawers_css.open, open);
this.class_list.toggle(drawers_css.resizable, resizable);
const icon_el = div({ class: drawers_css.chevron });
const title = this.title(open);
this.toggle_el = div({ class: drawers_css.toggle, title }, icon_el);
this.toggle_el.addEventListener("click", () => this.toggle());
this.shadow_el.append(this.contents_el, this.toggle_el, this.handle_el);
this.sizing.replace(`
:host {
--drawer-size: ${isNumber(size) ? px(size) : size};
}
`);
}
toggle(open) {
open = this.class_list.toggle(drawers_css.open, open);
this.toggle_el.title = this.title(open);
this.model.open = open;
}
state = null;
on_pan_start(_event) {
assert(this.state == null);
const styles = getComputedStyle(this.el);
this.state = {
width: parseFloat(styles.width),
height: parseFloat(styles.height),
};
this.class_list.add(drawers_css.resizing);
}
on_pan(event) {
assert(this.state != null);
const size = (() => {
const { width, height } = this.state;
const { dx, dy } = event;
switch (this.model.location) {
case "left": return max(width + dx, 0);
case "right": return max(width - dx, 0);
case "above": return max(height + dy, 0);
case "below": return max(height - dy, 0);
}
})();
this.sizing.replace(`
:host {
--drawer-size: ${size}px;
}
`);
}
on_pan_end(_event) {
assert(this.state != null);
this.state = null;
this.class_list.remove(drawers_css.resizing);
}
}
export class Drawer extends Pane {
static __name__ = "Drawer";
constructor(attrs) {
super(attrs);
}
static {
this.prototype.default_view = DrawerView;
this.define(({ Bool }) => ({
location: [Location],
open: [Bool, false],
size: [CSSSize, 300],
resizable: [Bool, false],
}));
}
}
//# sourceMappingURL=drawer.js.map