// icon.jsx — safe Icon for lucide UMD v0.395
// lucide.icons[Key] is the array form: ["svg", attrs, [["path", {...}], ...]]
// We build SVG markup ourselves at mount time (no DOM mutation after render).
const Icon = ({ name, size = 18, stroke = 2, className, style }) => {
const html = React.useMemo(() => {
const lib = window.lucide && window.lucide.icons;
if (!lib) return '';
const key = name
.split('-')
.map(s => s.charAt(0).toUpperCase() + s.slice(1))
.join('');
const node = lib[key] || lib[name];
if (!node) return '';
// Some lucide builds expose IconNode form: { toSvg } | array form
if (node && typeof node.toSvg === 'function') {
return node.toSvg({ width: size, height: size, 'stroke-width': stroke });
}
if (!Array.isArray(node)) return '';
const renderNode = (n) => {
if (!Array.isArray(n)) return '';
const [tag, attrs, children] = n;
const attrStr = Object.entries(attrs || {})
.map(([k, v]) => `${k}="${String(v).replace(/"/g, '"')}"`)
.join(' ');
const inner = Array.isArray(children) ? children.map(renderNode).join('') : '';
return `<${tag} ${attrStr}>${inner}${tag}>`;
};
// Top level: ["svg", attrs, children]
const [, attrs, children] = node;
const merged = {
...(attrs || {}),
width: size,
height: size,
'stroke-width': stroke,
};
const attrStr = Object.entries(merged)
.map(([k, v]) => `${k}="${String(v).replace(/"/g, '"')}"`)
.join(' ');
const inner = Array.isArray(children) ? children.map(renderNode).join('') : '';
return ``;
}, [name, size, stroke]);
return (
);
};
window.Icon = Icon;