@r74tech/docusaurus-plugin-panzoom
Version:
A plugin to enable the panzoom component on SVG and other elements
155 lines (154 loc) • 6.05 kB
JavaScript
;
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;