Compare commits

...

5 Commits

Author SHA1 Message Date
Eric Fennis
c784dd09c7 Remove exports lucide-react 2022-12-05 14:26:07 +01:00
Markus Napp
0f11acdd7f Language improvements for introduction text (#895)
* Language improvements for introduction text

* Updated number of icons
2022-12-04 22:49:57 +01:00
Lucide Bot
2149645895 📦 Bump lucide package versions to 0.104.0 2022-12-04 21:45:15 +00:00
Eric Fennis
fa6ed02297 Implement: Typescript, Esbuild and vitest (#877)
* init modernization

* implement esbuild

* Make first build work

* Fix esbuild for lucide-react

* Add vitest for lucide-react

* add esbuild lucide and lucide-react

* update package lock

* implement preact

* Add typescript and vitest

* adjust workflows

* Fix mocking react-native package

* update lock file

* Add esbuild in svelte

* make svelte test work in vitest

* Refactor lucide svelte

* Transform lucide vue to typescript

* Finish lucide-vue-next typescript

* 0.104.0-beta.0

* remove version in main package.json

* cleanup

* Fix svelte tests snapshots

* clean up

* add rollup lucide-vue-next

* Fix lucide svelte package

* change to workspace link

* revert filter position

* revert preact workflow change

* cleanup

* Fix some types

* add semi
2022-12-04 22:38:56 +01:00
Lucide Bot
4a2c6ed8b0 📦 Bump lucide package versions to 0.103.0 2022-11-30 10:29:46 +00:00
136 changed files with 3662 additions and 4312 deletions

View File

@@ -34,6 +34,7 @@ module.exports = {
parserOptions: { parserOptions: {
tsconfigRootDir: __dirname, tsconfigRootDir: __dirname,
project: ['./site/tsconfig.json', './packages/*/tsconfig.json'], project: ['./site/tsconfig.json', './packages/*/tsconfig.json'],
ecmaVersion: 2020, ecmaVersion: 'latest',
sourceType: 'module',
}, },
}; };

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-angular/** - packages/lucide-angular/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-angular/**
- pnpm-lock.yaml
jobs: jobs:
lucide-angular: lucide-angular:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- icons/** - icons/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- icons/**
- pnpm-lock.yaml
jobs: jobs:
lucide-font: lucide-font:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-preact/** - packages/lucide-preact/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-preact/**
- pnpm-lock.yaml
jobs: jobs:
lucide-preact: lucide-preact:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-react-native/** - packages/lucide-react-native/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-react-native/**
- pnpm-lock.yaml
jobs: jobs:
lucide-react-native: lucide-react-native:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-react/** - packages/lucide-react/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-react/**
- pnpm-lock.yaml
jobs: jobs:
lucide-react: lucide-react:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-solid/** - packages/lucide-solid/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-solid/**
- pnpm-lock.yaml
jobs: jobs:
lucide-solid: lucide-solid:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-static/** - packages/lucide-static/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-static/**
- pnpm-lock.yaml
jobs: jobs:
lucide-static: lucide-static:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-svelte/** - packages/lucide-svelte/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-svelte/**
- pnpm-lock.yaml
jobs: jobs:
lucide-svelte: lucide-svelte:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-vue-next/** - packages/lucide-vue-next/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-vue-next/**
- pnpm-lock.yaml
jobs: jobs:
lucide-vue-next: lucide-vue-next:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide-vue/** - packages/lucide-vue/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide-vue/**
- pnpm-lock.yaml
jobs: jobs:
lucide-vue: lucide-vue:

View File

@@ -5,10 +5,6 @@ on:
paths: paths:
- packages/lucide/** - packages/lucide/**
- pnpm-lock.yaml - pnpm-lock.yaml
push:
paths:
- packages/lucide/**
- pnpm-lock.yaml
jobs: jobs:
lucide: lucide:

View File

@@ -1,20 +0,0 @@
module.exports = {
presets: ['@babel/env'],
// babelrcRoots: ['.', './packages/*'],
env: {
test: {
presets: ['@babel/env'],
plugins: ['@babel/plugin-transform-runtime'],
},
dev: {
plugins: [
[
'transform-inline-environment-variables',
{
include: ['NODE_ENV'],
},
],
],
},
},
};

View File

@@ -6,16 +6,15 @@ nextPage:
--- ---
# Introduction # Introduction
Lucide is an open source icon library for displaying icons and symbols in digital and non-digital projects. It consists of 850+ Vector (svg) files. To use these icons, lucide provides several official packages to make it easier to use these icons in projects.
An open source icon library for displaying icons and symbols in digital and non digital projects. It is containing over 500+ Vector (svg) files. To use these icons, lucide provides several official packages to make it easier to use these icons in projects. Lucide contains icons with different variants and states. With that, designers and developers can choose the right icon for themselves. If a desired icon doesn't exist yet, you're free to open a design request. The Lucide community contributors will help to provide new icons.
Lucide contains icons with different variants and states. With that designers and developers can choose the right icon for them selves. If icons don't exist you're free to open design request. The Lucide community will help. With more icons, we simply have more icons to work with in our projects. Also with rising of new applications with specific features, lucide has the goal to provide the complete set for your project.
With help of the community, contributors are providing the library of new icons. With more icons, we simply have more icons to work with in your project. Also with rising of new applications with specific features lucide has the goal the provide the complete set for you project. When designing new icons, the community is working with a set of design rules. This is to maintain some standards for the icons: recognizable, consistency in style, and readable on all sizes. The community loves creativity in new icons but recognizable design conventions are important.
When designing new icons, the community is working with a set of design rules. This is to keep icons: recognizable, consistency in style, and readable on all sizes. The community likes to have creativity in new icons but conventional design is important to have recognizable icons. Beside design, code is also important. Assets like icons in, for example, web projects can increase the bandwidth usage significantly. With the growing internet, lucide has the responsibility to keep their assets as small as possible. To achieve this, lucide uses SVG compression and specific code architecture for tree-shaking abilities. After tree-shaking, you will only ship the icons you used, helps you to keep the software distribution size to a minimum.
Beside design, code is also important. Assets like icons in for example web projects can increase the transferred bytes significantly. With the growing internet, lucide has the responsibility to keep their assets small as possible. To achieve this, lucide uses SVG compression and specific code architecture for tree-shaking abilities. With tree-shaking used you will only ship the icons you used, helps you to keep the software small as possible when distributed.
Lucide provides several official packages for: [Web (Vanilla)](https://lucide.dev/docs/lucide), [React](https://lucide.dev/docs/lucide-react), [React Native](https://lucide.dev/docs/lucide-react-native), [Vue](https://lucide.dev/docs/lucide-vue), [Vue 3](https://lucide.dev/docs/lucide-vue-next), [Svelte](https://lucide.dev/docs/lucide-svelte),[Preact](https://lucide.dev/docs/lucide-preact), [Angular](https://lucide.dev/docs/lucide-angular), [NodeJS](https://lucide.dev/docs/lucide-static#nodejs) and [Flutter](https://lucide.dev/docs/lucide-flutter). Lucide provides several official packages for: [Web (Vanilla)](https://lucide.dev/docs/lucide), [React](https://lucide.dev/docs/lucide-react), [React Native](https://lucide.dev/docs/lucide-react-native), [Vue](https://lucide.dev/docs/lucide-vue), [Vue 3](https://lucide.dev/docs/lucide-vue-next), [Svelte](https://lucide.dev/docs/lucide-svelte),[Preact](https://lucide.dev/docs/lucide-preact), [Angular](https://lucide.dev/docs/lucide-angular), [NodeJS](https://lucide.dev/docs/lucide-static#nodejs) and [Flutter](https://lucide.dev/docs/lucide-flutter).

View File

@@ -28,37 +28,16 @@
"lint": "eslint --ext .ts,.js,.mjs ./{packages/lucide,scripts}" "lint": "eslint --ext .ts,.js,.mjs ./{packages/lucide,scripts}"
}, },
"devDependencies": { "devDependencies": {
"@atomico/rollup-plugin-sizes": "^1.1.4",
"@babel/cli": "^7.19.3",
"@babel/core": "^7.19.6",
"@babel/node": "^7.20.0",
"@babel/plugin-transform-runtime": "^7.19.6",
"@babel/preset-env": "^7.19.4",
"@rollup/plugin-babel": "^6.0.2",
"@rollup/plugin-commonjs": "^23.0.2",
"@rollup/plugin-node-resolve": "^15.0.1",
"@rollup/plugin-replace": "^5.0.1",
"@rollup/plugin-typescript": "^9.0.2",
"babel-jest": "^29.2.2",
"babel-plugin-add-import-extension": "^1.6.0",
"core-js": "^3.26.0",
"esbuild": "^0.15.12",
"eslint": "^8.26.0", "eslint": "^8.26.0",
"eslint-config-airbnb-base": "^15.0.0", "eslint-config-airbnb-base": "^15.0.0",
"eslint-config-prettier": "^8.5.0", "eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0", "eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1", "eslint-plugin-prettier": "^4.2.1",
"husky": "^8.0.1", "husky": "^8.0.1",
"jest": "^29.2.2",
"lint-staged": "^13.0.3", "lint-staged": "^13.0.3",
"minimist": "^1.2.7", "minimist": "^1.2.7",
"node-fetch": "^3.2.10", "node-fetch": "^3.2.10",
"prettier": "2.7.1", "prettier": "2.7.1",
"rollup": "^3.2.4",
"rollup-plugin-license": "^3.0.1",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-visualizer": "^5.8.3",
"svg-outline-stroke": "^1.3.1",
"svgo": "^3.0.0", "svgo": "^3.0.0",
"svgson": "^5.2.1" "svgson": "^5.2.1"
}, },
@@ -70,5 +49,13 @@
"lint-staged": { "lint-staged": {
"icons/*.svg": "node ./scripts/optimizeStagedSvgs.mjs" "icons/*.svg": "node ./scripts/optimizeStagedSvgs.mjs"
}, },
"packageManager": "pnpm@7.14.0" "packageManager": "pnpm@7.14.0",
"pnpm": {
"peerDependencyRules": {
"ignoreMissing": [
"@babel/core",
"@babel/preset-env"
]
}
}
} }

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-angular", "name": "lucide-angular",
"description": "A Lucide icon library package for Angular applications", "description": "A Lucide icon library package for Angular applications",
"version": "0.102.0", "version": "0.104.0",
"author": "SMAH1", "author": "SMAH1",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
@@ -28,7 +28,7 @@
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:ng", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:ng",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf ./src/icons/*.ts", "clean": "rm -rf dist && rm -rf ./src/icons/*.ts",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtention=.ts --exportFileName=index.ts", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --iconFileExtension=.ts --exportFileName=index.ts",
"build:ng": "ng build --configuration production", "build:ng": "ng build --configuration production",
"test": "ng test --no-watch --no-progress --browsers=ChromeHeadlessCI", "test": "ng test --no-watch --no-progress --browsers=ChromeHeadlessCI",
"test:watch": "ng test", "test:watch": "ng test",

View File

@@ -1,6 +1,6 @@
name: lucide_icons name: lucide_icons
description: A Lucide icon library package for Flutter applications. Fork of Feather Icons, open for anyone to contribute icons. description: A Lucide icon library package for Flutter applications. Fork of Feather Icons, open for anyone to contribute icons.
version: 0.102.0 version: 0.104.0
homepage: https://lucide.dev homepage: https://lucide.dev
repository: https://github.com/lucide-icons/lucide repository: https://github.com/lucide-icons/lucide

View File

@@ -1,6 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: ['preact'],
env: mainConfig.env,
};

View File

@@ -1,9 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transformIgnorePatterns: [`/node_modules`],
transform: {
'^.+\\.js$': 'babel-jest',
},
};

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-preact", "name": "lucide-preact",
"description": "A Lucide icon library package for Preact applications", "description": "A Lucide icon library package for Preact applications",
"version": "0.102.0", "version": "0.104.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -22,21 +22,25 @@
], ],
"sideEffects": false, "sideEffects": false,
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:types && pnpm build:bundles", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts",
"build:es": "babel src -d dist/esm",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@preact/preset-vite": "^2.4.0",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/preact": "^2.0.1", "@testing-library/preact": "^2.0.1",
"babel-preset-preact": "^2.0.0", "preact": "^10.11.2",
"jest": "^26.6.3", "rollup": "^3.5.1",
"preact": "^10.5.13" "typescript": "^4.8.4",
"vite": "^3.1.0",
"vitest": "^0.24.3"
}, },
"peerDependencies": { "peerDependencies": {
"preact": "^10.5.13" "preact": "^10.5.13"

View File

@@ -1,10 +1,10 @@
import plugins from '../../rollup.plugins.mjs'; import plugins from '@lucide/rollup-plugins';
import pkg from './package.json' assert { type: "json" }; import pkg from './package.json' assert { type: "json" };
const packageName = 'LucidePreact'; const packageName = 'LucidePreact';
const outputFileName = 'lucide-preact'; const outputFileName = 'lucide-preact';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = [`src/lucide-preact.js`]; const inputs = [`src/lucide-preact.ts`];
const bundles = [ const bundles = [
{ {
format: 'umd', format: 'umd',
@@ -22,17 +22,35 @@ const bundles = [
inputs, inputs,
outputDir, outputDir,
}, },
{
format: 'es',
inputs,
outputDir,
},
{
format: 'esm',
inputs,
outputDir,
preserveModules: true,
},
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify }) => .map(({ inputs, outputDir, format, minify, preserveModules }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: plugins(pkg, minify), plugins: plugins(pkg, minify),
external: ['preact', 'prop-types'], external: ['preact', 'prop-types'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules
? {
dir: `${outputDir}/${format}`,
}
: {
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
}),
preserveModules,
format, format,
sourcemap: true, sourcemap: true,
globals: { globals: {

View File

@@ -1,33 +0,0 @@
import { h, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
/**
* Converts string to KebabCase
* Copied from scripts/helper. If anyone knows how to properly import it here
* then please fix it.
*
* @param {string} string
* @returns {string} A kebabized string
*/
export const toKebabCase = string => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
export default (iconName, iconNode) => {
const Component = ({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }) =>
h(
'svg',
{
...defaultAttributes,
width: size,
height: size,
stroke: color,
'stroke-width': strokeWidth,
class: `lucide lucide-${toKebabCase(iconName)}`,
...rest,
},
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
);
Component.displayName = `${iconName}`;
return Component;
};

View File

@@ -0,0 +1,46 @@
import { ComponentType, h, JSX, toChildArray } from 'preact';
import defaultAttributes from './defaultAttributes';
type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][]
interface LucideProps extends Omit<JSX.SVGAttributes<SVGElement>, "ref" | "size"> {
size?: string | number
color: string
}
/**
* Converts string to KebabCase
* Copied from scripts/helper. If anyone knows how to properly import it here
* then please fix it.
*
* @param {string} string
* @returns {string} A kebabized string
*/
export const toKebabCase = (string: string) => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
const createPreactComponent = (iconName: string, iconNode: IconNode) => {
const Component = (
{ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }: LucideProps
) =>
h(
'svg' as unknown as ComponentType<Partial<JSX.SVGAttributes<SVGElement> & { 'stroke-width': number | string }>>,
{
...defaultAttributes,
width: String(size),
height: size,
stroke: color,
['stroke-width' as 'strokeWidth']: strokeWidth,
class: `lucide lucide-${toKebabCase(iconName)}`,
...rest,
},
[...iconNode.map(([tag, attrs]) => h(tag, attrs)), ...toChildArray(children)],
);
Component.displayName = `${iconName}`;
return Component;
};
export default createPreactComponent

View File

@@ -5,7 +5,7 @@ export default {
viewBox: '0 0 24 24', viewBox: '0 0 24 24',
fill: 'none', fill: 'none',
stroke: 'currentColor', stroke: 'currentColor',
'stroke-width': 2, 'stroke-width': '2',
'stroke-linecap': 'round', 'stroke-linecap': 'round',
'stroke-linejoin': 'round', 'stroke-linejoin': 'round',
}; };

View File

@@ -1,5 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Using lucide icon components should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"lucide lucide-grid\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components should render an component 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\\" class=\\"lucide lucide-grid\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -0,0 +1,5 @@
// Vitest Snapshot v1
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"lucide lucide-grid\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components > should render an component 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\\" class=\\"lucide lucide-grid\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -1,4 +1,4 @@
import { h } from 'preact' import { describe, it, expect } from 'vitest';
import { render } from '@testing-library/preact' import { render } from '@testing-library/preact'
import { Grid } from '../src/icons' import { Grid } from '../src/icons'

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"strict": true,
"declaration": true,
"noEmitOnError": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"module": "ESNext",
"target": "ESNext",
"esModuleInterop": true,
"isolatedModules": true,
"lib": ["esnext", "dom"],
"skipLibCheck": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"sourceMap": true,
"outDir": "./dist",
"declarationMap": true,
"jsx": "react-jsx",
"jsxImportSource": "preact",
},
"exclude": ["**/node_modules"]
}

View File

@@ -0,0 +1,19 @@
import { defineConfig } from 'vitest/config'
import preact from '@preact/preset-vite'
export default defineConfig({
plugins: [preact()],
test: {
globals: true,
environment: 'jsdom',
transformMode: {
web: [/\.jsx?$/],
},
setupFiles: './tests/setupVitest.js',
threads: false,
isolate: false,
},
resolve: {
mainFields: ['module'],
},
});

View File

@@ -1,10 +1,10 @@
// @flow
// https://github.com/FormidableLabs/react-native-svg-mock // https://github.com/FormidableLabs/react-native-svg-mock
import React from 'react'; import React from 'react';
import type { LucideProps } from '../../src/createReactComponent';
export type { SvgProps } from 'react-native-svg';
const createComponent = function(name) { const createComponent = function(name: string) {
const component = (props) => { const component = (props: LucideProps) => {
return React.createElement(name, props, props.children); return React.createElement(name, props, props.children);
} }

View File

@@ -1,19 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: {
...mainConfig.env,
test: {
presets: ['react-app'],
},
},
};

View File

@@ -1,9 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transformIgnorePatterns: [`/node_modules`],
transform: {
'^.+\\.js$': 'babel-jest',
},
};

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-react-native", "name": "lucide-react-native",
"description": "A Lucide icon library package for React Native applications", "description": "A Lucide icon library package for React Native applications",
"version": "0.102.0", "version": "0.104.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -26,21 +26,28 @@
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:types", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "test": "vitest",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0", "@testing-library/react": "^13.4.0",
"babel-preset-react-app": "^10.0.0", "@types/prop-types": "^15.7.5",
"jest": "^26.6.3", "@types/react": "^18.0.21",
"@vitejs/plugin-react": "^2.1.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "^18.0.0", "react": "^18.0.0",
"react-dom": "^18.0.0", "react-dom": "^18.0.0",
"react-native": "^0.69.0", "react-native": "^0.69.0",
"react-native-svg": "^13.0.0" "react-native-svg": "^13.0.0",
"rollup": "^3.5.1",
"typescript": "^4.8.4",
"vite": "^3.1.0",
"vitest": "^0.24.3"
}, },
"peerDependencies": { "peerDependencies": {
"prop-types": "^15.7.2", "prop-types": "^15.7.2",

View File

@@ -1,10 +1,10 @@
import plugins from '../../rollup.plugins.mjs'; import plugins from '@lucide/rollup-plugins';
import pkg from './package.json' assert { type: 'json' }; import pkg from './package.json' assert { type: 'json' };
const packageName = 'LucideReact'; const packageName = 'LucideReact';
const outputFileName = 'lucide-react-native'; const outputFileName = 'lucide-react-native';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = ['src/lucide-react-native.js']; const inputs = ['src/lucide-react-native.ts'];
const bundles = [ const bundles = [
{ {
format: 'umd', format: 'umd',
@@ -23,6 +23,11 @@ const bundles = [
outputDir, outputDir,
preserveModules: true, preserveModules: true,
}, },
{
format: 'es',
inputs,
outputDir,
},
{ {
format: 'esm', format: 'esm',
inputs, inputs,
@@ -36,7 +41,7 @@ const configs = bundles
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: plugins(pkg, minify), plugins: plugins(pkg, minify),
external: ['react', 'prop-types', 'lucide', 'react-native-svg'], external: ['react', 'prop-types', 'react-native-svg'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules ...(preserveModules
@@ -54,7 +59,6 @@ const configs = bundles
react: 'react', react: 'react',
'react-native-svg': 'react-native-svg', 'react-native-svg': 'react-native-svg',
'prop-types': 'PropTypes', 'prop-types': 'PropTypes',
lucide: 'lucide',
}, },
}, },
})), })),

View File

@@ -5,16 +5,15 @@ import {
resetFile, resetFile,
toPascalCase, toPascalCase,
writeFile, writeFile,
getCurrentDirPath getCurrentDirPath,
} from '../../../scripts/helpers.mjs'; } from '../../../scripts/helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url) const currentDir = getCurrentDirPath(import.meta.url);
const srcDirectory = path.join(currentDir, '../dist'); const srcDirectory = path.join(currentDir, '../dist');
// Declare type definitions // Declare type definitions
const typeDefinitions = `\ const typeDefinitions = `\
/// <reference types="react" /> /// <reference types="react" />
import { SVGAttributes } from 'react'
declare module 'lucide-react-native' declare module 'lucide-react-native'
@@ -38,7 +37,7 @@ writeFile(typeDefinitions, TYPES_FILE, srcDirectory);
const svgFiles = readSvgDirectory(ICONS_DIR); const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => { svgFiles.forEach((svgFile) => {
const iconName = path.basename(svgFile, '.svg'); const iconName = path.basename(svgFile, '.svg');
const componentName = toPascalCase(iconName); const componentName = toPascalCase(iconName);

View File

@@ -1,11 +1,18 @@
import { forwardRef, createElement } from 'react'; import { forwardRef, createElement, ReactSVG, ReactNode, FunctionComponent } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import * as NativeSvg from 'react-native-svg'; import * as NativeSvg from 'react-native-svg';
import defaultAttributes from './defaultAttributes'; import defaultAttributes from './defaultAttributes';
import type { SvgProps } from 'react-native-svg';
type IconNode = [elementName: keyof ReactSVG, attrs: Record<string, string>][]
const createReactComponent = (iconName, iconNode) => {
export interface LucideProps extends SvgProps {
size?: string | number
}
const createReactComponent = (iconName: string, iconNode: IconNode) => {
const Component = forwardRef( const Component = forwardRef(
({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }, ref) => ({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }: LucideProps, ref) =>
createElement( createElement(
NativeSvg.Svg, NativeSvg.Svg,
{ {
@@ -19,10 +26,10 @@ const createReactComponent = (iconName, iconNode) => {
}, },
[ [
...iconNode.map(([tag, attrs]) => { ...iconNode.map(([tag, attrs]) => {
const uppercasedTag = tag.charAt(0).toUpperCase() + tag.slice(1); const upperCasedTag = (tag.charAt(0).toUpperCase() + tag.slice(1)) as keyof (typeof NativeSvg);
return createElement(NativeSvg[uppercasedTag], attrs); return createElement(NativeSvg[upperCasedTag] as FunctionComponent<Record<string, string>>, attrs);
}), }),
...(children || []), ...(children as ReactNode[] || []),
], ],
), ),
); );

View File

@@ -1,5 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Using lucide icon components should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components should render an component 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\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -0,0 +1,5 @@
// Vitest Snapshot v1
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components > should render an component 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\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -1,10 +1,14 @@
import React from 'react'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { Grid } from '../src/icons' import { Grid } from '../src/icons'
vi.mock('react-native-svg')
type Attributes = Record<string, { value: unknown}>
describe('Using lucide icon components', () => { describe('Using lucide icon components', () => {
it('should render an component', () => { it('should render an component', () => {
const { container } = render( <Grid/> ); const { container } = render(<Grid /> );
expect( container.innerHTML ).toMatchSnapshot(); expect( container.innerHTML ).toMatchSnapshot();
}); });
@@ -21,10 +25,10 @@ describe('Using lucide icon components', () => {
); );
const { attributes } = getByTestId(testId); const { attributes } = getByTestId(testId);
expect(attributes.stroke.value).toBe('red'); expect((attributes as unknown as Attributes).stroke.value).toBe('red');
expect(attributes.width.value).toBe('48'); expect((attributes as unknown as Attributes).width.value).toBe('48');
expect(attributes.height.value).toBe('48'); expect((attributes as unknown as Attributes).height.value).toBe('48');
expect(attributes['stroke-width'].value).toBe('4'); expect((attributes as unknown as Attributes)['stroke-width'].value).toBe('4');
expect( container.innerHTML ).toMatchSnapshot(); expect( container.innerHTML ).toMatchSnapshot();
}); });

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "esnext",
"module": "ESNext",
"lib": [
"es2019",
"DOM"
],
"allowJs": true,
"jsx": "react-jsx",
"noEmit": true,
"isolatedModules": true,
"strict": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"esModuleInterop": true,
"skipLibCheck": false
},
"exclude": [
"node_modules",
]
}

View File

@@ -0,0 +1,19 @@
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [
react(),
],
test: {
globals: true,
environment: 'jsdom',
transformMode: {
web: [/\.jsx?$/],
},
setupFiles: './tests/setupVitest.js',
// threads: false,
// isolate: false,
mockReset: true,
},
});

View File

@@ -1,19 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: {
...mainConfig.env,
test: {
presets: ['react-app'],
},
},
};

View File

@@ -1,9 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transformIgnorePatterns: [`/node_modules`],
transform: {
'^.+\\.js$': 'babel-jest',
},
};

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-react", "name": "lucide-react",
"description": "A Lucide icon library package for React applications", "description": "A Lucide icon library package for React applications",
"version": "0.102.0", "version": "0.104.1",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -22,23 +22,31 @@
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:types && pnpm build:bundles", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm typecheck && pnpm build:bundles && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.ts",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts",
"build:es": "babel src -d dist/esm",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "typecheck": "tsc",
"typecheck:watch": "tsc -w",
"test": "vitest run",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^11.2.6", "@testing-library/react": "^11.2.6",
"babel-preset-react-app": "^10.0.0", "@types/prop-types": "^15.7.5",
"jest": "^26.6.3", "@types/react": "^18.0.21",
"@vitejs/plugin-react": "^2.1.0",
"prop-types": "^15.7.2", "prop-types": "^15.7.2",
"react": "17.0.2", "react": "17.0.2",
"react-dom": "17.0.2" "react-dom": "17.0.2",
"rollup": "^3.5.1",
"typescript": "^4.8.4",
"vite": "^3.1.0",
"vitest": "^0.24.3"
}, },
"peerDependencies": { "peerDependencies": {
"prop-types": "^15.7.2", "prop-types": "^15.7.2",

View File

@@ -1,10 +1,10 @@
import plugins from '../../rollup.plugins.mjs'; import plugins from '@lucide/rollup-plugins';
import pkg from './package.json' assert { type: 'json' }; import pkg from './package.json' assert { type: 'json' };
const packageName = 'LucideReact'; const packageName = 'LucideReact';
const outputFileName = 'lucide-react'; const outputFileName = 'lucide-react';
const outputDir = `dist`; const outputDir = `dist`;
const inputs = [`src/lucide-react.js`]; const inputs = [`src/lucide-react.ts`];
const bundles = [ const bundles = [
{ {
format: 'umd', format: 'umd',
@@ -22,23 +22,40 @@ const bundles = [
inputs, inputs,
outputDir, outputDir,
}, },
{
format: 'es',
inputs,
outputDir,
},
{
format: 'esm',
inputs,
outputDir,
preserveModules: true,
},
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify }) => .map(({ inputs, outputDir, format, minify, preserveModules }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: plugins(pkg, minify), plugins: plugins(pkg, minify),
external: ['react', 'prop-types', 'lucide'], external: ['react', 'prop-types'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules
? {
dir: `${outputDir}/${format}`,
}
: {
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
}),
format, format,
sourcemap: true, sourcemap: true,
preserveModules,
globals: { globals: {
react: 'react', react: 'react',
'prop-types': 'PropTypes', 'prop-types': 'PropTypes'
lucide: 'lucide',
}, },
}, },
})), })),

View File

@@ -5,10 +5,10 @@ import {
resetFile, resetFile,
toPascalCase, toPascalCase,
writeFile, writeFile,
getCurrentDirPath getCurrentDirPath,
} from '../../../scripts/helpers.mjs'; } from '../../../scripts/helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url) const currentDir = getCurrentDirPath(import.meta.url);
const srcDirectory = path.join(currentDir, '../dist'); const srcDirectory = path.join(currentDir, '../dist');
// Declare type definitions // Declare type definitions
@@ -38,7 +38,7 @@ writeFile(typeDefinitions, TYPES_FILE, srcDirectory);
const svgFiles = readSvgDirectory(ICONS_DIR); const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => { svgFiles.forEach((svgFile) => {
const iconName = path.basename(svgFile, '.svg'); const iconName = path.basename(svgFile, '.svg');
const componentName = toPascalCase(iconName); const componentName = toPascalCase(iconName);

View File

@@ -1,7 +1,14 @@
import { forwardRef, createElement } from 'react'; import { forwardRef, createElement, ReactSVG, SVGProps } from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import defaultAttributes from './defaultAttributes'; import defaultAttributes from './defaultAttributes';
type IconNode = [elementName: keyof ReactSVG, attrs: Record<string, string>][]
export type SVGAttributes = Partial<SVGProps<SVGSVGElement>>
export interface LucideProps extends SVGAttributes {
size?: string | number
}
/** /**
* Converts string to KebabCase * Converts string to KebabCase
* Copied from scripts/helper. If anyone knows how to properly import it here * Copied from scripts/helper. If anyone knows how to properly import it here
@@ -10,10 +17,10 @@ import defaultAttributes from './defaultAttributes';
* @param {string} string * @param {string} string
* @returns {string} A kebabized string * @returns {string} A kebabized string
*/ */
export const toKebabCase = string => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); export const toKebabCase = (string: string) => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
export default (iconName, iconNode) => { const createReactComponent = (iconName: string, iconNode: IconNode) => {
const Component = forwardRef( const Component = forwardRef<SVGSVGElement, LucideProps>(
({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }, ref) => ({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }, ref) =>
createElement( createElement(
'svg', 'svg',
@@ -27,7 +34,12 @@ export default (iconName, iconNode) => {
className: `lucide lucide-${toKebabCase(iconName)}`, className: `lucide lucide-${toKebabCase(iconName)}`,
...rest, ...rest,
}, },
[...iconNode.map(([tag, attrs]) => createElement(tag, attrs)), ...(children || [])], [
...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
...(
(Array.isArray(children) ? children : [children]) || []
)
],
), ),
); );
@@ -41,3 +53,5 @@ export default (iconName, iconNode) => {
return Component; return Component;
}; };
export default createReactComponent

View File

@@ -1,5 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Using lucide icon components should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"lucide lucide-grid\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components should render an component 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\\" class=\\"lucide lucide-grid\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -0,0 +1,5 @@
// Vitest Snapshot v1
exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `"<svg xmlns=\\"http://www.w3.org/2000/svg\\" width=\\"48\\" height=\\"48\\" viewBox=\\"0 0 24 24\\" fill=\\"none\\" stroke=\\"red\\" stroke-width=\\"4\\" stroke-linecap=\\"round\\" stroke-linejoin=\\"round\\" class=\\"lucide lucide-grid\\" data-testid=\\"grid-icon\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;
exports[`Using lucide icon components > should render an component 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\\" class=\\"lucide lucide-grid\\"><rect x=\\"3\\" y=\\"3\\" width=\\"18\\" height=\\"18\\" rx=\\"2\\" ry=\\"2\\"></rect><line x1=\\"3\\" y1=\\"9\\" x2=\\"21\\" y2=\\"9\\"></line><line x1=\\"3\\" y1=\\"15\\" x2=\\"21\\" y2=\\"15\\"></line><line x1=\\"9\\" y1=\\"3\\" x2=\\"9\\" y2=\\"21\\"></line><line x1=\\"15\\" y1=\\"3\\" x2=\\"15\\" y2=\\"21\\"></line></svg>"`;

View File

@@ -1,3 +1,4 @@
import { describe, it, expect } from 'vitest';
import React from 'react'; import React from 'react';
import { render } from '@testing-library/react' import { render } from '@testing-library/react'
import { Grid } from '../src/icons' import { Grid } from '../src/icons'
@@ -20,7 +21,7 @@ describe('Using lucide icon components', () => {
/>, />,
); );
const { attributes } = getByTestId(testId); const { attributes } = getByTestId(testId) as unknown as{ attributes: Record<string, { value: string }>};
expect(attributes.stroke.value).toBe('red'); expect(attributes.stroke.value).toBe('red');
expect(attributes.width.value).toBe('48'); expect(attributes.width.value).toBe('48');
expect(attributes.height.value).toBe('48'); expect(attributes.height.value).toBe('48');

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,24 @@
{
"compilerOptions": {
"strict": true,
"declaration": true,
"noEmitOnError": true,
"noEmit": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"module": "ESNext",
"target": "ESNext",
"esModuleInterop": true,
"isolatedModules": true,
"lib": ["esnext", "dom"],
"skipLibCheck": true,
"resolveJsonModule": true,
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"sourceMap": true,
"outDir": "./dist",
"declarationMap": true,
"jsx": "react-jsx",
},
"exclude": ["**/node_modules"]
}

View File

@@ -0,0 +1,19 @@
import { defineConfig } from 'vitest/config'
import react from '@vitejs/plugin-react'
export default defineConfig({
plugins: [react()],
test: {
globals: true,
environment: 'jsdom',
transformMode: {
web: [/\.jsx?$/],
},
setupFiles: './tests/setupVitest.js',
threads: false,
isolate: false,
},
resolve: {
conditions: ['development', 'browser'],
},
});

View File

@@ -1,6 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: ['solid'],
env: mainConfig.env,
};

View File

@@ -22,26 +22,24 @@
], ],
"sideEffects": false, "sideEffects": false,
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:types && pnpm build:bundles", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts",
"build:es": "babel src -d dist/esm",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test:jest": "jest", "test": "vitest run",
"test": "vitest",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@testing-library/jest-dom": "^5.16.5", "@testing-library/jest-dom": "^5.16.5",
"babel-preset-solid": "^1.5.4", "babel-preset-solid": "^1.5.4",
"jest": "^26.6.3",
"jsdom": "^20.0.0", "jsdom": "^20.0.0",
"rollup": "^3.5.1",
"solid-js": "^1.4.7", "solid-js": "^1.4.7",
"solid-testing-library": "^0.3.0", "solid-testing-library": "^0.3.0",
"solid-jest": "^0.2.0", "vite": "^3.2.4",
"vite": "^2.6.4",
"vite-plugin-solid": "^2.3.0", "vite-plugin-solid": "^2.3.0",
"vitest": "^0.23.2" "vitest": "^0.23.2"
}, },

View File

@@ -1,10 +1,10 @@
import plugins from '../../rollup.plugins.mjs'; import plugins from '@lucide/rollup-plugins';
import pkg from './package.json' assert { type: 'json' }; import pkg from './package.json' assert { type: 'json' };
const packageName = 'LucideSolid'; const packageName = 'LucideSolid';
const outputFileName = 'lucide-solid'; const outputFileName = 'lucide-solid';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = [`src/lucide-solid.js`]; const inputs = [`src/lucide-solid.ts`];
const bundles = [ const bundles = [
{ {
format: 'umd', format: 'umd',
@@ -22,17 +22,35 @@ const bundles = [
inputs, inputs,
outputDir, outputDir,
}, },
{
format: 'es',
inputs,
outputDir,
},
{
format: 'esm',
inputs,
outputDir,
preserveModules: true,
},
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify }) => .map(({ inputs, outputDir, format, minify, preserveModules }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: plugins(pkg, minify), plugins: plugins(pkg, minify),
external: ['solid-js', 'solid-js/h'], external: ['solid-js', 'solid-js/h'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules
? {
dir: `${outputDir}/${format}`,
}
: {
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
}),
preserveModules,
format, format,
sourcemap: true, sourcemap: true,
globals: { globals: {

View File

@@ -5,10 +5,10 @@ import {
resetFile, resetFile,
toPascalCase, toPascalCase,
appendFile, appendFile,
getCurrentDirPath getCurrentDirPath,
} from '../../../scripts/helpers.mjs'; } from '../../../scripts/helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url) const currentDir = getCurrentDirPath(import.meta.url);
const srcDirectory = path.join(currentDir, '../dist'); const srcDirectory = path.join(currentDir, '../dist');
// Declare type definitions // Declare type definitions
@@ -16,9 +16,8 @@ const typeDefinitions = `\
/// <reference types="solid-js" /> /// <reference types="solid-js" />
import { JSX } from 'solid-js' import { JSX } from 'solid-js'
interface LucideProps extends Partial<JSX.IntrinsicElements & JSX.SvgSVGAttributes<SVGSVGElement>> { interface LucideProps extends Partial<JSX.SvgSVGAttributes<SVGSVGElement>> {
key?: string | number; key?: string | number;
ref?: string | ((component: any) => any);
color?: string color?: string
size?: string | number size?: string | number
strokeWidth?: string | number strokeWidth?: string | number
@@ -36,7 +35,7 @@ writeFile(typeDefinitions, TYPES_FILE, srcDirectory);
const svgFiles = readSvgDirectory(ICONS_DIR); const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => { svgFiles.forEach((svgFile) => {
const iconName = path.basename(svgFile, '.svg'); const iconName = path.basename(svgFile, '.svg');
const componentName = toPascalCase(iconName); const componentName = toPascalCase(iconName);

View File

@@ -1,7 +1,17 @@
import h from 'solid-js/h'; import h from 'solid-js/h';
import { splitProps } from 'solid-js'; import { JSX, splitProps } from 'solid-js';
import defaultAttributes from './defaultAttributes'; import defaultAttributes from './defaultAttributes';
type IconNode = [elementName: keyof JSX.IntrinsicElements, attrs: Record<string, string>][]
interface LucideProps extends Partial<JSX.SvgSVGAttributes<SVGSVGElement>> {
key?: string | number;
color?: string
size?: string | number
strokeWidth?: string | number
class?: string
}
/** /**
* Converts string to KebabCase * Converts string to KebabCase
* Copied from scripts/helper. If anyone knows how to properly import it here * Copied from scripts/helper. If anyone knows how to properly import it here
@@ -10,10 +20,10 @@ import defaultAttributes from './defaultAttributes';
* @param {string} string * @param {string} string
* @returns {string} A kebabized string * @returns {string} A kebabized string
*/ */
export const toKebabCase = string => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); export const toKebabCase = (string: string) => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
export default (iconName, iconNode) => { export default (iconName: string, iconNode: IconNode) => {
const Component = props => { const Component = (props: LucideProps) => {
const [localProps, rest] = splitProps(props, [ const [localProps, rest] = splitProps(props, [
'color', 'color',
'size', 'size',

View File

@@ -1,14 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: mainConfig.env,
};

View File

@@ -1,11 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
transformIgnorePatterns: [`/node_modules`],
transform: {
'^.+\\.js$': 'babel-jest',
'^.+\\.svelte$': 'svelte-jester',
},
moduleFileExtensions: ['js', 'svelte'],
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};

View File

@@ -1,7 +1,7 @@
{ {
"name": "lucide-svelte", "name": "lucide-svelte",
"description": "A Lucide icon library package for Svelte applications", "description": "A Lucide icon library package for Svelte applications",
"version": "0.102.0", "version": "0.104.0",
"license": "ISC", "license": "ISC",
"homepage": "https://lucide.dev", "homepage": "https://lucide.dev",
"bugs": "https://github.com/lucide-icons/lucide/issues", "bugs": "https://github.com/lucide-icons/lucide/issues",
@@ -12,42 +12,45 @@
}, },
"author": "Eric Fennis", "author": "Eric Fennis",
"amdName": "lucide-svelte", "amdName": "lucide-svelte",
"main": "dist/cjs/lucide-svelte.js", "type": "module",
"main:umd": "dist/umd/lucide-svelte.js", "main": "dist/esm/lucide-svelte.js",
"module": "dist/esm/lucide-svelte.js", "module": "dist/esm/lucide-svelte.js",
"svelte": "dist/esm/lucide-svelte.js", "svelte": "dist/svelte/lucide-svelte.js",
"unpkg": "dist/umd/lucide-svelte.min.js",
"typings": "dist/lucide-svelte.d.ts", "typings": "dist/lucide-svelte.d.ts",
"sideEffects": false, "sideEffects": false,
"files": [ "files": [
"dist" "dist"
], ],
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:bundles && pnpm build:types", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:strip && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.svelte && rm -f index.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.svelte && rm -f index.js",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --exportFileName=index.js --iconFileExtention=.svelte --pretty=false", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --exportFileName=index.ts --iconFileExtension=.svelte --pretty=false",
"build:es": "babel src -d dist/esm --copy-files",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "build:strip": "svelte-strip strip src/ dist/svelte",
"test:watch": "jest --watch", "test": "vitest",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@rollup/plugin-node-resolve": "^15.0.1",
"@sveltejs/vite-plugin-svelte": "^1.2.0",
"@testing-library/jest-dom": "^5.16.2", "@testing-library/jest-dom": "^5.16.2",
"@testing-library/preact": "^2.0.1",
"@testing-library/svelte": "^3.0.3", "@testing-library/svelte": "^3.0.3",
"babel-preset-preact": "^2.0.0", "@tsconfig/svelte": "^3.0.0",
"jest": "^28.1.3", "jsdom": "^20.0.3",
"rollup": "^3.5.1",
"rollup-plugin-svelte": "^7.1.0", "rollup-plugin-svelte": "^7.1.0",
"svelte": "^3.49.0", "svelte": "^3.53.1",
"svelte-jester": "^2.3.1", "svelte-check": "^2.9.2",
"svelte-preprocess": "^4.10.1", "svelte-preprocess": "^4.10.7",
"svelte2tsx": "^0.4.12" "svelte-strip": "^1.0.3",
"typescript": "^4.9.3",
"vite": "^3.1.0",
"vitest": "^0.23.2"
}, },
"peerDependencies": { "peerDependencies": {
"svelte": "^3.49.0", "svelte": "^3.49.0"
"svelte2tsx": "^0.4.12"
} }
} }

View File

@@ -1,66 +1,76 @@
/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable import/no-extraneous-dependencies */
import svelte from 'rollup-plugin-svelte'; import svelte from 'rollup-plugin-svelte';
import preprocess from 'svelte-preprocess';
import bundleSize from '@atomico/rollup-plugin-sizes';
import { terser } from 'rollup-plugin-terser';
import license from 'rollup-plugin-license';
import resolve from '@rollup/plugin-node-resolve';
import commonJS from '@rollup/plugin-commonjs';
import pkg from './package.json' assert { type: 'json' }; import pkg from './package.json' assert { type: 'json' };
import plugins from '@lucide/rollup-plugins';
import resolve from '@rollup/plugin-node-resolve';
import svelteConfig from './svelte.config.js';
const packageName = 'LucideSvelte'; const packageName = 'LucideSvelte';
const outputFileName = 'lucide-svelte'; const outputFileName = 'lucide-svelte';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = ['./src/lucide-svelte.js']; const inputs = ['./src/lucide-svelte.ts'];
const bundles = [ const bundles = [
// Not sure if this one is needed for Svelte
// {
// format: 'cjs',
// inputs,
// outputDir,
// },
{ {
format: 'umd', format: 'es',
inputs, inputs,
outputDir, outputDir,
minify: true,
sourcemap: true,
}, },
{ {
format: 'umd', format: 'esm',
inputs, inputs,
outputDir, outputDir,
sourcemap: true, preserveModules: true,
}, },
{ {
format: 'cjs', format: 'svelte',
inputs, inputs,
outputDir, outputDir,
sourcemap: true, preserveModules: true,
}, },
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify }) => .map(({ inputs, outputDir, format, minify, preserveModules }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: [ plugins: [
...(format !== 'svelte' ? [
svelte({ svelte({
preprocess, ...svelteConfig,
include: 'src/**/*.svelte',
compilerOptions: { compilerOptions: {
dev: false, dev: false,
css: false,
hydratable: true,
}, },
emitCss: false, emitCss: false,
}), }),
resolve(), resolve({
commonJS({ browser: true,
include: 'node_modules/**', exportConditions: ['svelte'],
extensions: ['.svelte']
}), }),
minify && terser(), ] : []),
license({ ...plugins(pkg, minify),
banner: `${pkg.name} v${pkg.version} - ${pkg.license}`,
}),
bundleSize(),
], ],
external: ['svelte'], external: format === 'svelte' ? [/\.svelte/] : ['svelte'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules
? {
dir: `${outputDir}/${format}`,
}
: {
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
format, }),
preserveModules,
format: format === 'svelte' ? 'esm' : format,
sourcemap: true, sourcemap: true,
globals: { globals: {
svelte: 'svelte', svelte: 'svelte',

View File

@@ -5,16 +5,16 @@ import {
resetFile, resetFile,
toPascalCase, toPascalCase,
appendFile, appendFile,
getCurrentDirPath getCurrentDirPath,
} from '../../../scripts/helpers.mjs'; } from '../../../scripts/helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url) const currentDir = getCurrentDirPath(import.meta.url);
const srcDirectory = path.join(currentDir, '../dist'); const srcDirectory = path.join(currentDir, '../dist');
// Declare type definitions // Declare type definitions
const typeDefinitions = `\ const typeDefinitions = `\
/// <reference types="svelte" /> /// <reference types="svelte" />
/// <reference types="svelte2tsx/svelte-jsx" /> /// <reference types="svelte-check/dist/src/svelte-jsx" />
import { SvelteComponentTyped } from "svelte"; import { SvelteComponentTyped } from "svelte";
interface IconProps extends Partial<svelte.JSX.SVGProps<SVGSVGElement>> { interface IconProps extends Partial<svelte.JSX.SVGProps<SVGSVGElement>> {
@@ -41,7 +41,7 @@ writeFile(typeDefinitions, TYPES_FILE, srcDirectory);
const svgFiles = readSvgDirectory(ICONS_DIR); const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => { svgFiles.forEach((svgFile) => {
const iconName = path.basename(svgFile, '.svg'); const iconName = path.basename(svgFile, '.svg');
const componentName = toPascalCase(iconName); const componentName = toPascalCase(iconName);

View File

@@ -1,17 +1,14 @@
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import { stringify } from 'svgson'; export default ({ iconName, children }) =>
`\
export default ({ iconName, children }) => { <script lang="ts">
const iconChildNodes = children.map(([name, attributes]) => ({ name, attributes, children: [] }));
const iconChildrenHTML = iconChildNodes.map(stringify).join('\n ');
return `\
<script>
import Icon from '../Icon.svelte'; import Icon from '../Icon.svelte';
import type { IconNode } from '../types';
const iconNode: IconNode = ${JSON.stringify(children)};
</script> </script>
<Icon name="${iconName}" {...$$props} > <Icon name="${iconName}" {...$$props} iconNode={iconNode}>
${iconChildrenHTML}
<slot/> <slot/>
</Icon> </Icon>
`; `;
};

View File

@@ -1,9 +1,12 @@
<script> <script lang="ts">
import defaultAttributes from './defaultAttributes' import defaultAttributes from './defaultAttributes'
export let name import type { IconNode } from './types';
export let name: string
export let color = 'currentColor' export let color = 'currentColor'
export let size = 24 export let size = 24
export let strokeWidth = 2 export let strokeWidth = 2
export let iconNode: IconNode
</script> </script>
<svg <svg
@@ -15,5 +18,8 @@
stroke-width={strokeWidth} stroke-width={strokeWidth}
class={`lucide-icon lucide lucide-${name} ${$$props.class ?? ''}`} class={`lucide-icon lucide lucide-${name} ${$$props.class ?? ''}`}
> >
{#each iconNode as [tag, attrs]}
<svelte:element this={tag} {...attrs}/>
{/each}
<slot /> <slot />
</svg> </svg>

View File

@@ -1,4 +1,6 @@
export default { import type { Attrs } from "./types";
const defaultAttributes: Attrs = {
xmlns: 'http://www.w3.org/2000/svg', xmlns: 'http://www.w3.org/2000/svg',
width: 24, width: 24,
height: 24, height: 24,
@@ -9,3 +11,5 @@ export default {
'stroke-linecap': 'round', 'stroke-linecap': 'round',
'stroke-linejoin': 'round', 'stroke-linejoin': 'round',
}; };
export default defaultAttributes;

View File

@@ -0,0 +1,2 @@
export * from './icons';
export { default as defaultAttributes } from './defaultAttributes'

View File

@@ -0,0 +1,5 @@
/// <reference types="svelte" />
/// <reference types="svelte2tsx/svelte-jsx" />
export type Attrs = svelte.JSX.SVGProps<SVGSVGElement>
export type IconNode = [elementName: keyof svelte.JSX.IntrinsicElements, attrs: Attrs][]

View File

@@ -1,6 +1,8 @@
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
const sveltePreprocess = require('svelte-preprocess'); import sveltePreprocess from 'svelte-preprocess';
module.exports = { export default {
preprocess: sveltePreprocess(), preprocess: sveltePreprocess({
typescript: true,
}),
}; };

View File

@@ -1,4 +1,4 @@
<script> <script lang="ts">
import Smile from '../src/icons/smile.svelte' import Smile from '../src/icons/smile.svelte'
</script> </script>

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1
exports[`Using lucide icon components should add a class to the element 1`] = ` exports[`Using lucide icon components > should add a class to the element 1`] = `
<svg <svg
class="lucide-icon lucide lucide-smile my-icon" class="lucide-icon lucide lucide-smile my-icon"
fill="none" fill="none"
@@ -37,10 +37,11 @@ exports[`Using lucide icon components should add a class to the element 1`] = `
y2="9" y2="9"
/> />
</svg> </svg>
`; `;
exports[`Using lucide icon components should adjust the size, stroke color and stroke width 1`] = ` exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `
<body> <body>
<div> <div>
<svg <svg
@@ -79,12 +80,13 @@ exports[`Using lucide icon components should adjust the size, stroke color and s
y2="9" y2="9"
/> />
</svg> </svg>
</div> </div>
</body> </body>
`; `;
exports[`Using lucide icon components should render an component 1`] = ` exports[`Using lucide icon components > should render an component 1`] = `
<body> <body>
<div> <div>
<svg <svg
@@ -123,12 +125,13 @@ exports[`Using lucide icon components should render an component 1`] = `
y2="9" y2="9"
/> />
</svg> </svg>
</div> </div>
</body> </body>
`; `;
exports[`Using lucide icon components should render an icon slot 1`] = ` exports[`Using lucide icon components > should render an icon slot 1`] = `
<body> <body>
<div> <div>
<svg <svg
@@ -167,6 +170,7 @@ exports[`Using lucide icon components should render an icon slot 1`] = `
y2="9" y2="9"
/> />
<text> <text>
Test Test
</text> </text>

View File

@@ -1,8 +1,10 @@
import { render, fireEvent } from '@testing-library/svelte'; import { describe, it, expect, afterEach } from 'vitest';
import { render, cleanup } from '@testing-library/svelte';
import { Smile } from '../src/icons' import { Smile } from '../src/icons'
import TestSlots from './TestSlots.svelte' import TestSlots from './TestSlots.svelte'
describe('Using lucide icon components', () => { describe('Using lucide icon components', () => {
afterEach(() => cleanup())
it('should render an component', () => { it('should render an component', () => {
const { container } = render(Smile); const { container } = render(Smile);
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,19 @@
{
"extends": "@tsconfig/svelte/tsconfig.json",
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"resolveJsonModule": true,
"allowJs": true,
"checkJs": true,
"isolatedModules": true,
},
"include": [
"src/**/*.d.ts",
"src/**/*.ts",
"src/**/*.js",
"src/**/*.svelte",
"tests/**/*.ts"
],
}

View File

@@ -0,0 +1,13 @@
import { defineConfig } from 'vitest/config'
import { svelte } from '@sveltejs/vite-plugin-svelte'
export default defineConfig({
plugins: [svelte({ hot: false })],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './tests/setupVitest.ts',
threads: false,
isolate: false,
},
});

View File

@@ -1,14 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: mainConfig.env,
};

View File

@@ -1,15 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transform: {
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest',
},
transformIgnorePatterns: [`/node_modules`],
snapshotSerializers: ['jest-serializer-vue'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};

View File

@@ -1,6 +1,6 @@
{ {
"name": "lucide-vue-next", "name": "lucide-vue-next",
"version": "0.102.0", "version": "0.104.0",
"author": "Eric Fennis", "author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 3 applications", "description": "A Lucide icon library package for Vue 3 applications",
"license": "ISC", "license": "ISC",
@@ -24,24 +24,27 @@
"nuxt.js" "nuxt.js"
], ],
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:types && pnpm build:bundles", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles && pnpm build:types",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf ./src/icons/*.ts",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtension=.ts --exportFileName=index.ts",
"build:es": "babel src -d dist/esm",
"build:types": "node ./scripts/buildTypes.mjs", "build:types": "node ./scripts/buildTypes.mjs",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "test": "vitest",
"test:watch": "jest --watchAll",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@testing-library/vue": "^6.4.2", "@lucide/rollup-plugins": "workspace:*",
"@vue/compiler-sfc": "3.0.6", "@testing-library/jest-dom": "^5.16.5",
"@vue/test-utils": "2.0.0-rc.18", "@testing-library/vue": "^6.6.1",
"jest-serializer-vue": "^2.0.2", "@vue/compiler-sfc": "3.2.45",
"vue": "3.0.6", "@vue/test-utils": "2.2.4",
"vue-jest": "^5.0.0-alpha.10" "@vitejs/plugin-vue": "^3.2.0",
"rollup": "^3.5.1",
"vite": "^3.1.0",
"vitest": "^0.24.3",
"vue": "3.2.45",
"jsdom": "^20.0.3"
}, },
"peerDependencies": { "peerDependencies": {
"vue": ">=3.0.1" "vue": ">=3.0.1"

View File

@@ -1,10 +1,10 @@
import plugins from '../../rollup.plugins.mjs'; import plugins from '@lucide/rollup-plugins';
import pkg from './package.json' assert { type: 'json' }; import pkg from './package.json' assert { type: 'json' };
const packageName = 'LucideVueNext'; const packageName = 'LucideVueNext';
const outputFileName = 'lucide-vue-next'; const outputFileName = 'lucide-vue-next';
const outputDir = 'dist'; const outputDir = 'dist';
const inputs = ['src/lucide-vue-next.js']; const inputs = ['src/lucide-vue-next.ts'];
const bundles = [ const bundles = [
{ {
format: 'umd', format: 'umd',
@@ -22,18 +22,36 @@ const bundles = [
inputs, inputs,
outputDir, outputDir,
}, },
{
format: 'es',
inputs,
outputDir,
},
{
format: 'esm',
inputs,
outputDir,
preserveModules: true,
},
]; ];
const configs = bundles const configs = bundles
.map(({ inputs, outputDir, format, minify }) => .map(({ inputs, outputDir, format, minify, preserveModules }) =>
inputs.map(input => ({ inputs.map(input => ({
input, input,
plugins: plugins(pkg, minify), plugins: plugins(pkg, minify),
external: ['vue'], external: ['vue'],
output: { output: {
name: packageName, name: packageName,
...(preserveModules
? {
dir: `${outputDir}/${format}`,
}
: {
file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`,
}),
format, format,
preserveModules,
sourcemap: true, sourcemap: true,
globals: { globals: {
vue: 'vue', vue: 'vue',

View File

@@ -5,10 +5,10 @@ import {
resetFile, resetFile,
appendFile, appendFile,
toPascalCase, toPascalCase,
getCurrentDirPath getCurrentDirPath,
} from '../../../scripts/helpers.mjs'; } from '../../../scripts/helpers.mjs';
const currentDir = getCurrentDirPath(import.meta.url) const currentDir = getCurrentDirPath(import.meta.url);
const TARGET_DIR = path.join(currentDir, '../dist'); const TARGET_DIR = path.join(currentDir, '../dist');
const ICONS_DIR = path.resolve(currentDir, '../../../icons'); const ICONS_DIR = path.resolve(currentDir, '../../../icons');
@@ -32,7 +32,7 @@ appendFile(typeDefinitions, TYPES_FILE_NAME, TARGET_DIR);
const svgFiles = readSvgDirectory(ICONS_DIR); const svgFiles = readSvgDirectory(ICONS_DIR);
svgFiles.forEach(svgFile => { svgFiles.forEach((svgFile) => {
const nameSvg = path.basename(svgFile, '.svg'); const nameSvg = path.basename(svgFile, '.svg');
const componentName = toPascalCase(nameSvg); const componentName = toPascalCase(nameSvg);

View File

@@ -1,6 +1,15 @@
import { h } from 'vue'; import { h } from 'vue';
import type { SVGAttributes, FunctionalComponent } from 'vue';
import defaultAttributes from './defaultAttributes'; import defaultAttributes from './defaultAttributes';
// Create interface extending SVGAttributes
export interface SVGProps extends Partial<SVGAttributes> {
size?: 24 | number
}
type IconNode = [elementName: string, attrs: Record<string, string>][]
/** /**
* Converts string to KebabCase * Converts string to KebabCase
* Copied from scripts/helper. If anyone knows how to properly import it here * Copied from scripts/helper. If anyone knows how to properly import it here
@@ -9,11 +18,11 @@ import defaultAttributes from './defaultAttributes';
* @param {string} string * @param {string} string
* @returns {string} A kebabized string * @returns {string} A kebabized string
*/ */
export const toKebabCase = string => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase(); export const toKebabCase = (string: string) => string.replace(/([a-z0-9])([A-Z])/g, '$1-$2').toLowerCase();
const createVueComponent = (iconName, iconNode) => ( const createVueComponent = (iconName: string, iconNode: IconNode): FunctionalComponent<SVGProps> => (
{ size, color, ...props }, // props { size, color, ...props }, // props
{ attrs, emit, slots } // context { attrs, slots } // context
) => { ) => {
return h( return h(
'svg', 'svg',

View File

@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Vitest Snapshot v1
exports[`Using lucide icon components should add a class to the element 1`] = ` exports[`Using lucide icon components > should add a class to the element 1`] = `
<div> <div>
<svg <svg
class="my-icon" class="my-icon"
@@ -38,7 +38,7 @@ exports[`Using lucide icon components should add a class to the element 1`] = `
</div> </div>
`; `;
exports[`Using lucide icon components should add a style attribute to the element 1`] = ` exports[`Using lucide icon components > should add a style attribute to the element 1`] = `
<div> <div>
<svg <svg
class="lucide lucide-smile-icon" class="lucide lucide-smile-icon"
@@ -77,7 +77,7 @@ exports[`Using lucide icon components should add a style attribute to the elemen
</div> </div>
`; `;
exports[`Using lucide icon components should adjust the size, stroke color and stroke width 1`] = ` exports[`Using lucide icon components > should adjust the size, stroke color and stroke width 1`] = `
<div> <div>
<svg <svg
class="lucide lucide-smile-icon" class="lucide lucide-smile-icon"
@@ -117,7 +117,7 @@ exports[`Using lucide icon components should adjust the size, stroke color and s
</div> </div>
`; `;
exports[`Using lucide icon components should pass children to the icon slot 1`] = ` exports[`Using lucide icon components > should pass children to the icon slot 1`] = `
<div> <div>
<svg <svg
class="lucide lucide-smile-icon" class="lucide lucide-smile-icon"
@@ -160,7 +160,7 @@ exports[`Using lucide icon components should pass children to the icon slot 1`]
</div> </div>
`; `;
exports[`Using lucide icon components should render an component 1`] = ` exports[`Using lucide icon components > should render an component 1`] = `
<div> <div>
<svg <svg
class="lucide lucide-smile-icon" class="lucide lucide-smile-icon"

View File

@@ -1,7 +1,10 @@
import {render, fireEvent} from '@testing-library/vue' import { describe, it, expect, vi, afterEach } from 'vitest';
import {render, fireEvent, cleanup } from '@testing-library/vue'
import { Smile } from '../src/icons' import { Smile } from '../src/icons'
describe('Using lucide icon components', () => { describe('Using lucide icon components', () => {
afterEach(() => cleanup())
it('should render an component', () => { it('should render an component', () => {
const { container } = render(Smile) const { container } = render(Smile)
expect(container).toMatchSnapshot(); expect(container).toMatchSnapshot();
@@ -55,7 +58,7 @@ describe('Using lucide icon components', () => {
}); });
it('should call the onClick event', async () => { it('should call the onClick event', async () => {
const onClick = jest.fn() const onClick = vi.fn()
render(Smile, { render(Smile, {
attrs: { attrs: {
onClick, onClick,

View File

@@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"moduleResolution": "Node",
"strict": true,
"jsx": "preserve",
"resolveJsonModule": true,
"isolatedModules": true,
"esModuleInterop": true,
"lib": ["ESNext", "DOM"],
"skipLibCheck": true,
"noEmit": true,
"types": ["vitest/globals"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
}

View File

@@ -0,0 +1,11 @@
import { defineConfig } from 'vitest/config'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
test: {
globals: true,
environment: 'jsdom',
setupFiles: './tests/setupVitest.js',
},
});

View File

@@ -1,14 +0,0 @@
const mainConfig = require('../../babel.config');
module.exports = {
presets: [
[
'@babel/env',
{
loose: true,
modules: false,
},
],
],
env: mainConfig.env,
};

View File

@@ -1,15 +0,0 @@
module.exports = {
verbose: true,
roots: ['<rootDir>/src/', '<rootDir>/tests/'],
moduleFileExtensions: ['js'],
transform: {
'^.+\\.js$': 'babel-jest',
'^.+\\.vue$': 'vue-jest',
},
transformIgnorePatterns: [`/node_modules`],
snapshotSerializers: ['jest-serializer-vue'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1',
},
setupFilesAfterEnv: ['@testing-library/jest-dom/extend-expect'],
};

View File

@@ -1,6 +1,6 @@
{ {
"name": "lucide-vue", "name": "lucide-vue",
"version": "0.102.0", "version": "0.104.0",
"author": "Eric Fennis", "author": "Eric Fennis",
"description": "A Lucide icon library package for Vue 2 applications", "description": "A Lucide icon library package for Vue 2 applications",
"license": "ISC", "license": "ISC",
@@ -23,24 +23,27 @@
"nuxt.js" "nuxt.js"
], ],
"scripts": { "scripts": {
"build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:es && pnpm build:bundles", "build": "pnpm clean && pnpm copy:license && pnpm build:icons && pnpm build:bundles",
"copy:license": "cp ../../LICENSE ./LICENSE", "copy:license": "cp ../../LICENSE ./LICENSE",
"clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js", "clean": "rm -rf dist && rm -rf stats && rm -rf ./src/icons/*.js",
"build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs", "build:icons": "node ../../scripts/buildIcons.mjs --output=./src --templateSrc=./scripts/exportTemplate.mjs --renderUniqueKey --iconFileExtention=.ts --exportFileName=index.ts",
"build:es": "babel src -d dist/esm",
"build:bundles": "rollup -c ./rollup.config.mjs", "build:bundles": "rollup -c ./rollup.config.mjs",
"test": "jest", "test": "vitest",
"test:watch": "jest --watchAll",
"version": "pnpm version --git-tag-version=false" "version": "pnpm version --git-tag-version=false"
}, },
"devDependencies": { "devDependencies": {
"@lucide/rollup-plugins": "workspace:*",
"@testing-library/jest-dom": "^5.16.2", "@testing-library/jest-dom": "^5.16.2",
"@testing-library/vue": "^5.8.2", "@testing-library/vue": "^5.8.2",
"@vitejs/plugin-vue2": "^2.0.1",
"@vue/test-utils": "1.3.0", "@vue/test-utils": "1.3.0",
"jest-serializer-vue": "^2.0.2", "jest-serializer-vue": "^2.0.2",
"vue": "2.6.14", "rollup": "^3.5.1",
"vue-jest": "^3.0.7", "typescript": "^4.8.4",
"vue-template-compiler": "2.6.14" "vite": "^3.1.0",
"vitest": "^0.24.3",
"vue": "2.7.14",
"vue-template-compiler": "2.7.14"
}, },
"peerDependencies": { "peerDependencies": {
"vue": "^2.6.12" "vue": "^2.6.12"

Some files were not shown because too many files have changed in this diff Show More