// Icon.jsx — React wrapper that renders Lucide icons as real SVG elements, // avoiding the `lucide.createIcons()` DOM-swap pattern (which fights with React's // reconciler and crashes on unmount with "removeChild" errors). // // Usage: // // Reads icon path data from `window.lucide[Pascal]` (provided by the lucide UMD // bundle on the page) and renders an svg directly. No DOM mutation. (function () { const cache = new Map(); function pascal(name) { if (cache.has(name)) return cache.get(name); const p = String(name).split(/[-_\s]+/).filter(Boolean) .map(w => w[0].toUpperCase() + w.slice(1)).join(''); cache.set(name, p); return p; } function L({ name, className = '', style, strokeWidth = 1.5, size, ...rest }) { if (!name) return null; const data = (window.lucide && (window.lucide[pascal(name)] || window.lucide[name])); if (!data) { // Fallback: an empty box so layout doesn't shift. return React.createElement('span', { className, style, 'aria-hidden': 'true', ...rest }); } const children = data.map((entry, i) => { if (!Array.isArray(entry)) return null; const [tag, attrs] = entry; // Convert any HTML attribute names to React-friendly camelCase only where it matters. const reactAttrs = {}; for (const k of Object.keys(attrs || {})) { if (k === 'class') reactAttrs.className = attrs[k]; else reactAttrs[k] = attrs[k]; } return React.createElement(tag, { key: i, ...reactAttrs }); }); return React.createElement('svg', { xmlns: 'http://www.w3.org/2000/svg', width: size || 24, height: size || 24, viewBox: '0 0 24 24', fill: 'none', stroke: 'currentColor', strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round', 'aria-hidden': 'true', className, style, ...rest, }, ...children); } window.L = L; })();