├── .gitignore
├── LICENSE
├── README.md
├── example
├── .npmignore
├── index.html
├── index.tsx
├── package.json
└── tsconfig.json
├── package-lock.json
├── package.json
├── src
└── index.tsx
├── test
├── __snapshots__
│ └── render.test.tsx.snap
├── render.test.tsx
└── utils
│ └── test-components.tsx
└── tsconfig.json
/.gitignore:
--------------------------------------------------------------------------------
1 | *.log
2 | .DS_Store
3 | node_modules
4 | .cache
5 | .rts2_cache_cjs
6 | .rts2_cache_esm
7 | .rts2_cache_umd
8 | .rts2_cache_system
9 | dist
10 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Horus Lugo
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.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Component Pack · [](https://www.npmjs.com/package/react-component-pack) [](./LICENSE)
2 |
3 | Say goodbye to provider hell with react-component-pack, a utility that allows you to group multiple components into a single one
4 |
5 | ```bash
6 | npm install react-component-pack
7 | ```
8 |
9 | ## Usage
10 |
11 | With `react-component-pack` you can go from this:
12 |
13 | ```jsx
14 | function App() {
15 | return (
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | }
31 | ```
32 |
33 | To this:
34 |
35 | ```jsx
36 | import { createPack } from 'react-component-pack';
37 |
38 | const ProviderPack = createPack(
39 | AuthProvider,
40 | DataProvider,
41 | AnotherDataProvider,
42 | WtfProvider,
43 | ThisIsGettingReallyBigProvider,
44 | OhMyGodTheresMoreProvider
45 | );
46 |
47 | function App() {
48 | return (
49 |
50 |
51 |
52 | );
53 | }
54 | ```
55 |
--------------------------------------------------------------------------------
/example/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache
3 | dist
--------------------------------------------------------------------------------
/example/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Playground
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/example/index.tsx:
--------------------------------------------------------------------------------
1 | import 'react-app-polyfill/ie11';
2 | import * as React from 'react';
3 | import * as ReactDOM from 'react-dom';
4 | import { createPack } from '../.';
5 |
6 | const ExamplePack = createPack(
7 | "div",
8 | "h1"
9 | )
10 |
11 | const App = () => {
12 | return (
13 |
14 |
15 | Div and H1 packed!
16 |
17 |
18 | );
19 | };
20 |
21 | ReactDOM.render(, document.getElementById('root'));
22 |
--------------------------------------------------------------------------------
/example/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "example",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "license": "MIT",
6 | "scripts": {
7 | "start": "parcel index.html",
8 | "build": "parcel build index.html"
9 | },
10 | "dependencies": {
11 | "react-app-polyfill": "^1.0.0"
12 | },
13 | "alias": {
14 | "react": "../node_modules/react",
15 | "react-dom": "../node_modules/react-dom/profiling",
16 | "scheduler/tracing": "../node_modules/scheduler/tracing-profiling"
17 | },
18 | "devDependencies": {
19 | "@types/react": "^16.9.11",
20 | "@types/react-dom": "^16.8.4",
21 | "parcel": "^1.12.3",
22 | "typescript": "^3.4.5"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/example/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "allowSyntheticDefaultImports": false,
4 | "target": "es5",
5 | "module": "commonjs",
6 | "jsx": "react",
7 | "moduleResolution": "node",
8 | "noImplicitAny": false,
9 | "noUnusedLocals": false,
10 | "noUnusedParameters": false,
11 | "removeComments": true,
12 | "strictNullChecks": true,
13 | "preserveConstEnums": true,
14 | "sourceMap": true,
15 | "lib": ["es2015", "es2016", "dom"],
16 | "baseUrl": ".",
17 | "types": ["node"]
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-component-pack",
3 | "version": "1.0.1",
4 | "license": "MIT",
5 | "author": "Horus Lugo ",
6 | "description": "Say goodbye to provider hell with react-component-pack, a utility that allows you to group multiple components into a single one",
7 | "keywords": [
8 | "react",
9 | "pack",
10 | "context hell",
11 | "component pack",
12 | "tree",
13 | "provider hell"
14 | ],
15 | "homepage": "https://github.com/HorusGoul/react-component-pack#readme",
16 | "repository": {
17 | "type": "git",
18 | "url": "https://github.com/HorusGoul/react-component-pack.git"
19 | },
20 | "bugs": {
21 | "url": "https://github.com/HorusGoul/react-component-pack/issues"
22 | },
23 | "main": "dist/index.js",
24 | "module": "dist/react-component-pack.esm.js",
25 | "typings": "dist/index.d.ts",
26 | "files": [
27 | "dist"
28 | ],
29 | "scripts": {
30 | "start": "tsdx watch",
31 | "build": "tsdx build",
32 | "test": "tsdx test --env=jsdom",
33 | "lint": "tsdx lint",
34 | "release": "npm run test && npm run build && npm publish"
35 | },
36 | "peerDependencies": {
37 | "react": ">=16"
38 | },
39 | "husky": {
40 | "hooks": {
41 | "pre-commit": "tsdx lint"
42 | }
43 | },
44 | "prettier": {
45 | "printWidth": 80,
46 | "semi": true,
47 | "singleQuote": true,
48 | "trailingComma": "es5"
49 | },
50 | "devDependencies": {
51 | "@types/jest": "^24.0.23",
52 | "@types/react": "^16.9.11",
53 | "@types/react-dom": "^16.9.4",
54 | "@types/react-test-renderer": "^16.9.1",
55 | "husky": "^3.0.9",
56 | "react": "^16.12.0",
57 | "react-dom": "^16.12.0",
58 | "react-test-renderer": "^16.12.0",
59 | "tsdx": "^0.11.0",
60 | "tslib": "^1.10.0",
61 | "typescript": "^3.7.2"
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export interface WithChildrenProps {
4 | children: React.ReactNode;
5 | }
6 |
7 | export type PackComponentType<
8 | T extends WithChildrenProps = WithChildrenProps
9 | > = React.ElementType;
10 |
11 | export function pack(
12 | children: React.ReactNode = null,
13 | ...components: PackComponentType[]
14 | ) {
15 | if (!components.length) {
16 | return children as JSX.Element;
17 | }
18 |
19 | const [Component, ...rest] = components;
20 |
21 | return {pack(children, ...rest)};
22 | }
23 |
24 | export function createPack(...components: PackComponentType[]) {
25 | return function PackComponent({ children }: WithChildrenProps) {
26 | return pack(children, ...components);
27 | };
28 | }
29 |
--------------------------------------------------------------------------------
/test/__snapshots__/render.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Jest Snapshot v1, https://goo.gl/fbAQLP
2 |
3 | exports[`it renders without crashing a pack of one component 1`] = `
4 |
5 | Test
6 |
7 | `;
8 |
9 | exports[`it renders without crashing a pack of three components 1`] = `
10 |
17 | `;
18 |
--------------------------------------------------------------------------------
/test/render.test.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import { createPack } from '../src';
3 | import { WithChildrenComponent } from './utils/test-components';
4 | import * as renderer from 'react-test-renderer';
5 |
6 | describe('it', () => {
7 | it('renders without crashing a pack of one component', () => {
8 | const Pack = createPack(WithChildrenComponent);
9 |
10 | const tree = renderer.create(Test).toJSON();
11 |
12 | expect(tree).toMatchSnapshot();
13 | });
14 |
15 | it('renders without crashing a pack of three components', () => {
16 | const Pack = createPack(
17 | WithChildrenComponent,
18 | WithChildrenComponent,
19 | WithChildrenComponent
20 | );
21 |
22 | const tree = renderer.create(Test).toJSON();
23 |
24 | expect(tree).toMatchSnapshot();
25 | });
26 | });
27 |
--------------------------------------------------------------------------------
/test/utils/test-components.tsx:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 |
3 | export function WithChildrenComponent({
4 | children,
5 | }: {
6 | children: React.ReactNode;
7 | }) {
8 | return {children}
;
9 | }
10 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "include": ["src", "types", "test"],
3 | "compilerOptions": {
4 | "target": "es5",
5 | "module": "esnext",
6 | "lib": ["dom", "esnext"],
7 | "importHelpers": true,
8 | "declaration": true,
9 | "sourceMap": true,
10 | "rootDir": "./",
11 | "strict": true,
12 | "noImplicitAny": true,
13 | "strictNullChecks": true,
14 | "strictFunctionTypes": true,
15 | "strictPropertyInitialization": true,
16 | "noImplicitThis": true,
17 | "alwaysStrict": true,
18 | "noUnusedLocals": true,
19 | "noUnusedParameters": true,
20 | "noImplicitReturns": true,
21 | "noFallthroughCasesInSwitch": true,
22 | "moduleResolution": "node",
23 | "baseUrl": "./",
24 | "paths": {
25 | "*": ["src/*", "node_modules/*"]
26 | },
27 | "jsx": "react",
28 | "esModuleInterop": true
29 | }
30 | }
31 |
--------------------------------------------------------------------------------