UNPKG

@r74tech/docusaurus-plugin-panzoom

Version:

A plugin to enable the panzoom component on SVG and other elements

155 lines (154 loc) 6.05 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const panzoom_1 = __importDefault(require("@panzoom/panzoom")); const PanzoomPluginOptions_1 = require("./PanzoomPluginOptions"); const zoom_in_1 = __importDefault(require("./img/zoom-in")); const zoom_out_1 = __importDefault(require("./img/zoom-out")); const zoom_reset_1 = __importDefault(require("./img/zoom-reset")); require("./styles/panzoom.css"); // eslint-disable-next-line @typescript-eslint/no-require-imports const config = require('@generated/docusaurus.config').default; const { themeConfig } = config; const { zoom } = themeConfig; const { selectors = ['div.mermaid[data-processed="true"]', 'div.docusaurus-mermaid-container', '.drawio'], wrap = true, timeout = 1000, excludeClass = 'panzoom-exclude', toolbar: { enabled = false, position = PanzoomPluginOptions_1.PanZoomPluginToolbarPosition.TopRight, opacity = 0 } = {}, enableWheelZoom = true, enableWheelZoomWithShift = false, enableDoubleClickResetZoom = true, restrictZoomOutBeyondOrigin = false, ...panZoomConfig } = zoom; /** * Creates a toolbar with zoom controls for a panzoom instance * * @param container The container element to append the toolbar to * @param instance The panzoom instance to control * @param position The position of the toolbar */ const createToolbar = (container, instance, position) => { const toolbar = document.createElement('div'); toolbar.className = `panzoom-toolbar panzoom-toolbar-${position} ${excludeClass}`; // Apply custom opacity from configuration toolbar.style.opacity = opacity.toString(); // Prevent double-click events from bubbling up to the container // By default the panzoom library will reset on double click toolbar.addEventListener('dblclick', (e) => { e.stopPropagation(); }); // Helper function to create toolbar buttons const createButton = (svg, title, action) => { const button = document.createElement('button'); button.innerHTML = svg; button.title = title; button.className = excludeClass; button.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); action(); }); return button; }; // Create and append all buttons const buttons = [ // Zoom in createButton(zoom_in_1.default, 'Zoom in', () => { instance.zoomIn(); }), // Zoom out createButton(zoom_out_1.default, 'Zoom out', () => { if (!restrictZoomOutBeyondOrigin) { instance.zoomOut(); return; } if (instance.getScale() > 1) { instance.zoomOut(); } }), // Reset zoom createButton(zoom_reset_1.default, 'Reset zoom', () => { instance.reset(); }), ]; buttons.forEach((button) => toolbar.appendChild(button)); container.appendChild(toolbar); }; /** * Attach event listeners to the element where panzoom is applied. * The listeners to add are based on the configuration options provided. * * @param element The element to add event listeners to * @param instance The panzoom instance to control */ const addEventListeners = (element, instance) => { const handleZoomWithWheel = (event) => { if (restrictZoomOutBeyondOrigin) { // Allow zooming in or zooming out only to the original size if (event.deltaY < 0 || (event.deltaY > 0 && instance.getScale() > 1)) { instance.zoomWithWheel(event); } } else { instance.zoomWithWheel(event); } }; // Handle the wheel zoom functionality if at least one of the options is enabled if (enableWheelZoom || enableWheelZoomWithShift) { element.addEventListener('wheel', (event) => { // Handle zoom with shift key if (enableWheelZoomWithShift && event.shiftKey) { handleZoomWithWheel(event); return; } // Handle regular zoom if (enableWheelZoom && !event.shiftKey) { handleZoomWithWheel(event); } }); } // Handle double-click reset zoom if (enableDoubleClickResetZoom) { element.addEventListener('dblclick', () => { instance.reset(); }); } }; /** * Main work method to zoom the set of elements. You can pass in global options to the pan zoom component * as well as control whether the items will be wrapped. * * @param selectors */ const zoomElements = (selectors) => { const foundElements = []; selectors.forEach((selector) => { foundElements.push(...document.querySelectorAll(selector)); }); foundElements.forEach((element) => { const instance = (0, panzoom_1.default)(element, { excludeClass, ...panZoomConfig }); let container; if (wrap) { const wrapper = document.createElement('div'); wrapper.setAttribute('style', 'overflow: hidden; position: relative;'); element.parentElement?.insertBefore(wrapper, element); wrapper.appendChild(element); container = wrapper; } else { const htmlElement = element; htmlElement.style.position = 'relative'; container = htmlElement; } addEventListeners(container, instance); // Add toolbar if enabled if (enabled) { createToolbar(container, instance, position); } }); }; /** * Client module implementation. Wait a bit before trying this, some components like mermaid take a second to process / render */ const ZoomModule = { onRouteDidUpdate() { setTimeout(() => { zoomElements(selectors); }, timeout); }, }; exports.default = ZoomModule;