mirror of
https://github.com/lucide-icons/lucide.git
synced 2025-12-17 19:37:41 +01:00
Compare commits
5 Commits
fix/fixed-
...
0.476.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6632ce8d7 | ||
|
|
a59c5de61a | ||
|
|
2bd0ae55fd | ||
|
|
3f2ad5b2a6 | ||
|
|
1250fc276d |
@@ -126,11 +126,23 @@ import { createElement, Menu } from 'lucide';
|
|||||||
|
|
||||||
const menuIcon = createElement(Menu); // Returns HTMLElement (svg)
|
const menuIcon = createElement(Menu); // Returns HTMLElement (svg)
|
||||||
|
|
||||||
// set custom attributes with browser native functions
|
// Append HTMLElement in the DOM
|
||||||
menuIcon.setAttribute('stroke', '#333');
|
const myApp = document.getElementById('app');
|
||||||
menuIcon.classList.add('my-icon-class');
|
myApp.appendChild(menuIcon);
|
||||||
|
```
|
||||||
|
|
||||||
// Append HTMLElement in webpage
|
#### Custom Element binding with custom attributes
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createElement, Menu } from 'lucide';
|
||||||
|
|
||||||
|
const menuIcon = createElement(Menu, {
|
||||||
|
class: ['my-custom-class', 'icon'],
|
||||||
|
'stroke-width': 1,
|
||||||
|
stroke: '#333'
|
||||||
|
}); // Returns HTMLElement (svg)
|
||||||
|
|
||||||
|
// Append HTMLElement in the DOM
|
||||||
const myApp = document.getElementById('app');
|
const myApp = document.getElementById('app');
|
||||||
myApp.appendChild(menuIcon);
|
myApp.appendChild(menuIcon);
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
>
|
>
|
||||||
|
<path d="M16.4 13.7A6.5 6.5 0 1 0 6.28 6.6c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c4 0 8.4-1.8 11.4-4.3" />
|
||||||
|
<path d="m18.5 6 2.19 4.5a6.48 6.48 0 0 1-2.29 7.2C15.4 20.2 11 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5" />
|
||||||
<circle cx="12.5" cy="8.5" r="2.5" />
|
<circle cx="12.5" cy="8.5" r="2.5" />
|
||||||
<path d="M12.5 2a6.5 6.5 0 0 0-6.22 4.6c-1.1 3.13-.78 3.9-3.18 6.08A3 3 0 0 0 5 18c4 0 8.4-1.8 11.4-4.3A6.5 6.5 0 0 0 12.5 2Z" />
|
|
||||||
<path d="m18.5 6 2.19 4.5a6.48 6.48 0 0 1 .31 2 6.49 6.49 0 0 1-2.6 5.2C15.4 20.2 11 22 7 22a3 3 0 0 1-2.68-1.66L2.4 16.5" />
|
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 468 B |
23
icons/shield-user.json
Normal file
23
icons/shield-user.json
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"$schema": "../icon.schema.json",
|
||||||
|
"contributors": [
|
||||||
|
"sebinemeth",
|
||||||
|
"ksk3110",
|
||||||
|
"karsa-mistmere",
|
||||||
|
"colebemis"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"shield",
|
||||||
|
"user",
|
||||||
|
"admin",
|
||||||
|
"protection",
|
||||||
|
"protected",
|
||||||
|
"safety",
|
||||||
|
"guard"
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
"account",
|
||||||
|
"security",
|
||||||
|
"development"
|
||||||
|
]
|
||||||
|
}
|
||||||
15
icons/shield-user.svg
Normal file
15
icons/shield-user.svg
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z" />
|
||||||
|
<path d="M6.376 18.91a6 6 0 0 1 11.249.003" />
|
||||||
|
<circle cx="12" cy="11" r="4" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 469 B |
@@ -1,15 +1,16 @@
|
|||||||
|
import defaultAttributes from './defaultAttributes';
|
||||||
import { IconNode, SVGProps } from './types';
|
import { IconNode, SVGProps } from './types';
|
||||||
|
|
||||||
type CreateElementParams = [tag: string, attrs: SVGProps, children?: IconNode];
|
type CreateSVGElementParams = [tag: string, attrs: SVGProps, children?: IconNode];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new HTMLElement from icon node
|
* Creates a new SVGElement
|
||||||
* @param {string} tag
|
* @param {string} tag - Tag name of the element
|
||||||
* @param {object} attrs
|
* @param {object} attrs - Attributes of the element
|
||||||
* @param {array} children
|
* @param {array} children - Children of the element
|
||||||
* @returns {HTMLElement}
|
* @returns {SVGElement}
|
||||||
*/
|
*/
|
||||||
const createElement = ([tag, attrs, children]: CreateElementParams) => {
|
const createSVGElement = ([tag, attrs, children]: CreateSVGElementParams) => {
|
||||||
const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
|
const element = document.createElementNS('http://www.w3.org/2000/svg', tag);
|
||||||
|
|
||||||
Object.keys(attrs).forEach((name) => {
|
Object.keys(attrs).forEach((name) => {
|
||||||
@@ -18,7 +19,7 @@ const createElement = ([tag, attrs, children]: CreateElementParams) => {
|
|||||||
|
|
||||||
if (children?.length) {
|
if (children?.length) {
|
||||||
children.forEach((child) => {
|
children.forEach((child) => {
|
||||||
const childElement = createElement(child);
|
const childElement = createSVGElement(child);
|
||||||
|
|
||||||
element.appendChild(childElement);
|
element.appendChild(childElement);
|
||||||
});
|
});
|
||||||
@@ -27,4 +28,20 @@ const createElement = ([tag, attrs, children]: CreateElementParams) => {
|
|||||||
return element;
|
return element;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new HTMLElement from icon node
|
||||||
|
* @param {array} iconNode - Icon node to be converted to an element
|
||||||
|
* @param {object} customAttrs - Custom attributes to be added to the element
|
||||||
|
* @returns {HTMLElement}
|
||||||
|
*/
|
||||||
|
const createElement = (iconNode: IconNode, customAttrs: SVGProps = {}) => {
|
||||||
|
const tag = 'svg';
|
||||||
|
const attrs = {
|
||||||
|
...defaultAttributes,
|
||||||
|
...customAttrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
return createSVGElement([tag, attrs, iconNode]);
|
||||||
|
};
|
||||||
|
|
||||||
export default createElement;
|
export default createElement;
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ const replaceElement = (element: Element, { nameAttr, icons, attrs }: ReplaceEle
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const svgElement = createElement(['svg', iconAttrs, iconNode]);
|
const svgElement = createElement(iconNode, iconAttrs);
|
||||||
|
|
||||||
return element.parentNode?.replaceChild(svgElement, element);
|
return element.parentNode?.replaceChild(svgElement, element);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`createElement > should match the snapshot 1`] = `
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewbox="0 0 24 24"
|
||||||
|
fill="none"
|
||||||
|
stroke="currentColor"
|
||||||
|
stroke-width="2"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
>
|
||||||
|
<path d="M15 21v-8a1 1 0 0 0-1-1h-4a1 1 0 0 0-1 1v8">
|
||||||
|
</path>
|
||||||
|
<path d="M3 10a2 2 0 0 1 .709-1.528l7-5.999a2 2 0 0 1 2.582 0l7 5.999A2 2 0 0 1 21 10v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z">
|
||||||
|
</path>
|
||||||
|
</svg>
|
||||||
|
`;
|
||||||
37
packages/lucide/tests/createElement.spec.ts
Normal file
37
packages/lucide/tests/createElement.spec.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { describe, it, expect } from 'vitest';
|
||||||
|
import { House, createElement } from '../src/lucide';
|
||||||
|
import { getOriginalSvg } from './helpers';
|
||||||
|
|
||||||
|
describe('createElement', () => {
|
||||||
|
it('should create SVG Element', () => {
|
||||||
|
const HomeSVG = createElement(House);
|
||||||
|
|
||||||
|
expect(HomeSVG.tagName).toBe('svg');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should match the snapshot', () => {
|
||||||
|
const HomeSVG = createElement(House);
|
||||||
|
|
||||||
|
expect(HomeSVG.outerHTML).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create SVG Element with attributes', () => {
|
||||||
|
const HomeSVG = createElement(House, { fill: 'red' });
|
||||||
|
|
||||||
|
expect(HomeSVG.getAttribute('fill')).toBe('red');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create SVG Element with class name', () => {
|
||||||
|
const HomeSVG = createElement(House, { class: 'icon' });
|
||||||
|
|
||||||
|
expect(HomeSVG.getAttribute('class')).toBe('icon');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create the correct svg element', () => {
|
||||||
|
const HomeSVG = createElement(House);
|
||||||
|
|
||||||
|
const svg = getOriginalSvg('house', undefined, false);
|
||||||
|
|
||||||
|
expect(HomeSVG.outerHTML).toBe(svg);
|
||||||
|
});
|
||||||
|
});
|
||||||
17
packages/lucide/tests/helpers.ts
Normal file
17
packages/lucide/tests/helpers.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { parseSync, stringify } from 'svgson';
|
||||||
|
|
||||||
|
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
|
||||||
|
|
||||||
|
export const getOriginalSvg = (iconName: string, aliasName?: string, setAttrs = true) => {
|
||||||
|
const svgContent = fs.readFileSync(path.join(ICONS_DIR, `${iconName}.svg`), 'utf8');
|
||||||
|
const svgParsed = parseSync(svgContent);
|
||||||
|
|
||||||
|
if (setAttrs) {
|
||||||
|
svgParsed.attributes['data-lucide'] = aliasName ?? iconName;
|
||||||
|
svgParsed.attributes['class'] = `lucide lucide-${aliasName ?? iconName}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringify(svgParsed, { selfClose: false });
|
||||||
|
};
|
||||||
@@ -1,20 +1,6 @@
|
|||||||
import { describe, it, expect } from 'vitest';
|
import { describe, it, expect } from 'vitest';
|
||||||
import { createIcons, icons } from '../src/lucide';
|
import { createIcons, icons } from '../src/lucide';
|
||||||
import fs from 'fs';
|
import { getOriginalSvg } from './helpers';
|
||||||
import path from 'path';
|
|
||||||
import { parseSync, stringify } from 'svgson';
|
|
||||||
|
|
||||||
const ICONS_DIR = path.resolve(__dirname, '../../../icons');
|
|
||||||
|
|
||||||
const getOriginalSvg = (iconName: string, aliasName?: string) => {
|
|
||||||
const svgContent = fs.readFileSync(path.join(ICONS_DIR, `${iconName}.svg`), 'utf8');
|
|
||||||
const svgParsed = parseSync(svgContent);
|
|
||||||
|
|
||||||
svgParsed.attributes['data-lucide'] = aliasName ?? iconName;
|
|
||||||
svgParsed.attributes['class'] = `lucide lucide-${aliasName ?? iconName}`;
|
|
||||||
|
|
||||||
return stringify(svgParsed, { selfClose: false });
|
|
||||||
};
|
|
||||||
|
|
||||||
describe('createIcons', () => {
|
describe('createIcons', () => {
|
||||||
it('should read elements from DOM and replace it with icons', () => {
|
it('should read elements from DOM and replace it with icons', () => {
|
||||||
|
|||||||
@@ -43,12 +43,13 @@ const getImageTagsByFiles = (files, getBaseUrl, width) =>
|
|||||||
return `<img title="${file}" alt="${file}" ${widthAttr} src="${url}/${base64}.svg"/>`;
|
return `<img title="${file}" alt="${file}" ${widthAttr} src="${url}/${base64}.svg"/>`;
|
||||||
});
|
});
|
||||||
|
|
||||||
const svgFiles = readSvgDirectory(ICONS_DIR).map((file) => `icons/${file}`);
|
const svgFiles = await readSvgDirectory(ICONS_DIR)
|
||||||
|
const svgFilePaths = svgFiles.map((file) => `icons/${file}`);
|
||||||
|
|
||||||
const iconsFilteredByName = (search) => svgFiles.filter((file) => file.includes(search));
|
const iconsFilteredByName = (search) => svgFilePaths.filter((file) => file.includes(search));
|
||||||
|
|
||||||
const cohesionRandomImageTags = getImageTagsByFiles(
|
const cohesionRandomImageTags = getImageTagsByFiles(
|
||||||
shuffleArray(svgFiles).slice(0, changedFiles.length),
|
shuffleArray(svgFilePaths).slice(0, changedFiles.length),
|
||||||
() => `${BASE_URL}/stroke-width/2`,
|
() => `${BASE_URL}/stroke-width/2`,
|
||||||
).join('');
|
).join('');
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,8 @@ import path from 'path';
|
|||||||
export const readSvgDirectory = async (directory, fileExtension = '.svg') => {
|
export const readSvgDirectory = async (directory, fileExtension = '.svg') => {
|
||||||
const directoryContents = await fs.readdir(directory);
|
const directoryContents = await fs.readdir(directory);
|
||||||
|
|
||||||
|
console.log(directoryContents);
|
||||||
|
|
||||||
|
|
||||||
return directoryContents.filter((file) => path.extname(file) === fileExtension);
|
return directoryContents.filter((file) => path.extname(file) === fileExtension);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user