mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-16 21:57:41 +01:00
fix(lucide-vue-next): Support for kebabCase props (#3477)
* Fix kebabCase Vue props * format code * Fix tests * Format code
This commit is contained in:
@@ -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()] : [])],
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>][];
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user