UNPKG

apexcharts

Version:

A JavaScript Chart Library

274 lines (250 loc) 6.58 kB
// @ts-check /** * Browser API abstraction layer for SSR support * Routes to either real browser APIs or SSR shims based on environment */ import { Environment } from '../utils/Environment.js' import { SSRDOMShim } from './DOMShim.js' /** @type {any} */ let shim = null /** @type {any} */ let xmlSerializerInstance = null /** @type {any} */ let domParserInstance = null /** * Browser API abstraction that works in both browser and Node.js */ export class BrowserAPIs { /** * Initialize the SSR shim if in SSR environment * Must be called before using other methods */ static init() { if (Environment.isSSR() && !shim) { shim = new SSRDOMShim() } } /** * Create an HTML element * @param {string} tagName - Element tag name * @returns {HTMLElement} HTML element */ static createElement(tagName) { if (Environment.isSSR()) { if (!shim) this.init() return shim.createElementNS(null, tagName) } return document.createElement(tagName) } /** * Create an SVG element with namespace * @param {string} namespaceURI - Namespace URI * @param {string} qualifiedName - Element tag name * @returns {HTMLElement} created element */ static createElementNS(namespaceURI, qualifiedName) { if (Environment.isSSR()) { if (!shim) this.init() return shim.createElementNS(namespaceURI, qualifiedName) } return /** @type {HTMLElement} */ ( document.createElementNS(namespaceURI, qualifiedName) ) } /** * Create a text node * @param {string} data - Text content * @returns {Text|object} Text node */ static createTextNode(data) { if (Environment.isSSR()) { if (!shim) this.init() return shim.createTextNode(data) } return document.createTextNode(data) } /** * Query selector * @param {string} selector - CSS selector * @returns {Element|null} */ static querySelector(selector) { if (Environment.isSSR()) { return null } return document.querySelector(selector) } /** * Query selector all * @param {string} selector - CSS selector * @returns {NodeList|any[]} */ static querySelectorAll(selector) { if (Environment.isSSR()) { return [] } return document.querySelectorAll(selector) } /** * Get computed style for an element * @param {Element} element - Element to get styles for * @returns {CSSStyleDeclaration|object} */ static getComputedStyle(element) { if (Environment.isSSR()) { return {} } return window.getComputedStyle(element) } /** * Get bounding client rect for an element * @param {Element} element - Element to measure * @returns {DOMRect|object} */ static getBoundingClientRect(element) { if (Environment.isSSR()) { if (!shim) this.init() return shim.getBoundingClientRect(element) } return element ? element.getBoundingClientRect() : { width: 0, height: 0, top: 0, left: 0, right: 0, bottom: 0, x: 0, y: 0, } } /** * Get XMLSerializer instance * @returns {XMLSerializer|object} */ static getXMLSerializer() { if (Environment.isSSR()) { if (!shim) this.init() if (!xmlSerializerInstance) { xmlSerializerInstance = shim.createXMLSerializer() } return xmlSerializerInstance } if (!xmlSerializerInstance) { xmlSerializerInstance = new XMLSerializer() } return xmlSerializerInstance } /** * Get DOMParser instance * @returns {DOMParser|object} */ static getDOMParser() { if (Environment.isSSR()) { if (!shim) this.init() if (!domParserInstance) { domParserInstance = shim.createDOMParser() } return domParserInstance } if (!domParserInstance) { domParserInstance = new DOMParser() } return domParserInstance } /** * Add event listener to window * @param {string} event - Event name * @param {EventListenerOrEventListenerObject} handler - Event handler * @param {object} options - Event options */ static addWindowEventListener(event, handler, options) { if (Environment.isBrowser()) { window.addEventListener(event, handler, options) } // No-op in SSR } /** * Remove event listener from window * @param {string} event - Event name * @param {EventListenerOrEventListenerObject} handler - Event handler * @param {object} options - Event options */ static removeWindowEventListener(event, handler, options) { if (Environment.isBrowser()) { window.removeEventListener(event, handler, options) } // No-op in SSR } /** * Request animation frame * @param {FrameRequestCallback} callback - Callback function * @returns {number|null} */ static requestAnimationFrame(callback) { if (Environment.isBrowser()) { return window.requestAnimationFrame(callback) } // Execute immediately in SSR callback(0) return null } /** * Cancel animation frame * @param {number} id - Animation frame ID */ static cancelAnimationFrame(id) { if (Environment.isBrowser() && id) { window.cancelAnimationFrame(id) } // No-op in SSR } /** * Check if element exists * @param {Element} element - Element to check * @returns {boolean} */ static elementExists(element) { if (!element) return false if (Environment.isSSR()) { // In SSR, element is valid if it's our mock element // @ts-ignore — _ssrMode is an internal SSR-only property on mock elements return element._ssrMode === true || element.nodeName !== undefined } // In browser, check if element is in DOM return element.getRootNode ? element.getRootNode({ composed: true }) === document || element.isConnected : false } /** * Get window object (or null in SSR) * @returns {Window|null} */ static getWindow() { return Environment.isBrowser() ? window : null } /** * Get document object (or null in SSR) * @returns {Document|null} */ static getDocument() { return Environment.isBrowser() ? document : null } /** * Get the shim instance (for testing purposes) * @returns {SSRDOMShim|null} */ static _getShim() { return shim } /** * Reset the shim instance (for testing purposes) */ static _resetShim() { shim = null xmlSerializerInstance = null domParserInstance = null } }