# presentation/components/panel.component.ts

> 94 lines of code and 9 definitions.

Tree: Site tree
Language: typescript
Layer: product
Canonical: https://banes-lab.com/anatomy/tree#file-presentation-components-panel-component-ts
Source text: https://banes-lab.com/assets/sources/source.6034d4ddcfa07294264c6dfc16febeea1affacb1871f90d8764a5a231562e927.generated.txt

## Definitions

- `createPanel` (lexical_declaration, line 77, exported)
- `bind` (lexical_declaration, line 30)
- `createControls` (lexical_declaration, line 56)
- `createControl` (lexical_declaration, line 17)
- `button` (lexical_declaration, line 18)
- `controls` (lexical_declaration, line 57)
- `stage` (lexical_declaration, line 78, exported)
- `element` (lexical_declaration, line 82, exported)
- `state` (lexical_declaration, line 87, exported)

## Used by

- [presentation/components/code.component.ts](https://banes-lab.com/source/tree/presentation/components/code.component.ts.md)

## Source

```typescript
import { ICON_BASE_CLASS, RESET_VIEW_ICON, ZOOM_IN_ICON, ZOOM_OUT_ICON } from "#configuration/icons/element.icons";
import {
    PANEL_CLASS,
    PANEL_CONTROLS_CLASS,
    PANEL_CONTROL_CLASS,
    PANEL_REVEAL_EVENT,
    PANEL_STAGE_CLASS,
    PANEL_ZOOM_CLASS,
    PANEL_ZOOM_STEP,
} from "#configuration/constants/panel.constants";
import { PANEL_HINT, RESET_VIEW_TITLE, ZOOM_IN_TITLE, ZOOM_OUT_TITLE } from "#configuration/strings/panel.strings";
import type { PanelHandle, PanelMode } from "#types/panel.types";
import { ORIGIN_VIEW } from "#core/analyzers/panel.analyzer";
import { PanelState } from "#presentation/components/stage.component";
import { createElement } from "#core/factories/element.factory";

const createControl = function createControl(icon: string, title: string, onClick: () => void): HTMLButtonElement {
    const button = createElement("button", {
        attributes: { "aria-label": title, title, type: "button" },
        children: [createElement("i", { className: `${ICON_BASE_CLASS} ${icon}` })],
        className: PANEL_CONTROL_CLASS,
    });
    button.addEventListener("click", (event) => {
        event.stopPropagation();
        onClick();
    });
    return button;
};

const bind = function bind(state: PanelState, element: HTMLElement): void {
    element.addEventListener("pointerdown", (event) => {
        state.press(event);
    });
    element.addEventListener("pointermove", (event) => {
        state.move(event);
    });
    element.addEventListener("pointerup", (event) => {
        state.release(event);
    });
    element.addEventListener("pointercancel", (event) => {
        state.release(event);
    });
    element.addEventListener("wheel", (event) => {
        state.wheel(event);
    });
    element.addEventListener("dblclick", () => {
        state.reset();
    });
    element.addEventListener(PANEL_REVEAL_EVENT, (event) => {
        if (event instanceof CustomEvent && typeof event.detail === "number") {
            state.reveal(event.detail);
        }
    });
};

const createControls = function createControls(state: PanelState): HTMLElement {
    const controls = createElement("div", {
        children: [
            createControl(ZOOM_OUT_ICON, ZOOM_OUT_TITLE, () => {
                state.zoomAtCenter(1 / PANEL_ZOOM_STEP);
            }),
            createControl(RESET_VIEW_ICON, RESET_VIEW_TITLE, () => {
                state.reset();
            }),
            createControl(ZOOM_IN_ICON, ZOOM_IN_TITLE, () => {
                state.zoomAtCenter(PANEL_ZOOM_STEP);
            }),
        ],
        className: PANEL_CONTROLS_CLASS,
    });
    controls.addEventListener("pointerdown", (event) => {
        event.stopPropagation();
    });
    return controls;
};

export const createPanel = function createPanel(content: Element, className: string, mode: PanelMode): PanelHandle {
    const stage = createElement("div", {
        children: [createElement("div", { children: [content], className: PANEL_ZOOM_CLASS })],
        className: PANEL_STAGE_CLASS,
    });
    const element = createElement("div", {
        attributes: { title: PANEL_HINT },
        children: [stage],
        className: `${PANEL_CLASS} ${className}`,
    });
    const state = new PanelState(element, stage, mode);
    element.append(createControls(state));
    bind(state, element);
    state.apply(ORIGIN_VIEW);
    return {
        element,
        reset: () => {
            state.reset();
        },
        view: () => state.view,
    };
};
```
