mirror of
https://github.com/iconify/iconify.git
synced 2024-12-04 18:23:17 +00:00
feat(tailwind): dynamic icon selectors
This commit is contained in:
parent
2049c1d512
commit
53f4d2a4be
@ -148,3 +148,47 @@ export function getCSSRules(
|
||||
|
||||
return rules;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dynamic CSS rule
|
||||
*/
|
||||
export function getDynamicCSSRules(
|
||||
selector: string,
|
||||
icon: string,
|
||||
options: IconifyPluginOptions = {}
|
||||
): Record<string, string> {
|
||||
const nameParts = icon.split('--');
|
||||
let nameError = `Invalid icon name: "${icon}"`;
|
||||
if (nameParts.length !== 2) {
|
||||
if (nameParts.length === 1 && icon.indexOf(':') !== -1) {
|
||||
nameError += `. "{prefix}:{name}" is not supported because of Tailwind limitations, use "{prefix}--{name}" (use double dash!) instead.`;
|
||||
}
|
||||
throw new Error(nameError);
|
||||
}
|
||||
|
||||
const [prefix, name] = nameParts;
|
||||
if (!prefix.match(matchIconName) || !name.match(matchIconName)) {
|
||||
throw new Error(nameError);
|
||||
}
|
||||
|
||||
const iconSet = loadIconSet(prefix, options);
|
||||
if (!iconSet) {
|
||||
throw new Error(`Cannot load icon set for "${prefix}"`);
|
||||
}
|
||||
|
||||
console.log('Selector:', selector);
|
||||
const generated = getIconsCSSData(iconSet, [name], {
|
||||
...options,
|
||||
// One selector
|
||||
iconSelector: selector,
|
||||
commonSelector: selector,
|
||||
overrideSelector: selector,
|
||||
});
|
||||
if (generated.css.length !== 1) {
|
||||
throw new Error(`Something went wrong generating "${icon}"`);
|
||||
}
|
||||
return {
|
||||
...(generated.common?.rules || {}),
|
||||
...generated.css[0].rules,
|
||||
};
|
||||
}
|
||||
|
@ -8,11 +8,22 @@ export interface IconifyPluginFileOptions {
|
||||
files?: Record<string, string>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for matching dynamic icon names
|
||||
*/
|
||||
export interface IconifyPluginDynamicPrefixOptions {
|
||||
// Dynamic prefix for selectors. Default is `icon`
|
||||
// Allows using icon names like `<span class="icon[mdi--home]"></span>
|
||||
// Where prefix and name are separated by '--' because Tailwind does not allow ':'
|
||||
dynamicPrefix?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* All options
|
||||
*/
|
||||
export interface IconifyPluginOptions
|
||||
extends IconCSSIconSetOptions,
|
||||
IconifyPluginDynamicPrefixOptions,
|
||||
IconifyPluginFileOptions {
|
||||
//
|
||||
}
|
||||
|
@ -1,17 +1,41 @@
|
||||
import plugin from 'tailwindcss/plugin';
|
||||
import { getCSSRules } from './iconify';
|
||||
import { getCSSRules, getDynamicCSSRules } from './iconify';
|
||||
import type { IconifyPluginOptions } from './options';
|
||||
|
||||
/**
|
||||
* Iconify plugin
|
||||
*/
|
||||
function iconifyPlugin(
|
||||
icons: string[] | string,
|
||||
options: IconifyPluginOptions = {}
|
||||
icons?: string[] | string,
|
||||
options?: IconifyPluginOptions
|
||||
) {
|
||||
const rules = getCSSRules(icons, options);
|
||||
return plugin(({ addUtilities }) => {
|
||||
addUtilities(rules);
|
||||
const passedOptions =
|
||||
typeof icons === 'object' && !(icons instanceof Array)
|
||||
? icons
|
||||
: options || {};
|
||||
const passedIcons =
|
||||
typeof icons !== 'object' || icons instanceof Array ? icons : void 0;
|
||||
|
||||
// Get selector for dynamic classes
|
||||
const dynamicSelector = passedOptions.dynamicPrefix || 'icon';
|
||||
|
||||
// Get hardcoded list of icons
|
||||
const rules = passedIcons
|
||||
? getCSSRules(passedIcons, passedOptions)
|
||||
: void 0;
|
||||
|
||||
return plugin(({ addUtilities, matchComponents }) => {
|
||||
if (rules) {
|
||||
addUtilities(rules);
|
||||
}
|
||||
matchComponents({
|
||||
[dynamicSelector]: (icon: string) =>
|
||||
getDynamicCSSRules(
|
||||
`.${dynamicSelector}-[${icon}]`,
|
||||
icon,
|
||||
passedOptions
|
||||
),
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user