import {HTMLAttributes} from 'react'; import {CanvasExpressiveIcon} from '@workday/canvas-expressive-icons-web'; import {createComponent} from '@workday/canvas-kit-react/common'; import {CSProps, createStencil, cssVar, handleCsProp, px2rem} from '@workday/canvas-kit-styling'; import {CanvasIconTypes, CanvasSystemIcon} from '@workday/canvas-system-icons-web'; import { CanvasIcon as LegacyCanvasIcon, CanvasIconTypes as LegacyIconTypes, } from '@workday/design-assets-types'; export interface SvgProps extends CSProps, HTMLAttributes { src: CanvasSystemIcon | CanvasExpressiveIcon | LegacyCanvasIcon; type: CanvasIconTypes | LegacyIconTypes; /** * If set to `true`, transform the SVG's x-axis to mirror the graphic. Use this if you want to * always mirror the icon regardless of the content direction. If the SVG should mirror only when * in an right-to-left language, use `shouldMirrorInRTL` instead. * @default false */ shouldMirror?: boolean; /** * If set to `true`, transform the SVG's x-axis to mirror the graphic when the content direction * is `rtl`. Icons don't have enough context to know if they should be mirrored in all cases. * Setting this to `true` indicates the icon should be mirrored in right-to-left languages. * @default false */ shouldMirrorInRTL?: boolean; } export const svgStencil = createStencil({ vars: { /** sets width of svg element * @deprecated use size instead or svg selector */ width: '', /** sets height of svg element * @deprecated use size instead or svg selector */ height: '', /** sets width and height of svg element */ size: '', }, base: ({height, size, width}) => ({ display: 'inline-block', '> svg': { display: 'block', width: cssVar(width, size), height: cssVar(height, size), }, }), modifiers: { shouldMirror: { true: { transform: 'scaleX(-1)', }, }, shouldMirrorInRTL: { true: { '&:dir(rtl)': { transform: 'scaleX(-1)', }, }, }, }, }); /** * Resolves the size of the SVG based on the size token or string / numeric (px) value. * @param size - The size variant or string / numeric (px) value. * @param tokens - The tokens to use to resolve the size. * @returns The resolved size. */ export const resolveSize = ( size: T | string | number | undefined, tokens: Record ): string => { if (size) { return size in tokens ? tokens[size as keyof typeof tokens] : typeof size === 'number' ? px2rem(size) : size; } return ''; }; export const Svg = createComponent('span')({ displayName: 'Svg', Component: ( {shouldMirror, shouldMirrorInRTL, src, type, ...elemProps}: SvgProps, ref, Element ) => { if (src?.type !== type) { console.error(`Icon type "${src.type}" does not match expected type "${type}"`); return null; } return ( ); }, });