From 7f0454faf0a746c555b3be5d7b6c0571d18d480a Mon Sep 17 00:00:00 2001 From: Vjacheslav Trushkin Date: Mon, 6 May 2024 22:08:07 +0300 Subject: [PATCH] chore(utils): add customise option to css functions, fix forceSquare --- packages/utils/src/css/common.ts | 17 +++++++++++++-- packages/utils/src/css/icon.ts | 23 ++++++++++++++++++--- packages/utils/src/css/icons.ts | 25 +++++++++++++++++------ packages/utils/src/css/types.ts | 12 +++++++---- packages/utils/tests/icon-to-css-test.ts | 24 +++++++++++++++++++++- packages/utils/tests/icons-to-css-test.ts | 23 ++++++++++++++++++++- 6 files changed, 107 insertions(+), 17 deletions(-) diff --git a/packages/utils/src/css/common.ts b/packages/utils/src/css/common.ts index 66e1de5..e7b2bdc 100644 --- a/packages/utils/src/css/common.ts +++ b/packages/utils/src/css/common.ts @@ -61,8 +61,21 @@ export function generateItemCSSRules( const varName = options.varName; // Calculate width - if (!options.forceSquare && icon.width !== icon.height) { - result['width'] = calculateSize('1em', icon.width / icon.height); + if (icon.width !== icon.height) { + if (options.forceSquare) { + // Change viewBox + const max = Math.max(icon.width, icon.height); + icon = { + ...icon, + width: max, + height: max, + left: icon.left - (max - icon.width) / 2, + top: icon.top - (max - icon.height) / 2, + }; + } else { + // Change width in result + result['width'] = calculateSize('1em', icon.width / icon.height); + } } // Get SVG diff --git a/packages/utils/src/css/icon.ts b/packages/utils/src/css/icon.ts index bd58daf..06a5017 100644 --- a/packages/utils/src/css/icon.ts +++ b/packages/utils/src/css/icon.ts @@ -15,10 +15,13 @@ export function getIconCSS( icon: IconifyIcon, options: IconCSSIconOptions = {} ): string { + // Get body + const body = options.customise ? options.customise(icon.body) : icon.body; + // Get mode const mode = options.mode || - (options.color || !icon.body.includes('currentColor') + (options.color || !body.includes('currentColor') ? 'background' : 'mask'); @@ -44,7 +47,14 @@ export function getIconCSS( const rules = { ...options.rules, ...getCommonCSSRules(newOptions), - ...generateItemCSSRules({ ...defaultIconProps, ...icon }, newOptions), + ...generateItemCSSRules( + { + ...defaultIconProps, + ...icon, + body, + }, + newOptions + ), }; // Get selector and format CSS @@ -67,9 +77,16 @@ export function getIconContentCSS( icon: IconifyIcon, options: IconContentIconOptions ): string { + // Get body + const body = options.customise ? options.customise(icon.body) : icon.body; + // Get content const content = generateItemContent( - { ...defaultIconProps, ...icon }, + { + ...defaultIconProps, + ...icon, + body, + }, options ); diff --git a/packages/utils/src/css/icons.ts b/packages/utils/src/css/icons.ts index b4a2146..e2b3042 100644 --- a/packages/utils/src/css/icons.ts +++ b/packages/utils/src/css/icons.ts @@ -42,18 +42,20 @@ export function getIconsCSSData( const errors: string[] = []; // Get mode - const palette = options.color ? true : iconSet.info?.palette; + const palette = options.color ? true : undefined; let mode = options.mode || (typeof palette === 'boolean' && (palette ? 'background' : 'mask')); if (!mode) { // Attempt to detect mode from first available icon for (let i = 0; i < names.length; i++) { - const icon = getIconData(iconSet, names[i]); + const name = names[i]; + const icon = getIconData(iconSet, name); if (icon) { - mode = icon.body.includes('currentColor') - ? 'mask' - : 'background'; + const body = options.customise + ? options.customise(icon.body, name) + : icon.body; + mode = body.includes('currentColor') ? 'mask' : 'background'; break; } } @@ -114,10 +116,14 @@ export function getIconsCSSData( continue; } + const body = options.customise + ? options.customise(iconData.body, name) + : iconData.body; const rules = generateItemCSSRules( { ...defaultIconProps, ...iconData, + body, }, newOptions ); @@ -220,8 +226,15 @@ export function getIconsContentCSS( continue; } + const body = options.customise + ? options.customise(iconData.body, name) + : iconData.body; const content = generateItemContent( - { ...defaultIconProps, ...iconData }, + { + ...defaultIconProps, + ...iconData, + body, + }, options ); const selector = iconSelectorWithPrefix.replace(/{name}/g, name); diff --git a/packages/utils/src/css/types.ts b/packages/utils/src/css/types.ts index a364fd8..4d41e67 100644 --- a/packages/utils/src/css/types.ts +++ b/packages/utils/src/css/types.ts @@ -159,7 +159,8 @@ export interface IconCSSIconOptions IconCSSIconSelectorOptions, IconCSSModeOptions, IconCSSFormatOptions { - // + // Customise icon + customise?: (content: string) => string; } /** @@ -169,7 +170,8 @@ export interface IconContentIconOptions extends IconContentSharedOptions, IconContentIconSelectorOptions, IconCSSFormatOptions { - // + // Customise icon + customise?: (content: string) => string; } /** @@ -180,7 +182,8 @@ export interface IconCSSIconSetOptions IconCSSSelectorOptions, IconCSSModeOptions, IconCSSFormatOptions { - // + // Customise icon from icon set + customise?: (content: string, name: string) => string; } /** @@ -190,5 +193,6 @@ export interface IconContentIconSetOptions extends IconContentSharedOptions, IconContentIconSelectorOptions, IconCSSFormatOptions { - // + // Customise icon from icon set + customise?: (content: string, name: string) => string; } diff --git a/packages/utils/tests/icon-to-css-test.ts b/packages/utils/tests/icon-to-css-test.ts index d4a5a40..037d59f 100644 --- a/packages/utils/tests/icon-to-css-test.ts +++ b/packages/utils/tests/icon-to-css-test.ts @@ -35,7 +35,10 @@ describe('Testing CSS for icon', () => { height: 16, }; const expectedURL = svgToURL( - `${icon.body}` + `${icon.body.replace( + 'f80', + 'fff' + )}` ); expect( @@ -48,6 +51,7 @@ describe('Testing CSS for icon', () => { rules: { visibility: 'visible', }, + customise: (content) => content.replace('f80', 'fff'), }) ).toBe(`.test-icon:after { visibility: visible; @@ -104,6 +108,7 @@ describe('Testing CSS for icon', () => { )}` ); + // Use color option expect( getIconCSS(icon, { format: 'expanded', @@ -117,6 +122,23 @@ describe('Testing CSS for icon', () => { background-size: 100% 100%; background-image: ${expectedURL}; } +`); + + // Use customise option + expect( + getIconCSS(icon, { + format: 'expanded', + customise: (content) => + content.replace(/currentColor/g, 'purple'), + }) + ).toBe(`.icon { + display: inline-block; + width: 1em; + height: 1em; + background-repeat: no-repeat; + background-size: 100% 100%; + background-image: ${expectedURL}; +} `); }); diff --git a/packages/utils/tests/icons-to-css-test.ts b/packages/utils/tests/icons-to-css-test.ts index 39fa4fd..73298ef 100644 --- a/packages/utils/tests/icons-to-css-test.ts +++ b/packages/utils/tests/icons-to-css-test.ts @@ -73,6 +73,9 @@ describe('Testing CSS for multiple icons', () => { getIconsCSS(iconSet, ['123'], { format: 'expanded', mode: 'background', + // Swap content + customise: (content, name) => + name === '123' ? iconSet.icons['airplane'].body : content, }) ).toBe(`.icon--test-prefix { display: inline-block; @@ -83,7 +86,7 @@ describe('Testing CSS for multiple icons', () => { } .icon--test-prefix--123 { - background-image: ${expectedURL('123')}; + background-image: ${expectedURL('airplane')}; } `); @@ -104,6 +107,24 @@ describe('Testing CSS for multiple icons', () => { .icon--test-prefix--empty { background-image: ${expectedURL('empty', 'red')}; } +`); + + expect( + getIconsCSS(iconSet, ['activity'], { + format: 'expanded', + customise: (content) => content.replace(/currentColor/g, 'red'), + }) + ).toBe(`.icon--test-prefix { + display: inline-block; + width: 1em; + height: 1em; + background-repeat: no-repeat; + background-size: 100% 100%; +} + +.icon--test-prefix--activity { + background-image: ${expectedURL('activity', 'red')}; +} `); });