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 (
);
},
});