Add support for preact

This commit is contained in:
Eric Fennis
2025-03-19 11:14:07 +01:00
parent 4edcf24fc9
commit cf48dbb2d3
8 changed files with 53 additions and 13 deletions
+1
View File
@@ -39,6 +39,7 @@
"build:icons": "build-icons --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --withAliases --aliasesFileExtension=.ts --iconFileExtension=.ts --exportFileName=index.ts",
"build:bundles": "rollup -c ./rollup.config.mjs",
"test": "pnpm build:icons && vitest run",
"test:update": "vitest run -u",
"version": "pnpm version --git-tag-version=false"
},
"devDependencies": {
@@ -8,6 +8,7 @@ export default async ({
getSvg,
deprecated,
deprecationReason,
iconNameAliases,
}) => {
const svgContents = await getSvg();
const svgBase64 = base64SVG(svgContents);
@@ -26,7 +27,9 @@ import createLucideIcon from '../createLucideIcon';
* @returns {JSX.Element} JSX Element
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
*/
const ${componentName} = createLucideIcon('${componentName}', ${JSON.stringify(children)});
const ${componentName} = createLucideIcon('${componentName}', ${JSON.stringify(children)}${
iconNameAliases != null ? `, ${JSON.stringify(iconNameAliases)}` : ''
});
export default ${componentName};
`;
@@ -1,5 +1,5 @@
import { h, type JSX } from 'preact';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import { mergeClasses, createLucideClassNames } from '@lucide/shared';
import Icon from './Icon';
import type { IconNode, LucideIcon, LucideProps } from './types';
@@ -9,7 +9,12 @@ import type { IconNode, LucideIcon, LucideProps } from './types';
* @param {array} iconNode
* @returns {FunctionComponent} LucideIcon
*/
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
const createLucideIcon = (iconName: string, iconNode: IconNode, aliasNames: string[] = []): LucideIcon => {
const lucideClassNames = createLucideClassNames([
iconName,
...aliasNames,
]);
const Component = ({ class: classes = '', children, ...props }: LucideProps) =>
h(
Icon,
@@ -17,7 +22,7 @@ const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
...props,
iconNode,
class: mergeClasses<string | JSX.SignalLike<string | undefined>>(
`lucide-${toKebabCase(iconName)}`,
lucideClassNames,
classes,
),
},
@@ -10,7 +10,7 @@ exports[`Using lucide icon components > should adjust the size, stroke color and
stroke-width="4"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3"
class="lucide lucide-grid3x3 lucide-grid lucide-grid-3-x-3"
>
<rect width="18"
height="18"
@@ -40,7 +40,7 @@ exports[`Using lucide icon components > should not scale the strokeWidth when ab
stroke-width="1"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3"
class="lucide lucide-grid3x3 lucide-grid lucide-grid-3-x-3"
>
<rect width="18"
height="18"
@@ -70,7 +70,7 @@ exports[`Using lucide icon components > should render an component 1`] = `
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="lucide lucide-grid3x3"
class="lucide lucide-grid3x3 lucide-grid lucide-grid-3-x-3"
>
<rect width="18"
height="18"
@@ -70,6 +70,16 @@ describe('Using lucide icon components', () => {
expect(PenIconRenderedHTML).toBe(Edit2Container.innerHTML);
});
it('should render the alias icon name classNames', () => {
const { container } = render(
<Pen />,
);
const PenIcon = container.firstChild;
expect(PenIcon).toHaveClass('lucide-edit-2');
})
it('should not scale the strokeWidth when absoluteStrokeWidth is set', () => {
const { container } = render(
<Grid
@@ -13,7 +13,6 @@ export default async ({
const svgContents = await getSvg();
const svgBase64 = base64SVG(svgContents);
return `
import createLucideIcon from '../createLucideIcon';
import { IconNode } from '../types';
@@ -31,7 +30,9 @@ export const __iconNode: IconNode = ${JSON.stringify(children)}
* @returns {JSX.Element} JSX Element
* ${deprecated ? `@deprecated ${deprecationReason}` : ''}
*/
const ${componentName} = createLucideIcon('${componentName}', __iconNode${iconNameAliases != null ? `, ${JSON.stringify(iconNameAliases)}` : ''});
const ${componentName} = createLucideIcon('${componentName}', __iconNode${
iconNameAliases != null ? `, ${JSON.stringify(iconNameAliases)}` : ''
});
export default ${componentName};
`;
@@ -1,5 +1,5 @@
import { createElement, forwardRef } from 'react';
import { mergeClasses, toKebabCase } from '@lucide/shared';
import { mergeClasses, createLucideClassNames } from '@lucide/shared';
import { IconNode, LucideProps } from './types';
import Icon from './Icon';
@@ -9,14 +9,17 @@ import Icon from './Icon';
* @param {array} iconNode
* @returns {ForwardRefExoticComponent} LucideIcon
*/
const createLucideIcon = (iconName: string, iconNode: IconNode, aliasNames?: string[]) => {
const aliasClassNames = aliasNames != null ? aliasNames.map((aliasName) => `lucide-${toKebabCase(aliasName)}`).join(' ') : '';
const createLucideIcon = (iconName: string, iconNode: IconNode, aliasNames: string[] = []) => {
const lucideClassNames = createLucideClassNames([
iconName,
...aliasNames,
]);
const Component = forwardRef<SVGSVGElement, LucideProps>(({ className, ...props }, ref) =>
createElement(Icon, {
ref,
iconNode,
className: mergeClasses(`lucide-${toKebabCase(iconName)}`,aliasClassNames, className),
className: mergeClasses(lucideClassNames, className),
...props,
}),
);
+17
View File
@@ -49,3 +49,20 @@ export const mergeClasses = <ClassType = string | undefined | null>(...classes:
})
.join(' ')
.trim();
/**
* Create list of lucide icon names
*
* @param {array} classes
* @returns {string} A string of classes
*/
export const createLucideClassNames = (iconNames?: string[]) => {
if (iconNames == null) {
return '';
}
return iconNames
.map((aliasName) => `lucide-${toKebabCase(aliasName)}`)
.join(' ')
.trim();
};