UNPKG

@reusable-ui/icon

Version:

An icon set component for React app.

195 lines (194 loc) 6.57 kB
// cssfn: import { // writes css in javascript: rule, fallback, fontFace, children, style, // strongly typed of css variables: switchOf, // reads/writes css variables configuration: usesCssProps, // writes complex stylesheets in simpler way: watchChanges, memoizeStyle, } from '@cssfn/core'; // writes css in javascript // reusable-ui core: import { // common layouts: fillTextLineHeightLayout, // size options of UI: usesResizable, // color options of UI: usesThemeable, // colorize the UI based on its theme or the background theme: usesColorable, } from '@reusable-ui/core'; // a set of reusable-ui packages which are responsible for building any component // internals: import { // configs: icons, cssIconConfig, } from './config.js'; import { // configs: iconConfig, } from '../config.js'; import { usesIcon, } from '../features/icon.js'; import { sizeOptions, } from '../variants/resizable.js'; import { // utilities: concatUrl, formatOf, } from '../utilities.js'; // styles: export const onIconStylesChange = watchChanges(cssIconConfig.onChange); export const usesIconLayout = memoizeStyle(() => { // dependencies: // variants: const { colorableVars } = usesColorable(); // features: const { iconRule, iconVars } = usesIcon({ size: icons.size, color: colorableVars.color, }); return style({ // layouts: ...style({ // layouts: display: 'inline-flex', flexDirection: 'row', justifyContent: 'center', alignItems: 'center', flexWrap: 'nowrap', // positions: verticalAlign: 'baseline', // sizes: blockSize: iconVars.size, aspectRatio: switchOf(// set background_image's aspect_ratio iconVars.ratio, 'initial'), // children: ...children('::before', { // layouts: ...fillTextLineHeightLayout(), }), // customize: ...usesCssProps(icons), color: null, // delete color prop from config, we use color prop in special way }), // features: ...iconRule(), // must be placed at the last }); }, onIconStylesChange); export const usesIconFontLayout = (options) => { // dependencies: // features: const { iconVars } = usesIcon(); return style({ // load a custom_font: ...fontFace({ // fonts: ...iconConfig.font.style, ...style({ src: [ ...iconConfig.font.files .map((file) => [ `url("${concatUrl(iconConfig.font.path, file)}")`, formatOf(file) ?? '', ]), ], }), }), // children: ...children(options?.iconFontElement ?? '&', { // fonts: // use the loaded custom_font: ...iconConfig.font.style, // layouts: ...style({ // layouts: ...fallback({ content: iconVars.image, display: 'inline', // use inline, so it takes the width & height automatically }), // sizes: fontSize: iconVars.size, // overflowY : 'hidden', // a hack: hides the pseudo-inherited underline overflow: 'hidden', ...fallback({ blockSize: 'inherit', aspectRatio: 'inherit', // follows <parent>'s aspect_ratio }), // accessibilities: userSelect: 'none', // backgrounds: backg: 'transparent', // foregrounds: foreg: iconVars.color, // animations: ...fallback({ transition: 'inherit', // inherit transition for smooth sizing changes }), // typos: lineHeight: 1, textTransform: 'none', letterSpacing: 'normal', overflowWrap: 'normal', whiteSpace: 'nowrap', direction: 'ltr', //#region turn on available browser features WebkitFontSmoothing: 'antialiased', textRendering: 'optimizeLegibility', MozOsxFontSmoothing: 'grayscale', fontFeatureSettings: 'liga', // support for IE //#endregion turn on available browser features }), }), }); }; export const usesIconImageLayout = memoizeStyle(() => { // dependencies: // features: const { iconVars } = usesIcon(); // layouts: return style({ // appearances: maskSize: 'contain', WebkitMaskSize: 'contain', maskRepeat: 'no-repeat', WebkitMaskRepeat: 'no-repeat', maskPosition: 'center', WebkitMaskPosition: 'center', maskImage: iconVars.image, WebkitMaskImage: iconVars.image, // backgrounds: backg: iconVars.color, // set icon's color }); }); export const usesIconVariants = memoizeStyle(() => { // dependencies: // variants: const { resizableRule } = usesResizable(icons, sizeOptions()); const { themeableRule } = usesThemeable(); const { colorableRule } = usesColorable(icons, /* outlinedDefinition = not_supported */ null, /* mildDefinition = is_supported */ undefined); return style({ // variants: ...resizableRule(), ...themeableRule(), ...colorableRule(), }); }, onIconStylesChange); export const usesIconImage = (config) => { // dependencies: // features: const { iconRule } = usesIcon(config); return style({ // layouts: ...usesIconImageLayout(), // features: ...iconRule(), // must be placed at the last }); }; export default memoizeStyle(() => style({ // layouts: ...usesIconLayout(), ...rule('.font', { // layouts: ...usesIconFontLayout({ iconFontElement: '::after' }), }), ...rule('.image', { // layouts: ...usesIconImageLayout(), }), // variants: ...usesIconVariants(), }), onIconStylesChange);