mirror of
https://github.com/iconify/iconify.git
synced 2024-11-17 01:55:09 +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;
|
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>;
|
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
|
* All options
|
||||||
*/
|
*/
|
||||||
export interface IconifyPluginOptions
|
export interface IconifyPluginOptions
|
||||||
extends IconCSSIconSetOptions,
|
extends IconCSSIconSetOptions,
|
||||||
|
IconifyPluginDynamicPrefixOptions,
|
||||||
IconifyPluginFileOptions {
|
IconifyPluginFileOptions {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,41 @@
|
|||||||
import plugin from 'tailwindcss/plugin';
|
import plugin from 'tailwindcss/plugin';
|
||||||
import { getCSSRules } from './iconify';
|
import { getCSSRules, getDynamicCSSRules } from './iconify';
|
||||||
import type { IconifyPluginOptions } from './options';
|
import type { IconifyPluginOptions } from './options';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iconify plugin
|
* Iconify plugin
|
||||||
*/
|
*/
|
||||||
function iconifyPlugin(
|
function iconifyPlugin(
|
||||||
icons: string[] | string,
|
icons?: string[] | string,
|
||||||
options: IconifyPluginOptions = {}
|
options?: IconifyPluginOptions
|
||||||
) {
|
) {
|
||||||
const rules = getCSSRules(icons, options);
|
const passedOptions =
|
||||||
return plugin(({ addUtilities }) => {
|
typeof icons === 'object' && !(icons instanceof Array)
|
||||||
addUtilities(rules);
|
? 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