import classNames from 'classnames' import { cloneElement, memo, ReactElement, useLayoutEffect, useRef } from 'react' import { useAssetUrls } from '../../context/asset-urls' import { TLUiIconType } from '../../icon-types' /** @public */ export type TLUiIconJsx = ReactElement> /** @public */ export interface TLUiIconProps extends React.HTMLAttributes { icon: TLUiIconType | Exclude | TLUiIconJsx label: string small?: boolean color?: string children?: undefined invertIcon?: boolean crossOrigin?: 'anonymous' | 'use-credentials' } /** @public @react */ export const TldrawUiIcon = memo(function TldrawUiIcon({ label, small, invertIcon, icon, color, className, ...props }: TLUiIconProps) { if (typeof icon === 'string') { return ( ) } return cloneElement(icon, { ...props, className: classNames({ 'tlui-icon__small': small }, className, icon.props.className), 'aria-label': label, style: { color, transform: invertIcon ? 'scale(-1, 1)' : undefined, ...icon.props.style, }, }) }) function TldrawUIIconInner({ label, small, invertIcon, icon, color, className, ...props }: TLUiIconProps & { icon: TLUiIconType | Exclude }) { const assetUrls = useAssetUrls() const asset = assetUrls.icons[icon as TLUiIconType] ?? assetUrls.icons['question-mark-circle'] const ref = useRef(null) useLayoutEffect(() => { if (!asset) { console.error(`Icon not found: ${icon}. Add it to the assetUrls.icons object.`) } if (ref?.current) { // HACK: Fix for // It seems that passing `WebkitMask` to react will cause a render on each call, no idea why... but this appears to be the fix. // @ts-ignore // eslint-disable-next-line @typescript-eslint/no-deprecated ref.current.style.webkitMask = `url(${asset}) center 100% / 100% no-repeat` } }, [ref, asset, icon]) if (icon === 'none') { return (
) } return (
) }