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, }; };