├── .eslintignore
├── .huskyrc
├── src
├── types
│ └── index.ts
├── index.ts
├── css
│ └── tailwind-setup.css
├── assets
│ └── check.svg
├── stories
│ └── ReactLibraryStarter.stories.tsx
├── components
│ └── App.tsx
└── typings.d.ts
├── .lintstagedrc
├── .storybook
├── Layout.tsx
├── preview.js
└── main.js
├── tailwind.config.js
├── .prettierrc
├── postcss.config.js
├── .gitignore
├── tsconfig.json
├── LICENSE
├── rollup.config.js
├── .eslintrc.json
├── README.md
└── package.json
/.eslintignore:
--------------------------------------------------------------------------------
1 | dist
--------------------------------------------------------------------------------
/.huskyrc:
--------------------------------------------------------------------------------
1 | {
2 | "hooks": {
3 | "pre-commit": "lint-staged"
4 | }
5 | }
--------------------------------------------------------------------------------
/src/types/index.ts:
--------------------------------------------------------------------------------
1 | export type AppProps = {
2 | text?: string
3 | description?: string
4 | }
5 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import './css/tailwind-setup.css'
2 |
3 | export { default as MyComponent } from './components/App'
4 |
--------------------------------------------------------------------------------
/.lintstagedrc:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "*.{ts,tsx}": ["eslint --fix"],
4 | "**/*.+(ts|tsx|json|css|md)": ["prettier --write"]
5 | }
--------------------------------------------------------------------------------
/src/css/tailwind-setup.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | .app {
6 | @apply bg-green-400;
7 | }
8 |
--------------------------------------------------------------------------------
/.storybook/Layout.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 |
3 | const Layout: React.FC = ({ children }) => {
4 | return
{children}
5 | }
6 |
7 | export default Layout
8 |
--------------------------------------------------------------------------------
/tailwind.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | future: {},
3 | purge: ['./src/**/*.tsx'],
4 | theme: {
5 | extend: {},
6 | },
7 | variants: {},
8 | plugins: [],
9 | }
10 |
--------------------------------------------------------------------------------
/.storybook/preview.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { addDecorator } from '@storybook/react'
3 | import Layout from './Layout'
4 |
5 | addDecorator(storyFn => {storyFn()})
6 |
--------------------------------------------------------------------------------
/src/assets/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | {
2 | "arrowParens": "avoid",
3 | "bracketSpacing": true,
4 | "jsxBracketSameLine": false,
5 | "jsxSingleQuote": false,
6 | "printWidth": 80,
7 | "semi": false,
8 | "singleQuote": true,
9 | "tabWidth": 2,
10 | "trailingComma": "es5",
11 | "useTabs": false
12 | }
13 |
--------------------------------------------------------------------------------
/src/stories/ReactLibraryStarter.stories.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { MyComponent } from '..'
3 |
4 | export default {
5 | title: 'React Library Starter',
6 | }
7 |
8 | export const Default: React.FC = () => {
9 | return (
10 |
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/postcss.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: [
3 | require('postcss-flexbugs-fixes'),
4 | require('postcss-preset-env')({
5 | autoprefixer: {
6 | flexbox: 'no-2009',
7 | },
8 | stage: 3,
9 | features: {
10 | 'custom-properties': false,
11 | },
12 | }),
13 | require('tailwindcss')('./tailwind.config.js'),
14 | require('cssnano'),
15 | ],
16 | }
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /dist
13 | /storybook-static
14 |
15 | # misc
16 | .DS_Store
17 | .env.local
18 | .env.development.local
19 | .env.test.local
20 | .env.production.local
21 |
22 | npm-debug.log*
23 | yarn-debug.log*
24 | yarn-error.log*
25 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "declaration": true,
4 | "declarationDir": "dist",
5 | "module": "esnext",
6 | "target": "es5",
7 | "lib": ["es6", "dom", "es2016", "es2017"],
8 | "sourceMap": true,
9 | "jsx": "react",
10 | "moduleResolution": "node",
11 | "allowSyntheticDefaultImports": true,
12 | "esModuleInterop": true
13 | },
14 | "include": ["./src/**/*"],
15 | "exclude": ["node_modules", "dist"]
16 | }
17 |
--------------------------------------------------------------------------------
/src/components/App.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { AppProps } from '../types'
3 | import { ReactComponent as Check } from '../assets/check.svg'
4 |
5 | const App: React.FC = ({ text, description }) => {
6 | return (
7 |
8 |
9 |
10 |
11 |
{text}
12 |
{description}
13 |
14 | )
15 | }
16 | export default App
17 |
--------------------------------------------------------------------------------
/src/typings.d.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * Default CSS definition for typescript,
3 | * will be overridden with file-specific definitions by rollup
4 | */
5 | declare module '*.css' {
6 | const content: { [className: string]: string }
7 | export default content
8 | }
9 |
10 | interface SvgrComponent extends React.FC> {}
11 |
12 | declare module '*.svg' {
13 | const svgUrl: string
14 | const svgComponent: SvgrComponent
15 | export default svgUrl
16 | export { svgComponent as ReactComponent }
17 | }
18 |
19 | // use this to provide proper keys to elements on an array
20 | // https://reactjs.org/docs/lists-and-keys.html#keys
21 | declare module 'react-uuid'
22 |
--------------------------------------------------------------------------------
/.storybook/main.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | stories: ['../src/**/*.stories.tsx'],
3 | webpackFinal: async config => {
4 | const assetRule = config.module.rules.find(({ test }) => test.test('.svg'))
5 |
6 | const assetLoader = {
7 | loader: assetRule.loader,
8 | options: assetRule.options || assetRule.query,
9 | }
10 | config.module.rules.push({
11 | test: /\.(ts|tsx)$/,
12 | use: [
13 | {
14 | loader: require.resolve('ts-loader'),
15 | },
16 | ],
17 | })
18 | config.module.rules.unshift({
19 | test: /\.svg$/,
20 | use: ['@svgr/webpack', assetLoader],
21 | })
22 | config.resolve.extensions.push('.ts', '.tsx')
23 | return config
24 | },
25 | }
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Rhaidzsal Ali
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import peerDepsExternal from 'rollup-plugin-peer-deps-external'
2 | import resolve from '@rollup/plugin-node-resolve'
3 | import commonjs from '@rollup/plugin-commonjs'
4 | import typescript from 'rollup-plugin-typescript2'
5 | import postcss from 'rollup-plugin-postcss'
6 | import svgr from '@svgr/rollup'
7 | import url from '@rollup/plugin-url'
8 | import analyze from 'rollup-plugin-analyzer'
9 |
10 | const packageJson = require('./package.json')
11 |
12 | export default {
13 | input: 'src/index.ts',
14 | output: [
15 | {
16 | exports: 'named',
17 | file: packageJson.main,
18 | format: 'cjs',
19 | sourcemap: true,
20 | },
21 | {
22 | exports: 'named',
23 | file: packageJson.module,
24 | format: 'esm',
25 | sourcemap: true,
26 | },
27 | {
28 | name: 'ReactLibraryStarter',
29 | file: packageJson.unpkg,
30 | format: 'umd',
31 | globals: {
32 | react: 'React',
33 | },
34 | },
35 | ],
36 | plugins: [
37 | peerDepsExternal(),
38 | postcss({
39 | minimize: true,
40 | modules: false,
41 | extract: true,
42 | config: {
43 | path: './postcss.config.js',
44 | ctx: null,
45 | },
46 | }),
47 | url(),
48 | svgr(),
49 | resolve(),
50 | commonjs(),
51 | typescript({ useTsconfigDeclarationDir: true }),
52 | analyze(),
53 | ],
54 | external: ['react'],
55 | }
56 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "@typescript-eslint/parser",
3 | "parserOptions": {
4 | "ecmaFeatures": {
5 | "jsx": true
6 | },
7 | "ecmaVersion": 11,
8 | "sourceType": "module"
9 | },
10 | "env": {
11 | "browser": true,
12 | "es6": true
13 | },
14 | "globals": {
15 | "Atomics": "readonly",
16 | "SharedArrayBuffer": "readonly"
17 | },
18 | "extends": [
19 | "plugin:react/recommended",
20 | "airbnb",
21 | "airbnb/hooks",
22 | "plugin:@typescript-eslint/recommended",
23 | "prettier",
24 | "prettier/react",
25 | "prettier/@typescript-eslint"
26 | ],
27 | "plugins": ["react", "import", "prettier", "@typescript-eslint"],
28 | "rules": {
29 | // prettier
30 | "prettier/prettier": ["error"],
31 | // TypeScript
32 | "@typescript-eslint/no-unused-vars": "error",
33 | "@typescript-eslint/no-empty-interface": [
34 | "error",
35 | {
36 | "allowSingleExtends": true
37 | }
38 | ],
39 | // React
40 | "react/prop-types": ["off", {}],
41 | "react/jsx-filename-extension": [
42 | 1,
43 | {
44 | "extensions": [".ts", ".tsx"]
45 | }
46 | ],
47 | "react/jsx-props-no-spreading": "off",
48 | "import/extensions": [
49 | "error",
50 | "ignorePackages",
51 | {
52 | "js": "never",
53 | "jsx": "never",
54 | "ts": "never",
55 | "tsx": "never"
56 | }
57 | ],
58 | "import/prefer-default-export": "off"
59 | },
60 | "settings": {
61 | "import/resolver": {
62 | "typescript": {} // this loads /tsconfig.json to eslint
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-library-starter
2 |
3 | ⚡ A library starter kit and bundler for your React projects, powered by Rollup.
4 |
5 | ## Features
6 |
7 | - React with TypeScript support
8 | - [Rollup](https://rollupjs.org/) for bundling (with a customizable bundler config file)
9 | - [Babel](https://babeljs.io/) for transpiling
10 | - [Storybook](https://storybook.js.org) for development and component explorer
11 | - [SVGR](https://react-svgr.com/) support
12 | - Uses [TailwindCSS 2.0](https://blog.tailwindcss.com/tailwindcss-v2)
13 | - Linting before commit support with [ESLint](https://eslint.org/), [Husky](https://github.com/typicode/husky) and [Lint Staged](https://github.com/okonet/lint-staged)
14 | - Supports CSS modules configurable with [PostCSS](https://postcss.org/)
15 | - [styled-components](https://styled-components.com/) support
16 | - [react-uuid](https://www.npmjs.com/package/react-uuid) for component key indexing
17 | - Supports CJS, ESM and UMD formats
18 | - Sourcemap creation
19 |
20 |
21 | ## Development
22 |
23 | Clone this repo and run the following commands to start development with Storybook.
24 |
25 | ```bash
26 | npm install --production=false
27 | npm run storybook
28 | ```
29 |
30 | Go to `localhost:6006` and you should see something like this.
31 |
32 | 
33 |
34 | ## Building
35 | To build your project, run `npm run build`.
36 |
37 | ## Publishing
38 | ```bash
39 | npm publish
40 | ```
41 | This builds `commonjs`, `esm`, and `umd` versions of your module to `dist/` and then publishes your module to `npm`.
42 | Make sure that any npm modules you want as peer dependencies are properly marked as `peerDependencies` in `package.json`. The rollup config will automatically recognize them as peers and not try to bundle them in your module.
43 |
44 | ## License
45 |
46 | MIT © [Rhaidzsal Ali](https://github.com/rhaicode)
47 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-library-starter",
3 | "version": "1.0.0",
4 | "description": "A bundler for your React projects, powered by Rollup.",
5 | "author": "rhaicode",
6 | "license": "MIT",
7 | "repository": "rhaicode/react-library-starter",
8 | "main": "dist/index.js",
9 | "module": "dist/index.modern.js",
10 | "unpkg": "dist/index.umd.js",
11 | "files": [
12 | "dist"
13 | ],
14 | "scripts": {
15 | "build": "cross-env NODE_ENV=production && rm -rf dist && rollup -c",
16 | "storybook": "start-storybook -p 6006",
17 | "build-storybook": "build-storybook"
18 | },
19 | "devDependencies": {
20 | "@babel/core": "^7.10.5",
21 | "@rollup/plugin-commonjs": "^14.0.0",
22 | "@rollup/plugin-node-resolve": "^8.4.0",
23 | "@rollup/plugin-url": "^6.0.0",
24 | "@storybook/addon-actions": "^6.1.10",
25 | "@storybook/addon-links": "^6.1.10",
26 | "@storybook/addons": "^6.1.10",
27 | "@storybook/react": "^6.1.10",
28 | "@svgr/rollup": "^5.5.0",
29 | "@svgr/webpack": "^5.5.0",
30 | "@types/react": "^16.9.27",
31 | "@types/react-dom": "^16.9.7",
32 | "@types/styled-components": "^5.1.4",
33 | "@typescript-eslint/eslint-plugin": "^3.7.1",
34 | "@typescript-eslint/parser": "^3.7.1",
35 | "autoprefixer": "^10.1.0",
36 | "babel-loader": "^8.1.0",
37 | "cross-env": "^7.0.3",
38 | "cssnano": "^4.1.10",
39 | "eslint": "^7.6.0",
40 | "eslint-config-airbnb": "^18.2.0",
41 | "eslint-config-prettier": "^6.11.0",
42 | "eslint-import-resolver-typescript": "^2.2.0",
43 | "eslint-plugin-import": "^2.22.0",
44 | "eslint-plugin-jsx-a11y": "^6.3.1",
45 | "eslint-plugin-prettier": "^3.1.4",
46 | "eslint-plugin-react": "^7.20.5",
47 | "eslint-plugin-react-hooks": "^4.0.8",
48 | "husky": "^4.2.5",
49 | "lint-staged": "^10.2.11",
50 | "postcss": "^8.2.0",
51 | "postcss-flexbugs-fixes": "^4.2.1",
52 | "postcss-modules": "^4.0.0",
53 | "postcss-preset-env": "^6.7.0",
54 | "prettier": "^2.0.5",
55 | "react": "^16.13.1",
56 | "react-dom": "^16.13.1",
57 | "rollup": "^2.23.0",
58 | "rollup-plugin-analyzer": "^3.3.0",
59 | "rollup-plugin-peer-deps-external": "^2.2.3",
60 | "rollup-plugin-postcss": "^4.0.0",
61 | "rollup-plugin-typescript2": "^0.27.1",
62 | "ts-loader": "^8.0.1",
63 | "typescript": "^3.9.7"
64 | },
65 | "peerDependencies": {
66 | "react": ">=16.8.0",
67 | "react-dom": ">=16.8.0",
68 | "tailwindcss": ">=2.0.1"
69 | },
70 | "dependencies": {
71 | "@use-it/event-listener": "^0.1.6",
72 | "casual-browserify": "^1.5.19-2",
73 | "clsx": "^1.1.1",
74 | "react-uuid": "^1.0.2",
75 | "styled-components": "^5.2.1",
76 | "tailwindcss": "^2.0.1"
77 | }
78 | }
79 |
--------------------------------------------------------------------------------