import React from 'react'; import { createRoot } from 'react-dom/client'; import { App } from './App'; import type { WidgetConfig } from './types'; import './styles.css'; // Declare the global config injected by the WordPress plugin. We keep the SAME // window.AISTHETIX_CONFIG global the portable widget already reads. declare global { interface Window { AISTHETIX_CONFIG?: WidgetConfig; // Set true by App once it has bound its click handler to the plugin's // trigger button, so bootstrap.js can replay a cold first click without // racing React's effect timing. See assets/bootstrap.js. AISTHETIX_WIDGET_READY?: boolean; } } // Some themes/builders (e.g. via SVG sprites) can cause React to create HTML // elements in the SVG namespace, making them invisible. This patch forces known // HTML tags to always use the HTML namespace. const SVG_ONLY_TAGS = new Set( [ 'svg', 'g', 'path', 'circle', 'rect', 'line', 'polyline', 'polygon', 'text', 'tspan', 'defs', 'clipPath', 'mask', 'pattern', 'use', 'symbol', 'marker', 'linearGradient', 'radialGradient', 'stop', 'filter', 'feGaussianBlur', 'feOffset', 'feMerge', 'feMergeNode', 'feBlend', 'feColorMatrix', 'feComposite', 'feFlood', 'feImage', 'feMorphology', 'feTurbulence', 'animate', 'animateTransform', 'foreignObject', 'desc', 'title', 'metadata', 'image', 'switch', 'textPath', 'altGlyph', 'altGlyphDef', 'altGlyphItem', 'glyph', 'glyphRef', 'ellipse', ] ); const SVG_NS = 'http://www.w3.org/2000/svg'; const origCreateElementNS = document.createElementNS.bind( document ); document.createElementNS = function patchedCreateElementNS( namespaceURI: string, qualifiedName: string ) { if ( namespaceURI === SVG_NS && ! SVG_ONLY_TAGS.has( qualifiedName.toLowerCase() ) ) { return document.createElement( qualifiedName ); } return origCreateElementNS( namespaceURI, qualifiedName ); } as typeof document.createElementNS; let mounted = false; function init() { if ( mounted ) { return; } const container = document.getElementById( 'aisthetix-widget-root' ); if ( ! container ) { return; } const config = window.AISTHETIX_CONFIG; if ( ! config ) { // eslint-disable-next-line no-console console.warn( 'Aisthetix: configuration not found' ); return; } if ( ! config.apiBaseUrl || ! config.publishableKey || ! config.productImage ) { // eslint-disable-next-line no-console console.error( 'Aisthetix: missing required configuration (apiBaseUrl, publishableKey, productImage)' ); return; } try { const root = createRoot( container ); root.render( ); mounted = true; } catch ( error ) { // eslint-disable-next-line no-console console.error( 'Aisthetix: failed to render widget', error ); } } if ( document.readyState === 'loading' ) { document.addEventListener( 'DOMContentLoaded', init ); } else { init(); }