From c547243f6e6aa4d96e119fa50e5b71ff47e4965d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Kuna?= <1282324+codecalm@users.noreply.github.com> Date: Thu, 8 Feb 2024 23:08:55 +0100 Subject: [PATCH] React Native new package (#999) --- packages/icons-react-native/build.mjs | 28 +++++++++ packages/icons-react-native/package.json | 60 ++++++++++++++++++ packages/icons-react-native/rollup.config.mjs | 61 +++++++++++++++++++ packages/icons-react-native/src/aliases.ts | 7 +++ .../src/createReactNativeComponent.ts | 50 +++++++++++++++ .../src/defaultAttributes.ts | 21 +++++++ .../src/tabler-icons-react-native.ts | 8 +++ packages/icons-react-native/src/types.ts | 15 +++++ packages/icons-react-native/tsconfig.json | 23 +++++++ 9 files changed, 273 insertions(+) create mode 100644 packages/icons-react-native/build.mjs create mode 100644 packages/icons-react-native/package.json create mode 100644 packages/icons-react-native/rollup.config.mjs create mode 100644 packages/icons-react-native/src/aliases.ts create mode 100644 packages/icons-react-native/src/createReactNativeComponent.ts create mode 100644 packages/icons-react-native/src/defaultAttributes.ts create mode 100644 packages/icons-react-native/src/tabler-icons-react-native.ts create mode 100644 packages/icons-react-native/src/types.ts create mode 100644 packages/icons-react-native/tsconfig.json diff --git a/packages/icons-react-native/build.mjs b/packages/icons-react-native/build.mjs new file mode 100644 index 000000000..14e792e48 --- /dev/null +++ b/packages/icons-react-native/build.mjs @@ -0,0 +1,28 @@ +#!/usr/bin/env node + +import { buildIcons } from '../../.build/build-icons.mjs' + +const componentTemplate = ({ + name, + namePascal, + children +}) => `\ +import createReactNativeComponent from '../createReactNativeComponent'; +export default createReactNativeComponent('${name}', '${namePascal}', ${JSON.stringify(children)});`; + +const indexItemTemplate = ({ + name, + namePascal +}) => `export { default as ${namePascal} } from './${namePascal}';` + +const aliasTemplate = ({ fromPascal, toPascal }) => `export { default as Icon${fromPascal} } from './icons/Icon${toPascal}';\n` + +buildIcons({ + name: 'icons-react-native', + componentTemplate, + indexItemTemplate, + aliasTemplate, + indexFile: 'icons/index.ts', + pascalCase: true, + extension: 'ts' +}) diff --git a/packages/icons-react-native/package.json b/packages/icons-react-native/package.json new file mode 100644 index 000000000..c5383908f --- /dev/null +++ b/packages/icons-react-native/package.json @@ -0,0 +1,60 @@ +{ + "name": "@tabler/icons-react-native", + "version": "3.0.0-alpha.0", + "license": "MIT", + "author": "codecalm", + "description": "A set of free MIT-licensed high-quality SVG icons for you to use in your web projects.", + "homepage": "https://tabler-icons.io", + "bugs": { + "url": "https://github.com/tabler/tabler-icons/issues" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tabler/tabler-icons.git", + "directory": "packages/icons-react" + }, + "type": "module", + "amdName": "tabler-icons-react-native", + "main": "dist/cjs/tabler-icons-react-native.js", + "main:umd": "dist/umd/tabler-icons-react-native.js", + "module": "dist/esm/tabler-icons-react-native.js", + "unpkg": "dist/umd/tabler-icons-react-native.min.js", + "typings": "dist/tabler-icons-react-native.d.ts", + "react-native": "dist/esm/tabler-icons-react-native.js", + "sideEffects": false, + "files": [ + "dist" + ], + "scripts": { + "build": "pnpm run clean && pnpm run copy:license && pnpm run build:icons && pnpm typecheck && pnpm run build:bundles", + "build:icons": "node build.mjs", + "build:bundles": "rollup -c ./rollup.config.mjs", + "copy:license": "cp ../../LICENSE ./LICENSE", + "clean": "rm -rf dist && rm -rf ./src/icons/*.js && rm -rf ./src/icons/*.ts", + "test": "vitest run", + "typecheck": "tsc" + }, + "dependencies": { + "@tabler/icons": "3.0.0-alpha.0" + }, + "devDependencies": { + "@babel/preset-env": "7.23.8", + "@babel/preset-react": "7.23.3", + "@testing-library/react": "^14.1.2", + "@types/react": "18.2.48", + "@vitejs/plugin-react": "^4.2.1", + "babel-jest": "^29.7.0", + "react": "18.2.0", + "react-dom": "18.2.0", + "react-native": "^0.73.1", + "react-native-svg": "^14.1.0", + "react-test-renderer": "18.2.0" + }, + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0" + } +} \ No newline at end of file diff --git a/packages/icons-react-native/rollup.config.mjs b/packages/icons-react-native/rollup.config.mjs new file mode 100644 index 000000000..0fac66f4f --- /dev/null +++ b/packages/icons-react-native/rollup.config.mjs @@ -0,0 +1,61 @@ +import fs from 'fs' +import { getRollupPlugins } from '../../.build/rollup-plugins.mjs' +import dts from "rollup-plugin-dts"; + +const pkg = JSON.parse(fs.readFileSync('package.json', 'utf-8')) + +const packageName = '@tabler/icons-react-native'; +const outputFileName = 'tabler-icons-react-native'; +const outputDir = 'dist'; +const inputs = ['./src/tabler-icons-react-native.ts']; +const bundles = [ + { + format: 'cjs', + inputs, + outputDir, + }, + { + format: 'esm', + inputs, + outputDir, + preserveModules: true, + }, +]; + +const configs = bundles + .map(({ inputs, outputDir, format, minify, preserveModules }) => + inputs.map(input => ({ + input, + plugins: getRollupPlugins(pkg, minify), + external: ['react', 'react-native-svg'], + output: { + name: packageName, + ...(preserveModules + ? { + dir: `${outputDir}/${format}`, + } + : { + file: `${outputDir}/${format}/${outputFileName}${minify ? '.min' : ''}.js`, + }), + format, + sourcemap: true, + preserveModules, + globals: { + react: 'react', + 'react-native-svg': 'react-native-svg', + }, + }, + })), + ) + .flat(); + +export default [ + { + input: inputs[0], + output: [{ + file: `dist/${outputFileName}.d.ts`, format: "es" + }], + plugins: [dts()], + }, + ...configs +]; diff --git a/packages/icons-react-native/src/aliases.ts b/packages/icons-react-native/src/aliases.ts new file mode 100644 index 000000000..54e2932fa --- /dev/null +++ b/packages/icons-react-native/src/aliases.ts @@ -0,0 +1,7 @@ +export { default as IconCodeAsterix } from './icons/IconCodeAsterisk'; +export { default as IconDiscount2 } from './icons/IconRosetteDiscount'; +export { default as IconDiscount2Off } from './icons/IconRosetteDiscountOff'; +export { default as IconDiscountCheck } from './icons/IconRosetteDiscountCheck'; +export { default as IconDiscountCheckFilled } from './icons/IconRosetteDiscountCheckFilled'; +export { default as IconHandRock } from './icons/IconHandLoveYou'; +export { default as IconSortDeacendingSmallBig } from './icons/IconSortDescendingSmallBig'; diff --git a/packages/icons-react-native/src/createReactNativeComponent.ts b/packages/icons-react-native/src/createReactNativeComponent.ts new file mode 100644 index 000000000..35ff4ab10 --- /dev/null +++ b/packages/icons-react-native/src/createReactNativeComponent.ts @@ -0,0 +1,50 @@ +import { forwardRef, createElement, FunctionComponent } from 'react'; +import defaultAttributes, { childDefaultAttributes } from './defaultAttributes'; +import type { Icon, IconNode, IconProps } from './types'; +import { NativeSvg } from './types'; + +const createReactNativeComponent = ( + iconName: string, + iconNamePascal: string, + iconNode: IconNode, +): Icon => { + const Component = forwardRef( + ({ color = 'currentColor', size = 24, strokeWidth = 2, children, ...rest }: IconProps, ref) => { + const customAttrs = { + stroke: color, + strokeWidth, + ...rest, + }; + + return createElement( + NativeSvg.Svg as unknown as string, + { + ref, + ...defaultAttributes, + width: size, + height: size, + ...customAttrs, + ...rest, + }, + [ + ...iconNode.map(([tag, attrs]) => { + const upperCasedTag = (tag.charAt(0).toUpperCase() + + tag.slice(1)) as keyof typeof NativeSvg; + + return createElement( + NativeSvg[upperCasedTag] as FunctionComponent, + { ...childDefaultAttributes, ...customAttrs, ...attrs } as IconProps, + ); + }), + ...((Array.isArray(children) ? children : [children]) || []), + ], + ); + }, + ); + + Component.displayName = `${iconNamePascal}`; + + return Component; +}; + +export default createReactNativeComponent; diff --git a/packages/icons-react-native/src/defaultAttributes.ts b/packages/icons-react-native/src/defaultAttributes.ts new file mode 100644 index 000000000..3fae7d973 --- /dev/null +++ b/packages/icons-react-native/src/defaultAttributes.ts @@ -0,0 +1,21 @@ +const defaultAttributes = { + xmlns: 'http://www.w3.org/2000/svg', + width: 24, + height: 24, + viewBox: '0 0 24 24', + fill: 'none', + stroke: 'currentColor', + strokeWidth: 2, + strokeLinecap: 'round', + strokeLinejoin: 'round', +}; + +export const childDefaultAttributes = { + fill: defaultAttributes.fill, + stroke: defaultAttributes.stroke, + strokeWidth: defaultAttributes.strokeWidth, + strokeLinecap: defaultAttributes.strokeLinecap, + strokeLinejoin: defaultAttributes.strokeLinejoin, +}; + +export default defaultAttributes; diff --git a/packages/icons-react-native/src/tabler-icons-react-native.ts b/packages/icons-react-native/src/tabler-icons-react-native.ts new file mode 100644 index 000000000..3105ceed9 --- /dev/null +++ b/packages/icons-react-native/src/tabler-icons-react-native.ts @@ -0,0 +1,8 @@ +export * from './icons/index'; +export * as icons from './icons/index'; +export * from './aliases'; +export { default as createReactComponent } from './createReactNativeComponent'; + +export type { IconNode, IconProps, Icon } from './types'; + + diff --git a/packages/icons-react-native/src/types.ts b/packages/icons-react-native/src/types.ts new file mode 100644 index 000000000..d0895b9cb --- /dev/null +++ b/packages/icons-react-native/src/types.ts @@ -0,0 +1,15 @@ + +import { ForwardRefExoticComponent, ReactSVG, SVGProps } from 'react'; +import type { SvgProps } from 'react-native-svg'; +export * as NativeSvg from 'react-native-svg'; + +export type IconNode = [elementName: keyof ReactSVG, attrs: Record][]; + +export type SVGAttributes = Partial>; + +export interface IconProps extends SvgProps { + size?: string | number; + strokeWidth?: string | number; +} + +export type Icon = ForwardRefExoticComponent; diff --git a/packages/icons-react-native/tsconfig.json b/packages/icons-react-native/tsconfig.json new file mode 100644 index 000000000..23e3877e3 --- /dev/null +++ b/packages/icons-react-native/tsconfig.json @@ -0,0 +1,23 @@ +{ + "compilerOptions": { + "strict": true, + "declaration": false, + "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", + "jsx": "react-jsx" + }, + "exclude": ["**/node_modules"] +}