fix(lucide-vue-next): Support for kebabCase props (#3477)

* Fix kebabCase Vue props

* format code

* Fix tests

* Format code
This commit is contained in:
Eric Fennis
2025-08-01 11:39:49 +02:00
committed by GitHub
parent 673e76831d
commit a3ec4428f1
6 changed files with 71 additions and 9 deletions

View File

@@ -1,5 +1,5 @@
import { type FunctionalComponent, h } from 'vue';
import { mergeClasses, toKebabCase, toPascalCase } from '@lucide/shared';
import { mergeClasses, toKebabCase, toPascalCase, isEmptyString } from '@lucide/shared';
import defaultAttributes from './defaultAttributes';
import { IconNode, LucideProps } from './types';
@@ -9,24 +9,43 @@ interface IconProps {
}
const Icon: FunctionalComponent<LucideProps & IconProps> = (
{ size, strokeWidth = 2, absoluteStrokeWidth, color, iconNode, name, class: classes, ...props },
{
name,
iconNode,
absoluteStrokeWidth,
'absolute-stroke-width': absoluteStrokeWidthKebabCase,
strokeWidth,
'stroke-width': strokeWidthKebabCase,
size = defaultAttributes.width,
color = defaultAttributes.stroke,
...props
},
{ slots },
) => {
return h(
'svg',
{
...defaultAttributes,
width: size || defaultAttributes.width,
height: size || defaultAttributes.height,
stroke: color || defaultAttributes.stroke,
'stroke-width': absoluteStrokeWidth ? (Number(strokeWidth) * 24) / Number(size) : strokeWidth,
...props,
width: size,
height: size,
stroke: color,
'stroke-width':
isEmptyString(absoluteStrokeWidth) ||
isEmptyString(absoluteStrokeWidthKebabCase) ||
absoluteStrokeWidth === true ||
absoluteStrokeWidthKebabCase === true
? (Number(strokeWidth || strokeWidthKebabCase || defaultAttributes['stroke-width']) *
24) /
Number(size)
: strokeWidth || strokeWidthKebabCase || defaultAttributes['stroke-width'],
class: mergeClasses(
'lucide',
props.class,
...(name
? [`lucide-${toKebabCase(toPascalCase(name))}-icon`, `lucide-${toKebabCase(name)}`]
: ['lucide-icon']),
),
...props,
},
[...iconNode.map((child) => h(...child)), ...(slots.default ? [slots.default()] : [])],
);

View File

@@ -13,10 +13,11 @@ import Icon from './Icon';
*/
const createLucideIcon =
(iconName: string, iconNode: IconNode): FunctionalComponent<LucideProps> =>
(props, { slots }) =>
(props, { slots, attrs }) =>
h(
Icon,
{
...attrs,
...props,
iconNode,
name: iconName,

View File

@@ -4,6 +4,7 @@ export interface LucideProps extends Partial<SVGAttributes> {
size?: 24 | number;
strokeWidth?: number | string;
absoluteStrokeWidth?: boolean;
'absolute-stroke-width'?: boolean;
}
export type IconNode = [elementName: string, attrs: Record<string, string>][];

View File

@@ -3,7 +3,7 @@
exports[`Using lucide icon components > should add a class to the element 1`] = `
<div>
<svg
class="lucide lucide-smile-icon lucide-smile my-icon"
class="lucide my-icon lucide-smile-icon lucide-smile my-icon"
fill="none"
height="24"
stroke="currentColor"

View File

@@ -147,4 +147,37 @@ describe('Using lucide icon components', () => {
expect(icon).toHaveAttribute('stroke', 'red');
expect(icon).toHaveAttribute('stroke-width', '1');
});
it('should not scale the strokeWidth when absoluteStrokeWidth is as empty value attribute', () => {
const { container } = render(Pen, {
props: {
size: 48,
color: 'red',
absoluteStrokeWidth: '',
},
});
const icon = container.firstElementChild;
expect(icon).toHaveAttribute('width', '48');
expect(icon).toHaveAttribute('stroke', 'red');
expect(icon).toHaveAttribute('stroke-width', '1');
});
it('should not scale the strokeWidth when absoluteStrokeWidth is written in kebabCase', () => {
const { container } = render(Pen, {
props: {
size: 48,
color: 'red',
'stroke-width': '2',
'absolute-stroke-width': '',
},
});
const icon = container.firstElementChild;
expect(icon).toHaveAttribute('width', '48');
expect(icon).toHaveAttribute('stroke', 'red');
expect(icon).toHaveAttribute('stroke-width', '1');
});
});

View File

@@ -50,6 +50,14 @@ export const mergeClasses = <ClassType = string | undefined | null>(...classes:
.join(' ')
.trim();
/**
* Is empty string
*
* @param {unknown} value
* @returns {boolean} Whether the value is an empty string
*/
export const isEmptyString = (value: unknown): boolean => value === '';
/**
* Check if a component has an accessibility prop
*