UNPKG

@kitten-science/kitten-scientists

Version:

Add-on for the wonderful incremental browser game: https://kittensgame.com/web/

117 lines 4.42 kB
import { is } from "@oliversalzburg/js-utils/data/nil.js"; import { ExpandoButton } from "./buttons/ExpandoButton.js"; import { Container } from "./Container.js"; import stylesSettingListItem from "./SettingListItem.module.css"; import { UiComponent } from "./UiComponent.js"; /** * A `Panel` is a section of the UI that can be expanded and collapsed * through an expando button. * The panel also has a head element, which is extended to create the panel * behavior. */ export class CollapsiblePanel extends UiComponent { container; expando; head; _mainChildVisible; get isExpanded() { return this._mainChildVisible; } /** * Constructs a settings panel that is used to contain a single child element. * * @param host A reference to the host. * @param head Another component to host in the head of the panel. * @param options Options for this panel. */ constructor(parent, head, options) { super(parent, options); this.head = head; this.container = new Container(this); this.container.element.addClass(stylesSettingListItem.panelContent); // The expando button for this panel. const expando = new ExpandoButton(parent, { onClick: () => this.toggle(), }); head.head.addChild(expando); head.element.append(this.container.element); if (options?.initiallyExpanded) { this.container.element.removeClass(stylesSettingListItem.hidden); expando.setExpanded(); } else { this.container.element.addClass(stylesSettingListItem.hidden); } this._mainChildVisible = options?.initiallyExpanded ?? false; this.element = head.element; this.expando = expando; this.addChildren([this.head, this.container]); } toString() { return `[${CollapsiblePanel.name}#${this.componentId}]`; } addChildHead(child) { this.head.addChild(child); return this; } addChildrenHead(children) { for (const child of children ?? []) { this.head.addChild(child); } return this; } addChildContent(child) { this.container.addChild(child); return this; } addChildrenContent(children) { for (const child of children ?? []) { this.container.addChild(child); } return this; } /** * Control the visibility of the panel's contents. * * @param expand Should the panel be expanded? If not set, the panel is toggled. * @param toggleNested Also toggle all panels inside this panel? */ toggle(expand = undefined, toggleNested = false) { const visible = expand !== undefined ? expand : !this._mainChildVisible; if (visible !== this._mainChildVisible) { this._mainChildVisible = visible; if (this._mainChildVisible) { // Refresh panel UI on expand. this.container.requestRefresh(true); // Show the DOM element. this.container.element.removeClass(stylesSettingListItem.hidden); // Reflect expanded state on expando. this.expando.setExpanded(); // Reflect expanded state for CSS. this.head.element.addClass(stylesSettingListItem.expanded); // This is NOT a DOM event! It can only be caught by listening on this panel directly. this.element[0].dispatchEvent(new CustomEvent("panelShown")); } else { this.container.element.addClass(stylesSettingListItem.hidden); this.expando.setCollapsed(); this.head.element.removeClass(stylesSettingListItem.expanded); this.element[0].dispatchEvent(new CustomEvent("panelHidden")); } } if (toggleNested) { const toggleChildren = (children) => { for (const child of children) { if (is(child, CollapsiblePanel)) { child.toggle(expand, toggleNested); } else { toggleChildren(child.children); } } }; toggleChildren(this.children); } } } //# sourceMappingURL=CollapsiblePanel.js.map