import React from 'react'; import kebabCase from 'lodash/kebabCase'; import mapValues from 'lodash/mapValues'; import { createGlyphComponent } from './createGlyphComponent'; import { Size } from './glyphCommon'; import { isComponentGlyph } from './isComponentGlyph'; import { LGGlyph } from './types'; // We omit size here because we map string values for size to numbers in this component. export interface IconProps extends Omit { /** * The name of the icon glyph */ glyph: string; /** * Size of the icon */ size?: Size | number; } type GlyphObject = Record; /** * Returns a single component with a `glyph` prop to select the glyph * @param glyphs The set of glyphs * @returns Icon component */ export function createIconComponent( glyphs: G, ) { const allGlyphsAreComponents = Object.values(glyphs).every(isComponentGlyph); const glyphDict = allGlyphsAreComponents ? glyphs : mapValues(glyphs, (val, key) => { // We do not currently check for valid SVG files. TODO: LG-5827 if (isComponentGlyph(val)) return val; return createGlyphComponent(key, val); }); const Icon = ({ glyph, ...rest }: IconProps) => { const SVGComponent = glyphDict[glyph]; if (SVGComponent) { return ; } else { // TODO: improve fuzzy match // Suggest the proper icon casing if there's a near match const nearMatch = Object.keys(glyphs).find( key => kebabCase(key) === kebabCase(glyph), ); console.error( 'Error in Icon', `Could not find glyph named "${glyph}" in the icon set.`, nearMatch && `Did you mean "${nearMatch}?"`, ); return <>; } }; Icon.displayName = 'Icon'; Icon.isGlyph = true; return Icon; }