feat(packages/lucide): added support for providing a custom root element (#3543)

* feat(packages/lucide): added support for providing a custom root element

* feat(packages/lucide): ran prettier & renamed from root ⇒ context
This commit is contained in:
Karsa
2025-08-18 15:25:08 +02:00
committed by GitHub
parent f8a1a76b83
commit 85dba80322
3 changed files with 33 additions and 7 deletions

View File

@@ -88,7 +88,11 @@ createIcons({
### Additional Options
In the `createIcons` function you can pass some extra parameters to adjust the `nameAttr` or add custom attributes like for example classes.
In the `createIcons` function you can pass some extra parameters:
- you can pass `nameAttr` to adjust the attribute name to replace for
- you can pass `attrs` to pass additional custom attributes, for instance CSS classes or stroke options.
- you can pass `root` to provide a custom DOM element the icons should be replaced in (useful when manipulating small sections of a large DOM or elements in the shadow DOM)
Here is a full example:
@@ -101,7 +105,8 @@ createIcons({
'stroke-width': 1,
stroke: '#333'
},
nameAttr: 'data-lucide' // attribute for the icon name.
nameAttr: 'data-lucide', // attribute for the icon name.
root: element, // DOM element to replace icons in.
});
```

View File

@@ -3,27 +3,32 @@ import * as iconAndAliases from './iconsAndAliases';
/**
* Replaces all elements with matching nameAttr with the defined icons
* @param {{ icons?: object, nameAttr?: string, attrs?: object }} options
* @param {{ icons?: object, nameAttr?: string, attrs?: object, root?: Element | Document }} options
*/
const createIcons = ({ icons = {}, nameAttr = 'data-lucide', attrs = {} } = {}) => {
const createIcons = ({
icons = {},
nameAttr = 'data-lucide',
attrs = {},
root = document,
}: { icons?: object; nameAttr?: string; attrs?: object; root?: Element | Document } = {}) => {
if (!Object.values(icons).length) {
throw new Error(
"Please provide an icons object.\nIf you want to use all the icons you can import it like:\n `import { createIcons, icons } from 'lucide';\nlucide.createIcons({icons});`",
);
}
if (typeof document === 'undefined') {
if (typeof root === 'undefined') {
throw new Error('`createIcons()` only works in a browser environment.');
}
const elementsToReplace = document.querySelectorAll(`[${nameAttr}]`);
const elementsToReplace = root.querySelectorAll(`[${nameAttr}]`);
Array.from(elementsToReplace).forEach((element) =>
replaceElement(element, { nameAttr, icons, attrs }),
);
/** @todo: remove this block in v1.0 */
if (nameAttr === 'data-lucide') {
const deprecatedElements = document.querySelectorAll('[icon-name]');
const deprecatedElements = root.querySelectorAll('[icon-name]');
if (deprecatedElements.length > 0) {
console.warn(
'[Lucide] Some icons were found with the now deprecated icon-name attribute. These will still be replaced for backwards compatibility, but will no longer be supported in v1.0 and you should switch to data-lucide',

View File

@@ -27,6 +27,22 @@ describe('createIcons', () => {
expect(hasSvg).toBeTruthy();
});
it('should only execute given provided context', () => {
document.body.innerHTML = `<div id="context"><i data-lucide="volume-2"></i></div><i data-lucide="funnel"></i>`;
const context = document.querySelector('#context')!;
createIcons({
icons,
root: context,
});
const hasSvg = !!document.querySelector('svg.lucide-volume-2');
const hasUnreplaced = !!document.querySelector('i[data-lucide="funnel"]');
expect(hasSvg).toBeTruthy();
expect(hasUnreplaced).toBeTruthy();
});
it('should add custom attributes', () => {
document.body.innerHTML = `<i data-lucide="volume-2" class="lucide"></i>`;