UNPKG

@reusable-ui/icon

Version:

An icon set component for React app.

85 lines (84 loc) 3.35 kB
// react: import { // hooks: useMemo, } from 'react'; // cssfn: import { // writes css in javascript: style, vars, cssVars, } from '@cssfn/core'; // writes css in javascript // internals: import { iconConfig, } from '../config.js'; import { concatUrl, } from '../utilities.js'; const [iconVars] = cssVars({ prefix: 'icon', minify: false }); // shared variables: ensures the server-side & client-side have the same generated css variable names /** * Uses icon image and icon color. * @param config A configuration of `iconRule`. * @returns A `IconStuff` represents the icon rules. */ export const usesIcon = (config) => { return { iconRule: () => style({ ...vars({ // appearances: [iconVars.image]: config?.image, // sizes: [iconVars.size]: config?.size, // backgrounds: [iconVars.color]: config?.color, }), }), iconVars, }; }; const getFileNameWithoutExtension = (file) => { if (!file) return null; const fileName = (typeof (file) === 'string') ? file : file.name; const lastDotIndex = fileName.lastIndexOf('.'); if (lastDotIndex < 0) return fileName; // extension is not found => it's a pure fileName without extension return fileName.slice(0, lastDotIndex); }; export const useIcon = ({ icon }) => { return useMemo(() => { // dependencies: // features: const { iconVars } = usesIcon(); const [iconImage, iconRatio] = (() => { const file = iconConfig.image.files.find((file) => getFileNameWithoutExtension(file) === icon); if (!file) return [null, null]; return [ concatUrl(iconConfig.image.path, (typeof (file) === 'string') ? file : file.name), (typeof (file) === 'string') ? null : (file.ratio ?? null) ]; })(); const isIconFont = !iconImage; // && iconConfig.font.items.includes(icon); // assumes the user use TypeScript for validating the font name // memorized a whole object: return { class: (() => { if (iconImage) return 'image'; // icon name is found in iconImage if (isIconFont) return 'font'; // icon name is found in iconFont return null; // icon name is not found in both iconImage & iconFont })(), style: { // appearances: [iconVars.image .slice(4, -1) // fix: var(--customProp) => --customProp ]: (() => { if (iconImage) return `url("${iconImage}")`; // the url of the icon's image if (isIconFont) return `"${icon}"`; // the icon's name return undefined; // icon name is not found in both iconImage & iconFont })(), [iconVars.ratio .slice(4, -1) // fix: var(--customProp) => --customProp ]: iconRatio ?? '1/1', // defaults to '1/1' if the ratio is not defined }, }; }, [icon]); }; //#endregion icon