import {
DeesElement,
html,
property,
customElement,
css,
type TemplateResult,
} from '@design.estate/dees-element';
import * as lucideIcons from 'lucide';
import {
Activity,
ArrowUp,
Bell,
Bolt,
Box,
Building2,
Check,
ChevronDown,
ChevronRight,
Clock,
Cloud,
Copy,
CreditCard,
Fingerprint,
Globe,
Grid2x2,
Home,
Key,
Laptop,
Lock,
LogOut,
Mail,
MapPin,
Monitor,
MonitorSmartphone,
Nfc,
Phone,
Plus,
Power,
QrCode,
Search,
Settings,
Shield,
SmartphoneNfc,
SquarePen,
Trash2,
TriangleAlert,
User,
Users,
Wallet,
X,
createElement,
type IconNode,
} from 'lucide';
import { idpElementStyles } from './tokens.js';
export type TIdpIconName =
| 'activity'
| 'alert'
| 'alert-triangle'
| 'arrow-up'
| 'bell'
| 'bolt'
| 'box'
| 'building'
| 'building2'
| 'building-2'
| 'check'
| 'chevron'
| 'chevron-down'
| 'chevron-right'
| 'clock'
| 'cloud'
| 'copy'
| 'credit'
| 'device'
| 'edit'
| 'fingerprint'
| 'gear'
| 'globe'
| 'grid'
| 'home'
| 'key'
| 'laptop'
| 'location'
| 'lock'
| 'logout'
| 'mail'
| 'monitor'
| 'monitor-smartphone'
| 'nfc'
| 'phone'
| 'plus'
| 'power'
| 'qr'
| 'search'
| 'settings'
| 'shield'
| 'smartphone-nfc'
| 'trash'
| 'user'
| 'users'
| 'wallet'
| 'waveform'
| 'x'
| `lucide:${string}`;
declare global {
interface HTMLElementTagNameMap {
'idp-icon': IdpIcon;
}
}
const iconNodes: Record = {
activity: Activity,
alert: TriangleAlert,
'alert-triangle': TriangleAlert,
'arrow-up': ArrowUp,
bell: Bell,
bolt: Bolt,
box: Box,
building: Building2,
building2: Building2,
'building-2': Building2,
check: Check,
chevron: ChevronRight,
'chevron-down': ChevronDown,
'chevron-right': ChevronRight,
clock: Clock,
cloud: Cloud,
copy: Copy,
credit: CreditCard,
device: MonitorSmartphone,
edit: SquarePen,
fingerprint: Fingerprint,
gear: Settings,
globe: Globe,
grid: Grid2x2,
home: Home,
key: Key,
laptop: Laptop,
location: MapPin,
lock: Lock,
logout: LogOut,
mail: Mail,
monitor: Monitor,
'monitor-smartphone': MonitorSmartphone,
nfc: Nfc,
phone: Phone,
plus: Plus,
power: Power,
qr: QrCode,
search: Search,
settings: Settings,
shield: Shield,
'smartphone-nfc': SmartphoneNfc,
trash: Trash2,
user: User,
users: Users,
wallet: Wallet,
waveform: Activity,
x: X,
};
const toKebab = (valueArg: string): string => valueArg
.replace(/^lucide:/, '')
.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
.toLowerCase();
const toLucideExportName = (valueArg: string): string => valueArg
.replace(/^lucide:/i, '')
.split(/[-_: ]+/)
.filter(Boolean)
.map((partArg) => `${partArg.charAt(0).toUpperCase()}${partArg.slice(1)}`)
.join('');
@customElement('idp-icon')
export class IdpIcon extends DeesElement {
public static demo = () => html``;
public static demoGroups = ['idp.global v3 primitives'];
@property({ type: String })
public accessor name: TIdpIconName = 'shield';
@property({ type: Number })
public accessor size = 18;
private lastRenderKey = '';
public static styles = [
...idpElementStyles,
css`
:host {
display: inline-flex;
align-items: center;
justify-content: center;
color: currentColor;
line-height: 0;
vertical-align: middle;
}
#iconContainer {
width: var(--icon-size);
height: var(--icon-size);
}
#iconContainer svg {
display: block;
width: 100%;
height: 100%;
fill: none;
stroke: currentColor;
stroke-width: 1.75;
stroke-linecap: round;
stroke-linejoin: round;
}
`,
];
private resolveIconNode(): IconNode {
const rawName = String(this.name || 'shield');
const iconName = toKebab(rawName);
const aliasNode = iconNodes[iconName];
if (aliasNode) {
return aliasNode;
}
const exportName = toLucideExportName(rawName);
const lucideNode = (lucideIcons as Record)[exportName];
if (Array.isArray(lucideNode)) {
return lucideNode as IconNode;
}
return Shield;
}
public render(): TemplateResult {
return html`
`;
}
public updated(): void {
const renderKey = `${this.name}:${this.size}`;
if (this.lastRenderKey === renderKey) {
return;
}
this.lastRenderKey = renderKey;
const container = this.shadowRoot?.querySelector('#iconContainer');
if (!container) {
return;
}
container.innerHTML = '';
const iconElement = createElement(this.resolveIconNode(), {
color: 'currentColor',
size: this.size,
strokeWidth: 1.75,
});
iconElement.setAttribute('aria-hidden', 'true');
container.appendChild(iconElement);
}
}