The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .codeclimate.yml
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .flowconfig
├── .gitignore
├── .npmignore
├── .prettierignore
├── .prettierrc
├── .size-snapshot.json
├── .travis.yml
├── CHANGELOG.md
├── LICENSE.md
├── README.md
├── babel.config.js
├── docs
    ├── API.md
    ├── flow.md
    └── performance.md
├── package.json
├── scripts
    ├── getPackageNames.js
    ├── installNestedPackageDeps.js
    ├── jest.setup.js
    ├── release.js
    └── rollup.config.js
├── src
    ├── basePackage.json
    └── packages
    │   ├── recompose-relay
    │       ├── .npmignore
    │       ├── README.md
    │       ├── VERSION
    │       ├── createContainer.js
    │       ├── index.js
    │       ├── package.json
    │       └── yarn.lock
    │   ├── recompose
    │       ├── .npmignore
    │       ├── README.md
    │       ├── VERSION
    │       ├── __tests__
    │       │   ├── branch-test.js
    │       │   ├── componentFromProp-test.js
    │       │   ├── componentFromStream-test.js
    │       │   ├── componentFromStreamWithConfig-test.js
    │       │   ├── compose-test.js
    │       │   ├── createEventHandler-test.js
    │       │   ├── createSink-test.js
    │       │   ├── defaultProps-test.js
    │       │   ├── fixtures
    │       │   │   └── treeshake-entry.js
    │       │   ├── flattenProp-test.js
    │       │   ├── fromRenderProps-test.js
    │       │   ├── getContext-test.js
    │       │   ├── getDisplayName-test.js
    │       │   ├── hoistStatics-test.js
    │       │   ├── isClassComponent-test.js
    │       │   ├── lifecycle-test.js
    │       │   ├── mapProps-test.js
    │       │   ├── mapPropsStream-test.js
    │       │   ├── mapPropsStreamWithConfig-test.js
    │       │   ├── nest-test.js
    │       │   ├── onlyUpdateForKeys-test.js
    │       │   ├── onlyUpdateForPropTypes-test.js
    │       │   ├── pure-test.js
    │       │   ├── renameProp-test.js
    │       │   ├── renameProps-test.js
    │       │   ├── renderComponent-test.js
    │       │   ├── renderNothing-test.js
    │       │   ├── setDisplayName-test.js
    │       │   ├── setObservableConfig-test.js
    │       │   ├── setPropTypes-test.js
    │       │   ├── setStatic-test.js
    │       │   ├── shallowEqual-test.js
    │       │   ├── shouldUpdate-test.js
    │       │   ├── toClass-test.js
    │       │   ├── toRenderProps-test.js
    │       │   ├── types
    │       │   │   ├── test_branch.js
    │       │   │   ├── test_classBasedEnhancer.js
    │       │   │   ├── test_componentFromStream.js
    │       │   │   ├── test_createEventHandler.js
    │       │   │   ├── test_defaultProps.js
    │       │   │   ├── test_fromRenderProps.js
    │       │   │   ├── test_functionalEnhancer.js
    │       │   │   ├── test_getContext.js
    │       │   │   ├── test_mapProps.js
    │       │   │   ├── test_mapPropsStream.js
    │       │   │   ├── test_onlyUpdateForKeys.js
    │       │   │   ├── test_onlyUpdateForPropTypes.js
    │       │   │   ├── test_pure.js
    │       │   │   ├── test_shouldUpdate.js
    │       │   │   ├── test_statics.js
    │       │   │   ├── test_toClass.js
    │       │   │   ├── test_toRenderProps.js
    │       │   │   ├── test_utils.js
    │       │   │   ├── test_voodoo.js
    │       │   │   ├── test_withContext.js
    │       │   │   ├── test_withHandlers.js
    │       │   │   ├── test_withProps.js
    │       │   │   ├── test_withPropsOnChange.js
    │       │   │   └── test_withStateHandlers.js
    │       │   ├── utils.js
    │       │   ├── withContext-test.js
    │       │   ├── withHandlers-test.js
    │       │   ├── withProps-test.js
    │       │   ├── withPropsOnChange-test.js
    │       │   ├── withReducer-test.js
    │       │   ├── withState-test.js
    │       │   ├── withStateHandlers-test.js
    │       │   └── wrapDisplayName-test.js
    │       ├── baconObservableConfig.js
    │       ├── branch.js
    │       ├── componentFromProp.js
    │       ├── componentFromStream.js
    │       ├── compose.js
    │       ├── createEventHandler.js
    │       ├── createSink.js
    │       ├── defaultProps.js
    │       ├── flattenProp.js
    │       ├── flydObservableConfig.js
    │       ├── fromRenderProps.js
    │       ├── getContext.js
    │       ├── getDisplayName.js
    │       ├── hoistStatics.js
    │       ├── index.js
    │       ├── index.js.flow
    │       ├── isClassComponent.js
    │       ├── kefirObservableConfig.js
    │       ├── lifecycle.js
    │       ├── mapProps.js
    │       ├── mapPropsStream.js
    │       ├── mostObservableConfig.js
    │       ├── nest.js
    │       ├── onlyUpdateForKeys.js
    │       ├── onlyUpdateForPropTypes.js
    │       ├── package.json
    │       ├── pure.js
    │       ├── renameProp.js
    │       ├── renameProps.js
    │       ├── renderComponent.js
    │       ├── renderNothing.js
    │       ├── rxjs4ObservableConfig.js
    │       ├── rxjsObservableConfig.js
    │       ├── setDisplayName.js
    │       ├── setObservableConfig.js
    │       ├── setPropTypes.js
    │       ├── setStatic.js
    │       ├── shallowEqual.js
    │       ├── shouldUpdate.js
    │       ├── toClass.js
    │       ├── toRenderProps.js
    │       ├── utils
    │       │   ├── mapValues.js
    │       │   ├── omit.js
    │       │   └── pick.js
    │       ├── withContext.js
    │       ├── withHandlers.js
    │       ├── withProps.js
    │       ├── withPropsOnChange.js
    │       ├── withReducer.js
    │       ├── withState.js
    │       ├── withStateHandlers.js
    │       ├── wrapDisplayName.js
    │       ├── xstreamObservableConfig.js
    │       └── yarn.lock
    │   └── rx-recompose
    │       └── yarn.lock
├── types
    ├── README.md
    └── flow-example
    │   ├── .eslintrc
    │   ├── .flowconfig
    │   ├── .gitignore
    │   ├── README.md
    │   ├── flow-typed
    │       ├── glamor.js
    │       └── react-motion.js
    │   ├── package.json
    │   ├── public
    │       ├── favicon.ico
    │       ├── index.html
    │       └── manifest.json
    │   ├── src
    │       ├── App.js
    │       ├── Item.js
    │       ├── ItemsAnimator.js
    │       ├── MouseDetector.js
    │       └── index.js
    │   └── yarn.lock
└── yarn.lock


/.codeclimate.yml:
--------------------------------------------------------------------------------
 1 | ---
 2 | engines:
 3 |   duplication:
 4 |     enabled: true
 5 |     config:
 6 |       languages:
 7 |       - javascript
 8 |   eslint:
 9 |     enabled: true
10 |   fixme:
11 |     enabled: true
12 | ratings:
13 |   paths:
14 |   - "**.js"
15 | exclude_paths:
16 |   - "**/*-test.js"
17 | 


--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
 1 | # editorconfig.org
 2 | root = true
 3 | 
 4 | [*]
 5 | indent_style = space
 6 | indent_size = 2
 7 | end_of_line = lf
 8 | charset = utf-8
 9 | trim_trailing_whitespace = true
10 | insert_final_newline = true
11 | 
12 | [*.md]
13 | trim_trailing_whitespace = false
14 | 
15 | [Makefile]
16 | indent_style = tab
17 | 


--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | **/node_modules
2 | **/types


--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
 1 | {
 2 |   "extends": [
 3 |     "eslint-config-airbnb",
 4 |     "prettier",
 5 |     "prettier/flowtype",
 6 |     "prettier/react"
 7 |   ],
 8 |   "plugins": [
 9 |     "prettier"
10 |   ],
11 |   "parser": "babel-eslint",
12 |   "env": {
13 |     "browser": true,
14 |     "node": true,
15 |     "jest": true
16 |   },
17 |   "globals": {
18 |     "sinon": true
19 |   },
20 |   "rules": {
21 |     "semi": [2, "never"],
22 |     "no-use-before-define": ["error", { "functions": false }],
23 |     "no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
24 |     "no-underscore-dangle": [0],
25 |     "no-confusing-arrow": [0],
26 |     "no-class-assign": [0],
27 |     "no-plusplus": [0],
28 |     "no-prototype-builtins": [0],
29 |     "no-return-assign": [0],
30 |     "max-len": ["error", { "code": 120, "ignorePattern": "^test", "ignoreUrls": true }],
31 |     "lines-between-class-members": [0],
32 |     "prefer-destructuring": [0],
33 |     "import/no-unresolved": [0],
34 |     "import/no-extraneous-dependencies": [0],
35 |     "import/extensions": [0],
36 |     "import/prefer-default-export": [0],
37 |     "import/no-useless-path-segments": [0],
38 |     "jsx-a11y/label-has-for": [0],
39 |     "react/forbid-prop-types": [0],
40 |     "react/prop-types": [0],
41 |     "react/prefer-stateless-function": [0],
42 |     "react/no-multi-comp": [0],
43 |     "react/sort-comp": [0],
44 |     "react/jsx-filename-extension": [0],
45 |     "prettier/prettier": ["error", {"semi": false, "trailingComma": "es5", "singleQuote": true}],
46 |     "react/destructuring-assignment": [0],
47 |     "react/jsx-curly-brace-presence": [0],
48 |     "react/no-unused-prop-types": [0],
49 |     "react/require-default-props": [0],
50 |     "react/button-has-type": [0]
51 |   }
52 | }
53 | 


--------------------------------------------------------------------------------
/.flowconfig:
--------------------------------------------------------------------------------
 1 | [ignore]
 2 | <PROJECT_ROOT>/types/.*
 3 | 
 4 | [include]
 5 | 
 6 | [libs]
 7 | 
 8 | [options]
 9 | suppress_comment=\\(.\\|\n\\)*\\$ExpectError
10 | 
11 | [lints]


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | release
3 | lib
4 | coverage
5 | .vscode
6 | yarn-error.log
7 | 


--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | /**/__tests__
2 | coverage
3 | types


--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | package.json


--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
1 | semi: false
2 | singleQuote: true
3 | trailingComma: es5


--------------------------------------------------------------------------------
/.size-snapshot.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "lib/packages/recompose/dist/Recompose.umd.js": {
 3 |     "bundled": 46425,
 4 |     "minified": 16484,
 5 |     "gzipped": 4625
 6 |   },
 7 |   "lib/packages/recompose/dist/Recompose.min.js": {
 8 |     "bundled": 42863,
 9 |     "minified": 15204,
10 |     "gzipped": 4194
11 |   },
12 |   "lib/packages/recompose/dist/Recompose.esm.js": {
13 |     "bundled": 32428,
14 |     "minified": 15083,
15 |     "gzipped": 3550,
16 |     "treeshaked": {
17 |       "rollup": {
18 |         "code": 310,
19 |         "import_statements": 310
20 |       },
21 |       "webpack": {
22 |         "code": 1838
23 |       }
24 |     }
25 |   }
26 | }
27 | 


--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
 1 | language: node_js
 2 | node_js:
 3 |   - "node"
 4 | install: "yarn install --ignore-engines"
 5 | before_script: "npm install -g codeclimate-test-reporter"
 6 | script:
 7 |   - yarn run lint
 8 |   - yarn test
 9 | after_script:
10 |   - "CODECLIMATE_REPO_TOKEN=27125df6192d300baf67cd5f5eab6597c998256f4883b744a1055d0f0c18e608 codeclimate-test-reporter < coverage/lcov.info"
11 |   - "cat ./coverage/lcov.info | $(npm bin)/codecov"
12 | 


--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | We are using the [Github Releases page](https://github.com/acdlite/recompose/releases) as our CHANGELOG.
2 | 


--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
 1 | The MIT License (MIT)
 2 | 
 3 | Copyright (c) 2015-2018 Andrew Clark
 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 | 


--------------------------------------------------------------------------------
/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 |   plugins: [['@babel/proposal-class-properties', { loose: true }]],
3 |   presets: [['@babel/env', { loose: true }], '@babel/react'],
4 | }
5 | 
6 | if (process.env.NODE_ENV === 'cjs') {
7 |   module.exports.plugins.push('@babel/transform-runtime')
8 | }
9 | 


--------------------------------------------------------------------------------
/docs/flow.md:
--------------------------------------------------------------------------------
 1 | # Flow support for recompose
 2 | 
 3 | ## How it works
 4 | 
 5 | In most cases all you need is to declare a props type of enhanced Component.
 6 | Flow will infer all other types you need.
 7 | 
 8 | Example:
 9 | 
10 | ```javascript
11 | import type { HOC } from 'recompose';
12 | 
13 | type EnhancedComponentProps = {
14 |   text?: string,
15 | };
16 | 
17 | const baseComponent = ({ text }) => <div>{text}</div>;
18 | 
19 | const enhance:HOC<*, EnhancedComponentProps> = compose(
20 |   defaultProps({
21 |     text: 'world',
22 |   }),
23 |   withProps(({ text }) => ({
24 |     text: `Hello ${text}`
25 |   }))
26 | );
27 | 
28 | export default enhance(baseComponent);
29 | 
30 | ```
31 | 
32 | See it in action.
33 | 
34 | ![recompose-flow](https://user-images.githubusercontent.com/5077042/28116959-0c96ae2c-6714-11e7-930e-b1454c629908.gif)
35 | 
36 | ## How to start
37 | 
38 | The easiest way is to start from example.
39 | 
40 | Look at [this](http://grader-meets-16837.netlify.com/) app [source](../types/flow-example)
41 | 
42 | 
43 | ## Support
44 | 
45 | Type definitions of recompose HOCs are splitted into 2 parts.
46 | 
47 | ### Part 1 - HOCs with good flow support
48 | 
49 | In most cases you can use them without big issues.
50 | Type inference and errors detection works near well.
51 | 
52 | These HOCs are: *defaultProps, mapProps, withProps, withStateHandlers, withHandlers, pure, onlyUpdateForKeys, shouldUpdate, renderNothing, renderComponent, branch, withPropsOnChange, onlyUpdateForPropTypes, toClass, withContext, getContext, setStatic, setPropTypes, setDisplayName*
53 | 
54 | #### Known issues for "good" HOCs
55 | 
56 | see `test_mapProps.js` - inference work but type errors are not detected in hocs
57 | 
58 | ### Part 2 - other HOCs
59 | 
60 | To use these HOCs - you need to provide type information (no automatic type inference).
61 | You must be a good voodoo dancer.
62 | 
63 | See `test_voodoo.js` for the idea.
64 | 
65 | Some recomendations:
66 | 
67 | - *flattenProp,renameProp, renameProps* can easily be replaced with _withProps_
68 | - *withReducer, withState* -> use _withStateHandlers_ instead
69 | - _lifecycle_ -> you don't need recompose if you need a _lifecycle_, just use React class instead
70 | - _mapPropsStream_ -> see `test_mapPropsStream.js`
71 | 
72 | #### Known issues for above HOCs
73 | 
74 | See `test_voodoo.js`, `test_mapPropsStream.js`
75 | 
76 | ### Utils
77 | 
78 | *getDisplayName, wrapDisplayName, shallowEqual,isClassComponent, createSink, componentFromProp, nest, hoistStatics.*
79 | 
80 | ### Articles
81 | 
82 | [Typing Higher-order Components in Recompose With Flow](https://medium.com/flow-type/flow-support-in-recompose-1b76f58f4cfc)
83 | 
84 | ### Faq
85 | 
86 | Why to use existential type with `HOC<*, Blbla>` isn't it possible to avoid this?
87 | 
88 | *I tried to use type alias but haven't found how to make it work.*
89 | 
90 | ## Thanks
91 | 
92 | Big thanks to [@gcanti](https://github.com/gcanti) for his work on PR [#241](https://github.com/acdlite/recompose/pull/241), it was nice and clear base for current definitions.
93 | 


--------------------------------------------------------------------------------
/docs/performance.md:
--------------------------------------------------------------------------------
1 | # Should I use this? Performance and other concerns
2 | 
3 | If function composition doesn't scare you, then yes, I think so. I believe using higher-order component helpers leads to smaller, more focused components, and provides a better programming model than using classes for operations—like `mapProps()` or `shouldUpdate()`—that aren't inherently class-y.
4 | 
5 | That being said, any abstraction over an existing API is going to come with trade-offs. There is a performance overhead when introducing a new component to the tree. I suspect this cost is negligible compared to the gains achieved by blocking subtrees from re-rendering using `shouldComponentUpdate()`—which Recompose makes easy with its `shouldUpdate()` and `onlyUpdateForKeys()` helpers. In the future, I'll work on some benchmarks so we know what we're dealing with.
6 | 
7 | However, many of Recompose's higher-order component helpers are implemented using stateless function components rather than class components. Eventually, React will include optimizations for stateless components.
8 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "recompose-build",
 3 |   "private": true,
 4 |   "author": "Andrew Clark <acdlite@me.com>",
 5 |   "repository": {
 6 |     "type": "git",
 7 |     "url": "git://github.com/acdlite/recompose.git"
 8 |   },
 9 |   "license": "MIT",
10 |   "scripts": {
11 |     "lint": "eslint scripts src",
12 |     "build:recompose": "cross-env PACKAGE_NAME=recompose rollup --config scripts/rollup.config.js",
13 |     "test": "jest && flow check && cross-env SNAPSHOT=match npm run build:recompose",
14 |     "test:watch": "cross-env BABEL_ENV=cjs jest --watch",
15 |     "release": "node scripts/release.js",
16 |     "postinstall": "node scripts/installNestedPackageDeps.js",
17 |     "format": "prettier --semi false --trailing-comma es5 --single-quote --write 'scripts/*.js' 'src/packages/*/*.js' 'src/packages/*/!(node_modules)/**/*.js'",
18 |     "precommit": "lint-staged",
19 |     "prepush": "yarn test"
20 |   },
21 |   "jest": {
22 |     "testMatch": [
23 |       "<rootDir>/src/**/__tests__/**/*-test.js"
24 |     ],
25 |     "coverageReporters": [
26 |       "text-summary",
27 |       "lcov"
28 |     ],
29 |     "setupTestFrameworkScriptFile": "<rootDir>/scripts/jest.setup.js"
30 |   },
31 |   "lint-staged": {
32 |     "*.js": [
33 |       "prettier --semi false --trailing-comma es5 --single-quote --write",
34 |       "eslint --fix",
35 |       "git add"
36 |     ]
37 |   },
38 |   "devDependencies": {
39 |     "@babel/cli": "^7.0.0",
40 |     "@babel/core": "^7.0.0",
41 |     "@babel/plugin-proposal-class-properties": "^7.0.0",
42 |     "@babel/plugin-transform-runtime": "^7.0.0",
43 |     "@babel/preset-env": "^7.0.0",
44 |     "@babel/preset-react": "^7.0.0",
45 |     "@babel/runtime": "^7.0.0",
46 |     "babel-core": "^7.0.0-bridge.0",
47 |     "babel-eslint": "^9.0.0",
48 |     "babel-jest": "^22.4.3",
49 |     "baconjs": "^0.7.84",
50 |     "chalk": "^1.1.1",
51 |     "change-case": "^2.3.1",
52 |     "codecov": "^1.0.1",
53 |     "create-react-class": "^15.5.0",
54 |     "cross-env": "^4.0.0",
55 |     "enzyme": "^3.3.0",
56 |     "eslint": "^5.3.0",
57 |     "eslint-config-airbnb": "^17.0.0",
58 |     "eslint-config-prettier": "^2.9.0",
59 |     "eslint-plugin-import": "^2.13.0",
60 |     "eslint-plugin-jsx-a11y": "^6.1.1",
61 |     "eslint-plugin-prettier": "^2.0.1",
62 |     "eslint-plugin-react": "^7.10.0",
63 |     "flow-bin": "^0.72.0",
64 |     "flyd": "^0.2.4",
65 |     "husky": "^0.13.3",
66 |     "jest": "^22.4.3",
67 |     "kefir": "^3.2.3",
68 |     "lint-staged": "^3.4.0",
69 |     "most": "^1.0.2",
70 |     "prettier": "^1.2.2",
71 |     "prop-types": "^15.6.1",
72 |     "react": "^16.3.1",
73 |     "react-dom": "^16.3.1",
74 |     "readline-sync": "^1.2.21",
75 |     "rollup": "^0.65.0",
76 |     "rollup-plugin-babel": "^4.0.1",
77 |     "rollup-plugin-commonjs": "^9.1.6",
78 |     "rollup-plugin-node-resolve": "^3.3.0",
79 |     "rollup-plugin-replace": "^2.0.0",
80 |     "rollup-plugin-size-snapshot": "^0.6.1",
81 |     "rollup-plugin-uglify": "^4.0.0",
82 |     "rx": "^4.1.0",
83 |     "rxjs": "^5.0.0",
84 |     "shelljs": "^0.6.0",
85 |     "sinon": "^1.17.1",
86 |     "webpack": "^2.4.1",
87 |     "xstream": "^5.0.5"
88 |   },
89 |   "devEngines": {
90 |     "node": "5.x",
91 |     "npm": "3.x"
92 |   },
93 |   "dependencies": {
94 |     "enzyme-adapter-react-16": "^1.1.1"
95 |   }
96 | }
97 | 


--------------------------------------------------------------------------------
/scripts/getPackageNames.js:
--------------------------------------------------------------------------------
 1 | const fs = require('fs')
 2 | const path = require('path')
 3 | 
 4 | exports.PACKAGES_SRC_DIR = './src/packages'
 5 | exports.PACKAGES_OUT_DIR = './lib/packages'
 6 | 
 7 | let names
 8 | 
 9 | exports.getPackageNames = () => {
10 |   if (!names) {
11 |     names = fs.readdirSync(exports.PACKAGES_SRC_DIR).filter(file => {
12 |       try {
13 |         const packageJsonPath = path.resolve(
14 |           exports.PACKAGES_SRC_DIR,
15 |           file,
16 |           'package.json'
17 |         )
18 |         return fs.statSync(packageJsonPath).isFile()
19 |       } catch (error) {
20 |         return false
21 |       }
22 |     })
23 |   }
24 |   return names
25 | }
26 | 


--------------------------------------------------------------------------------
/scripts/installNestedPackageDeps.js:
--------------------------------------------------------------------------------
 1 | const path = require('path')
 2 | const { exec } = require('shelljs')
 3 | const { getPackageNames, PACKAGES_SRC_DIR } = require('./getPackageNames.js')
 4 | 
 5 | const packageNames = getPackageNames()
 6 | 
 7 | packageNames.forEach(packageName => {
 8 |   const sourceDir = path.resolve(PACKAGES_SRC_DIR, packageName)
 9 |   exec(`cd ${sourceDir} && yarn`, { async: true })
10 | })
11 | 


--------------------------------------------------------------------------------
/scripts/jest.setup.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000
3 | 
4 | import Enzyme from 'enzyme'
5 | import Adapter from 'enzyme-adapter-react-16'
6 | 
7 | Enzyme.configure({ adapter: new Adapter() })
8 | 


--------------------------------------------------------------------------------
/scripts/release.js:
--------------------------------------------------------------------------------
  1 | /* eslint global-require: 0 */
  2 | /* eslint-disable import/no-dynamic-require, no-console */
  3 | const fs = require('fs')
  4 | const path = require('path')
  5 | const { exec, exit, rm, cp, test } = require('shelljs')
  6 | const chalk = require('chalk')
  7 | const { flowRight: compose } = require('lodash')
  8 | const readline = require('readline-sync')
  9 | const semver = require('semver')
 10 | const { pascalCase } = require('change-case')
 11 | 
 12 | const BIN = './node_modules/.bin'
 13 | 
 14 | const {
 15 |   PACKAGES_SRC_DIR,
 16 |   PACKAGES_OUT_DIR,
 17 |   getPackageNames,
 18 | } = require('./getPackageNames')
 19 | 
 20 | const BASE_PACKAGE_LOC = '../src/basePackage.json'
 21 | 
 22 | const consoleLog = console.log.bind(console)
 23 | const log = compose(consoleLog, chalk.bold)
 24 | const logSuccess = compose(consoleLog, chalk.green.bold)
 25 | const logError = compose(consoleLog, chalk.red.bold)
 26 | 
 27 | const writeFile = (filepath, string) =>
 28 |   fs.writeFileSync(filepath, string, 'utf8')
 29 | 
 30 | try {
 31 |   if (exec('git diff-files --quiet').code !== 0) {
 32 |     logError(
 33 |       'You have unsaved changes in the working tree. ' +
 34 |         'Commit or stash changes before releasing.'
 35 |     )
 36 |     exit(1)
 37 |   }
 38 | 
 39 |   const packageNames = getPackageNames()
 40 | 
 41 |   let packageName = readline.question('Name of package to release: ')
 42 | 
 43 |   while (!packageNames.includes(packageName)) {
 44 |     packageName = readline.question(
 45 |       `The package "${packageName}" does not exist in this project. ` +
 46 |         'Choose again: '
 47 |     )
 48 |   }
 49 | 
 50 |   const libraryName = pascalCase(packageName)
 51 | 
 52 |   const versionLoc = path.resolve(PACKAGES_SRC_DIR, packageName, 'VERSION')
 53 |   const version = fs.readFileSync(versionLoc, 'utf8').trim()
 54 | 
 55 |   let nextVersion = readline.question(
 56 |     `Next version of ${packageName} (current version is ${version}): `
 57 |   )
 58 | 
 59 |   while (
 60 |     !(
 61 |       !nextVersion ||
 62 |       (semver.valid(nextVersion) && semver.gt(nextVersion, version))
 63 |     )
 64 |   ) {
 65 |     nextVersion = readline.question(
 66 |       `Must provide a valid version that is greater than ${version}, ` +
 67 |         'or leave blank to skip: '
 68 |     )
 69 |   }
 70 | 
 71 |   log('Running tests...')
 72 | 
 73 |   if (exec('yarn run lint && yarn test').code !== 0) {
 74 |     logError('The test command did not exit cleanly. Aborting release.')
 75 |     exit(1)
 76 |   }
 77 | 
 78 |   logSuccess('Tests were successful.')
 79 | 
 80 |   const sourceDir = path.resolve(PACKAGES_SRC_DIR, packageName)
 81 |   const outDir = path.resolve(PACKAGES_OUT_DIR, packageName)
 82 | 
 83 |   log('Cleaning destination directory...')
 84 |   rm('-rf', outDir)
 85 | 
 86 |   log('Compiling source files...')
 87 | 
 88 |   exec(
 89 |     'cross-env NODE_ENV=cjs ' +
 90 |       `${path.resolve(BIN)}/babel ${sourceDir} ` +
 91 |       `--out-dir ${path.resolve(
 92 |         outDir
 93 |       )} --ignore="**/__tests__/**,**/node_modules/**"`
 94 |   )
 95 | 
 96 |   log('Copying additional project files...')
 97 |   const additionalProjectFiles = ['README.md', '.npmignore']
 98 |   additionalProjectFiles.forEach(filename => {
 99 |     const src = path.resolve(sourceDir, filename)
100 | 
101 |     if (!test('-e', src)) return
102 | 
103 |     cp('-Rf', src, outDir)
104 |   })
105 | 
106 |   log('Generating package.json...')
107 |   const packageConfig = Object.assign(
108 |     { name: packageName, version: nextVersion },
109 |     require(BASE_PACKAGE_LOC),
110 |     require(path.resolve(sourceDir, 'package.json'))
111 |   )
112 | 
113 |   writeFile(
114 |     path.resolve(outDir, 'package.json'),
115 |     JSON.stringify(packageConfig, null, 2)
116 |   )
117 | 
118 |   log('Copying license...')
119 |   cp('-f', 'LICENSE.md', outDir)
120 | 
121 |   log(`Building ${packageName}...`)
122 |   const runRollup = () => `yarn build:${packageName}`
123 |   if (exec(runRollup()).code !== 0) {
124 |     exit(1)
125 |   }
126 | 
127 |   log(`Preparing ${libraryName}.cjs.js.flow...`)
128 |   cp(
129 |     '-f',
130 |     path.resolve(sourceDir, 'index.js.flow'),
131 |     path.resolve(outDir, 'dist', `${libraryName}.cjs.js.flow`)
132 |   )
133 | 
134 |   log(`About to publish ${packageName}@${nextVersion} to npm.`)
135 |   if (!readline.keyInYN('Sound good? ')) {
136 |     log('OK. Stopping release.')
137 |     exit(0)
138 |   }
139 | 
140 |   log('Publishing...')
141 |   if (exec(`cd ${outDir} && npm publish`).code !== 0) {
142 |     logError('Publish failed. Aborting release.')
143 |     exit(1)
144 |   }
145 | 
146 |   logSuccess(`${packageName}@${nextVersion} was successfully published.`)
147 | 
148 |   log('Updating VERSION file...')
149 |   writeFile(versionLoc, `${nextVersion}\n`)
150 | 
151 |   log('Committing changes...')
152 |   const newTagName = `v${nextVersion}`
153 |   exec(`git add ${versionLoc}`)
154 |   exec(`git commit -m "${packageName} ${newTagName}"`)
155 | 
156 |   if (packageName === 'recompose') {
157 |     log(`Tagging release... (${newTagName})`)
158 |     exec(`git tag ${newTagName}`)
159 |   }
160 | 
161 |   log('Pushing to GitHub...')
162 |   exec('git push')
163 |   exec('git push --tags')
164 | 
165 |   logSuccess('Done.')
166 | } catch (error) {
167 |   logError('Release failed due to an error', error)
168 | }
169 | 


--------------------------------------------------------------------------------
/scripts/rollup.config.js:
--------------------------------------------------------------------------------
 1 | import path from 'path'
 2 | import nodeResolve from 'rollup-plugin-node-resolve'
 3 | import babel from 'rollup-plugin-babel'
 4 | import replace from 'rollup-plugin-replace'
 5 | import commonjs from 'rollup-plugin-commonjs'
 6 | import { uglify } from 'rollup-plugin-uglify'
 7 | import { sizeSnapshot } from 'rollup-plugin-size-snapshot'
 8 | import { pascalCase } from 'change-case'
 9 | 
10 | const { PACKAGES_SRC_DIR, PACKAGES_OUT_DIR } = require('./getPackageNames')
11 | 
12 | const packageName = process.env.PACKAGE_NAME
13 | 
14 | const libraryName = pascalCase(packageName)
15 | 
16 | const input = `./${path.join(PACKAGES_SRC_DIR, packageName, 'index.js')}`
17 | 
18 | const outDir = path.join(PACKAGES_OUT_DIR, packageName, 'dist')
19 | 
20 | const isExternal = id => !id.startsWith('.') && !id.startsWith('/')
21 | 
22 | const getBabelOptions = ({ useESModules }) => ({
23 |   exclude: '**/node_modules/**',
24 |   runtimeHelpers: true,
25 |   plugins: [['@babel/transform-runtime', { useESModules }]],
26 | })
27 | 
28 | const matchSnapshot = process.env.SNAPSHOT === 'match'
29 | 
30 | export default [
31 |   {
32 |     input,
33 |     output: {
34 |       file: `${outDir}/${libraryName}.umd.js`,
35 |       format: 'umd',
36 |       name: libraryName,
37 |       globals: {
38 |         react: 'React',
39 |       },
40 |     },
41 |     external: ['react'],
42 |     plugins: [
43 |       nodeResolve(),
44 |       babel(getBabelOptions({ useESModules: true })),
45 |       commonjs(),
46 |       replace({ 'process.env.NODE_ENV': JSON.stringify('development') }),
47 |       sizeSnapshot({ matchSnapshot }),
48 |     ],
49 |   },
50 | 
51 |   {
52 |     input,
53 |     output: {
54 |       file: `${outDir}/${libraryName}.min.js`,
55 |       format: 'umd',
56 |       name: libraryName,
57 |       globals: {
58 |         react: 'React',
59 |       },
60 |     },
61 |     external: ['react'],
62 |     plugins: [
63 |       nodeResolve(),
64 |       babel(getBabelOptions({ useESModules: true })),
65 |       commonjs(),
66 |       replace({ 'process.env.NODE_ENV': JSON.stringify('production') }),
67 |       sizeSnapshot({ matchSnapshot }),
68 |       uglify(),
69 |     ],
70 |   },
71 | 
72 |   {
73 |     input,
74 |     output: {
75 |       file: `${outDir}/${libraryName}.cjs.js`,
76 |       format: 'cjs',
77 |     },
78 |     external: isExternal,
79 |     plugins: [babel(getBabelOptions({ useESModules: false }))],
80 |   },
81 | 
82 |   {
83 |     input,
84 |     output: {
85 |       file: `${outDir}/${libraryName}.esm.js`,
86 |       format: 'es',
87 |     },
88 |     external: isExternal,
89 |     plugins: [
90 |       babel(getBabelOptions({ useESModules: true })),
91 |       sizeSnapshot({ matchSnapshot }),
92 |     ],
93 |   },
94 | ]
95 | 


--------------------------------------------------------------------------------
/src/basePackage.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "author": "Andrew Clark <acdlite@me.com>",
 3 |   "repository": {
 4 |     "type": "git",
 5 |     "url": "https://github.com/acdlite/recompose.git"
 6 |   },
 7 |   "license": "MIT",
 8 |   "bugs": {
 9 |     "url": "https://github.com/acdlite/recompose/issues"
10 |   },
11 |   "homepage": "https://github.com/acdlite/recompose"
12 | }
13 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/.npmignore:
--------------------------------------------------------------------------------
1 | /**/__tests__
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/README.md:
--------------------------------------------------------------------------------
 1 | recompose-relay
 2 | ===============
 3 | 
 4 | [![npm version](https://img.shields.io/npm/v/recompose-relay.svg?style=flat-square)](https://www.npmjs.com/package/recompose-relay)
 5 | 
 6 | [Recompose](https://github.com/acdlite/recompose) helpers for [Relay](https://facebook.github.io/relay).
 7 | 
 8 | ```
 9 | npm install --save recompose-relay
10 | ```
11 | 
12 | ## API
13 | 
14 | ### `createContainer()`
15 | 
16 | ```js
17 | createContainer(
18 |   specification: Object,
19 |   BaseComponent: ReactElementType
20 | ): ReactElementType
21 | ```
22 | 
23 | A curried, component-last version of `Relay.createContainer()`. This makes it composable with other Recompose helpers.
24 | 
25 | If the base component is not a class component, it is converted to one using `toClass()`. This allows Relay to add a ref to the base component without causing React to print a warning. (Function components cannot have refs.) This behavior will be removed once Relay updates to support function components.
26 | 
27 | Tip: Use `flattenProp()` in combination with `createContainer()` to flatten fragment props:
28 | 
29 | ```js
30 | const Post = compose(
31 |   createContainer({
32 |     fragments: {
33 |       post: () => Relay.QL`
34 |         fragment on Post {
35 |           title,
36 |           content,
37 |           author {
38 |             name
39 |           }
40 |         }
41 |       `
42 |     }
43 |   }),
44 |   flattenProp('post')
45 | )(({ title, content, author }) => (
46 |   <article>
47 |     <h1>{title}</h1>
48 |     <h2>By {author.name}</h2>
49 |     <div>{content}</div>
50 |   </article>
51 | ));
52 | ```
53 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/VERSION:
--------------------------------------------------------------------------------
1 | 0.3.1
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/createContainer.js:
--------------------------------------------------------------------------------
1 | import Relay from 'react-relay'
2 | import { toClass } from 'recompose'
3 | 
4 | const createContainer = options => BaseComponent =>
5 |   Relay.createContainer(toClass(BaseComponent), options)
6 | 
7 | export default createContainer
8 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/index.js:
--------------------------------------------------------------------------------
1 | export { default as createContainer } from './createContainer'
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "description": "Recompose helpers for Relay.",
 3 |   "scripts": {
 4 |     "update-schema": "node -r babel-core/register updateSchema.js"
 5 |   },
 6 |   "keywords": [
 7 |     "recompose",
 8 |     "relay",
 9 |     "react",
10 |     "higher-order",
11 |     "components",
12 |     "microcomponentization",
13 |     "toolkit",
14 |     "utilities",
15 |     "composition"
16 |   ],
17 |   "main": "cjs/RecomposeRelay.js",
18 |   "module": "es/RecomposeRelay.js",
19 |   "dependencies": {
20 |     "lodash": "^4.0.0"
21 |   },
22 |   "peerDependencies": {
23 |     "recompose": "^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0",
24 |     "react": "^0.14.0 || ^15.0.0",
25 |     "react-relay": "^0.6.0 || ^0.7.0 || ^0.8.0 || ^0.9.0"
26 |   }
27 | }
28 | 


--------------------------------------------------------------------------------
/src/packages/recompose-relay/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 | 
4 | 
5 | lodash@^4.0.0:
6 |   version "4.17.4"
7 |   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae"
8 |   integrity sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/.npmignore:
--------------------------------------------------------------------------------
1 | /**/__tests__
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose/README.md:
--------------------------------------------------------------------------------
1 | recompose
2 | =========
3 | 
4 | [![npm version](https://img.shields.io/npm/v/recompose.svg?style=flat-square)](https://www.npmjs.com/package/recompose)
5 | 
6 | Recompose is a React utility belt for function components and higher-order components. See the [GitHub project page](https://github.com/acdlite/recompose) for more information.
7 | 


--------------------------------------------------------------------------------
/src/packages/recompose/VERSION:
--------------------------------------------------------------------------------
1 | 0.30.0
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/branch-test.js:
--------------------------------------------------------------------------------
 1 | import sinon from 'sinon'
 2 | import React from 'react'
 3 | import { mount } from 'enzyme'
 4 | import { branch, compose, withState, withProps } from '../'
 5 | 
 6 | test('branch tests props and applies one of two HoCs, for true and false', () => {
 7 |   const SayMyName = compose(
 8 |     withState('isBad', 'updateIsBad', false),
 9 |     branch(
10 |       props => props.isBad,
11 |       withProps({ name: 'Heisenberg' }),
12 |       withProps({ name: 'Walter' })
13 |     )
14 |   )(({ isBad, name, updateIsBad }) =>
15 |     <div>
16 |       <div className="isBad">
17 |         {isBad ? 'true' : 'false'}
18 |       </div>
19 |       <div className="name">
20 |         {name}
21 |       </div>
22 |       <button onClick={() => updateIsBad(b => !b)}>Toggle</button>
23 |     </div>
24 |   )
25 | 
26 |   expect(SayMyName.displayName).toBe('withState(branch(Component))')
27 | 
28 |   const wrapper = mount(<SayMyName />)
29 |   const getIsBad = () => wrapper.find('.isBad').text()
30 |   const getName = () => wrapper.find('.name').text()
31 |   const toggle = wrapper.find('button')
32 | 
33 |   expect(getIsBad()).toBe('false')
34 |   expect(getName()).toBe('Walter')
35 | 
36 |   toggle.simulate('click')
37 | 
38 |   expect(getIsBad()).toBe('true')
39 |   expect(getName()).toBe('Heisenberg')
40 | })
41 | 
42 | test('branch defaults third argument to identity function', () => {
43 |   const Left = () => <div className="left">Left</div>
44 |   const Right = () => <div className="right">Right</div>
45 | 
46 |   const BranchedComponent = branch(
47 |     () => false,
48 |     () => props => <Left {...props} />
49 |   )(Right)
50 | 
51 |   const wrapper = mount(<BranchedComponent />)
52 |   const right = wrapper.find('.right').text()
53 | 
54 |   expect(right).toBe('Right')
55 | })
56 | 
57 | test('branch third argument should not cause console error', () => {
58 |   const error = sinon.stub(console, 'error')
59 |   const Component = () => <div className="right">Component</div>
60 | 
61 |   const BranchedComponent = branch(() => false, v => v, v => v)(Component)
62 | 
63 |   mount(<BranchedComponent />)
64 | 
65 |   expect(error.called).toBe(false)
66 | 
67 |   /* eslint-disable */
68 |   error.restore()
69 |   /* eslint-enable */
70 | })
71 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/componentFromProp-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { componentFromProp } from '../'
 4 | 
 5 | test('componentFromProp creates a component that takes a component as a prop and renders it with the rest of the props', () => {
 6 |   const Container = componentFromProp('component')
 7 |   expect(Container.displayName).toBe('componentFromProp(component)')
 8 | 
 9 |   const Component = ({ pass }) =>
10 |     <div>
11 |       Pass: {pass}
12 |     </div>
13 | 
14 |   const wrapper = mount(<Container component={Component} pass="through" />)
15 |   const div = wrapper.find('div')
16 |   expect(div.text()).toBe('Pass: through')
17 | })
18 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/componentFromStream-test.js:
--------------------------------------------------------------------------------
  1 | import React from 'react'
  2 | import { mount } from 'enzyme'
  3 | import { Observable, Subject } from 'rxjs'
  4 | import sinon from 'sinon'
  5 | import rxjsConfig from '../rxjsObservableConfig'
  6 | import { componentFromStreamWithConfig } from '../componentFromStream'
  7 | 
  8 | const componentFromStream = componentFromStreamWithConfig(rxjsConfig)
  9 | 
 10 | test('componentFromStream creates a component from a prop stream transformation', () => {
 11 |   const Double = componentFromStream(props$ =>
 12 |     props$.map(({ n }) =>
 13 |       <div>
 14 |         {n * 2}
 15 |       </div>
 16 |     )
 17 |   )
 18 |   const wrapper = mount(<Double n={112} />)
 19 |   const div = wrapper.find('div')
 20 |   expect(div.text()).toBe('224')
 21 |   wrapper.setProps({ n: 358 })
 22 |   expect(div.text()).toBe('716')
 23 | })
 24 | 
 25 | test('componentFromStream unsubscribes from stream before unmounting', () => {
 26 |   let subscriptions = 0
 27 |   const vdom$ = new Observable(observer => {
 28 |     subscriptions += 1
 29 |     observer.next(<div />)
 30 |     return {
 31 |       unsubscribe() {
 32 |         subscriptions -= 1
 33 |       },
 34 |     }
 35 |   })
 36 |   const Div = componentFromStream(() => vdom$)
 37 |   const wrapper = mount(<Div />)
 38 |   expect(subscriptions).toBe(1)
 39 |   wrapper.unmount()
 40 |   expect(subscriptions).toBe(0)
 41 | })
 42 | 
 43 | test('componentFromStream renders nothing until the stream emits a value', () => {
 44 |   const vdom$ = new Subject()
 45 |   const Div = componentFromStream(() => vdom$.mapTo(<div />))
 46 |   const wrapper = mount(<Div />)
 47 |   expect(wrapper.find('div').length).toBe(0)
 48 |   vdom$.next()
 49 |   wrapper.update()
 50 |   expect(wrapper.find('div').length).toBe(1)
 51 | })
 52 | 
 53 | test('handler multiple observers of props stream', () => {
 54 |   const Other = () => <div />
 55 |   const Div = componentFromStream(props$ =>
 56 |     // Adds three observers to props stream
 57 |     props$.combineLatest(props$, props$, props1 => <Other {...props1} />)
 58 |   )
 59 | 
 60 |   const wrapper = mount(<Div data-value={1} />)
 61 |   const div = wrapper.find(Other)
 62 | 
 63 |   expect(div.prop('data-value')).toBe(1)
 64 |   wrapper.setProps({ 'data-value': 2 })
 65 |   wrapper.update()
 66 |   const div2 = wrapper.find(Other)
 67 |   expect(div2.prop('data-value')).toBe(2)
 68 | })
 69 | 
 70 | test('complete props stream before unmounting', () => {
 71 |   let counter = 0
 72 | 
 73 |   const Div = componentFromStream(props$ => {
 74 |     const first$ = props$.first().do(() => {
 75 |       counter += 1
 76 |     })
 77 | 
 78 |     const last$ = props$
 79 |       .last()
 80 |       .do(() => {
 81 |         counter -= 1
 82 |       })
 83 |       .startWith(null)
 84 | 
 85 |     return props$.combineLatest(first$, last$, props1 => <div {...props1} />)
 86 |   })
 87 | 
 88 |   const wrapper = mount(<Div />)
 89 | 
 90 |   expect(counter).toBe(1)
 91 |   expect(wrapper.find('div').length).toBe(1)
 92 | 
 93 |   wrapper.unmount()
 94 |   expect(counter).toBe(0)
 95 | })
 96 | 
 97 | test('completed props stream should throw an exception', () => {
 98 |   const Div = componentFromStream(props$ => {
 99 |     const first$ = props$.filter(() => false).first().startWith(null)
100 | 
101 |     return props$.combineLatest(first$, props1 => <div {...props1} />)
102 |   })
103 | 
104 |   const wrapper = mount(<Div />)
105 | 
106 |   expect(wrapper.find('div').length).toBe(1)
107 | 
108 |   const error = sinon.stub(console, 'error')
109 | 
110 |   expect(() => wrapper.unmount()).toThrowError(/no elements in sequence/)
111 |   expect(error.called).toBe(true)
112 | })
113 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/componentFromStreamWithConfig-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { Observable } from 'rxjs'
 4 | import { Stream as MostStream } from 'most'
 5 | import mostConfig from '../mostObservableConfig'
 6 | import rxjsConfig from '../rxjsObservableConfig'
 7 | import { componentFromStreamWithConfig } from '../componentFromStream'
 8 | 
 9 | test('componentFromStreamWithConfig creates a stream with the correct stream type.', () => {
10 |   const MostComponent = componentFromStreamWithConfig(mostConfig)(props$ => {
11 |     expect(props$ instanceof MostStream).toBe(true)
12 |     return props$.map(v =>
13 |       <div>
14 |         {String(v)}
15 |       </div>
16 |     )
17 |   })
18 | 
19 |   mount(<MostComponent />)
20 | 
21 |   const RXJSComponent = componentFromStreamWithConfig(rxjsConfig)(props$ => {
22 |     expect(props$ instanceof Observable).toBe(true)
23 |     return props$.map(v =>
24 |       <div>
25 |         {String(v)}
26 |       </div>
27 |     )
28 |   })
29 | 
30 |   mount(<RXJSComponent />)
31 | })
32 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/compose-test.js:
--------------------------------------------------------------------------------
 1 | import { compose } from '../'
 2 | 
 3 | test('compose composes from right to left', () => {
 4 |   const double = x => x * 2
 5 |   const square = x => x * x
 6 |   expect(compose(square)(5)).toBe(25)
 7 |   expect(compose(square, double)(5)).toBe(100)
 8 |   expect(compose(double, square, double)(5)).toBe(200)
 9 | })
10 | 
11 | test('compose can be seeded with multiple arguments', () => {
12 |   const square = x => x * x
13 |   const add = (x, y) => x + y
14 |   expect(compose(square, add)(1, 2)).toBe(9)
15 | })
16 | 
17 | test('compose returns the identity function if given no arguments', () => {
18 |   expect(compose()(1, 2)).toBe(1)
19 |   expect(compose()(3)).toBe(3)
20 |   expect(compose()()).toBe(undefined)
21 | })
22 | 
23 | test('compose returns the first function if given only one', () => {
24 |   const fn = x => x * x
25 |   expect(compose(fn)(3)).toBe(fn(3))
26 | })
27 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/createEventHandler-test.js:
--------------------------------------------------------------------------------
 1 | import { createEventHandler } from '../'
 2 | 
 3 | test('createEventHandler creates an event handler and a corresponding stream', () => {
 4 |   const result = []
 5 |   const { stream, handler } = createEventHandler()
 6 |   const subscription = stream.subscribe({ next: v => result.push(v) })
 7 | 
 8 |   handler(1)
 9 |   handler(2)
10 |   handler(3)
11 | 
12 |   subscription.unsubscribe()
13 |   expect(result).toEqual([1, 2, 3])
14 | })
15 | 
16 | test('handles multiple subscribers', () => {
17 |   const result1 = []
18 |   const result2 = []
19 |   const { handler, stream } = createEventHandler()
20 |   const subscription1 = stream.subscribe({ next: v => result1.push(v) })
21 |   const subscription2 = stream.subscribe({ next: v => result2.push(v) })
22 | 
23 |   handler(1)
24 |   handler(2)
25 |   handler(3)
26 | 
27 |   subscription1.unsubscribe()
28 |   subscription2.unsubscribe()
29 | 
30 |   expect(result1).toEqual([1, 2, 3])
31 |   expect(result2).toEqual([1, 2, 3])
32 | })
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/createSink-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { createSink, compose, withState, mapProps } from '../'
 5 | 
 6 | test('createSink creates a React component that fires a callback when receiving new props', () => {
 7 |   const spy = sinon.spy()
 8 |   const Sink = createSink(spy)
 9 |   const Counter = compose(
10 |     withState('counter', 'updateCounter', 0),
11 |     mapProps(({ updateCounter, ...rest }) => ({
12 |       increment: () => updateCounter(n => n + 1),
13 |       ...rest,
14 |     }))
15 |   )(Sink)
16 | 
17 |   mount(
18 |     <div>
19 |       <Counter />
20 |     </div>
21 |   )
22 | 
23 |   const { increment } = spy.lastCall.args[0]
24 |   const getCounter = () => spy.lastCall.args[0].counter
25 |   expect(getCounter()).toBe(0)
26 |   increment()
27 |   expect(getCounter()).toBe(1)
28 |   increment()
29 |   expect(getCounter()).toBe(2)
30 | })
31 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/defaultProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { shallow } from 'enzyme'
 3 | import { defaultProps } from '../'
 4 | 
 5 | test('defaultProps passes additional props to base component', () => {
 6 |   const DoReMi = defaultProps({ 'data-so': 'do', 'data-la': 'fa' })('div')
 7 |   expect(DoReMi.displayName).toBe('defaultProps(div)')
 8 | 
 9 |   const div = shallow(<DoReMi />).find('div')
10 |   expect(div.equals(<div data-so="do" data-la="fa" />)).toBe(true)
11 | })
12 | 
13 | test('defaultProps has lower precendence than props from owner', () => {
14 |   const DoReMi = defaultProps({ 'data-so': 'do', 'data-la': 'fa' })('div')
15 |   expect(DoReMi.displayName).toBe('defaultProps(div)')
16 | 
17 |   const div = shallow(<DoReMi data-la="ti" />).find('div')
18 |   expect(div.equals(<div data-so="do" data-la="ti" />)).toBe(true)
19 | })
20 | 
21 | test('defaultProps overrides undefined owner props', () => {
22 |   const DoReMi = defaultProps({ 'data-so': 'do', 'data-la': 'fa' })('div')
23 |   expect(DoReMi.displayName).toBe('defaultProps(div)')
24 | 
25 |   const div = shallow(<DoReMi data-la={undefined} />).find('div')
26 |   expect(div.equals(<div data-so="do" data-la="fa" />)).toBe(true)
27 | })
28 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/fixtures/treeshake-entry.js:
--------------------------------------------------------------------------------
1 | import '../../../../../lib/packages/recompose/es/Recompose.js'
2 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/flattenProp-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { shallow } from 'enzyme'
 3 | import { flattenProp } from '../'
 4 | 
 5 | test('flattenProps flattens an object prop and spreads it into the top-level props object', () => {
 6 |   const Counter = flattenProp('data-state')('div')
 7 |   expect(Counter.displayName).toBe('flattenProp(div)')
 8 | 
 9 |   const wrapper = shallow(
10 |     <Counter data-pass="through" data-state={{ 'data-counter': 1 }} />
11 |   )
12 | 
13 |   expect(
14 |     wrapper.equals(
15 |       <div
16 |         data-pass="through"
17 |         data-state={{ 'data-counter': 1 }}
18 |         data-counter={1}
19 |       />
20 |     )
21 |   ).toBe(true)
22 | 
23 |   wrapper.setProps({
24 |     'data-pass': 'through',
25 |     'data-state': { 'data-state': 1 },
26 |   })
27 |   expect(wrapper.equals(<div data-pass="through" data-state={1} />)).toBe(true)
28 | })
29 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/fromRenderProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { fromRenderProps, compose, toRenderProps, defaultProps } from '../'
 4 | 
 5 | test('fromRenderProps passes additional props to base component', () => {
 6 |   const RenderPropsComponent = ({ children }) => children({ i18n: 'zh-TW' })
 7 |   const EnhancedComponent = fromRenderProps(
 8 |     RenderPropsComponent,
 9 |     ({ i18n }) => ({
10 |       i18n,
11 |     })
12 |   )('div')
13 |   expect(EnhancedComponent.displayName).toBe('fromRenderProps(div)')
14 | 
15 |   const div = mount(<EnhancedComponent />)
16 |   expect(div.html()).toBe(`<div i18n="zh-TW"></div>`)
17 | })
18 | 
19 | test('fromRenderProps passes additional props to base component with custom renderPropName', () => {
20 |   const RenderPropsComponent = ({ render }) => render({ i18n: 'zh-TW' })
21 |   const EnhancedComponent = fromRenderProps(
22 |     RenderPropsComponent,
23 |     ({ i18n }) => ({
24 |       i18n,
25 |     }),
26 |     'render'
27 |   )('div')
28 |   expect(EnhancedComponent.displayName).toBe('fromRenderProps(div)')
29 | 
30 |   const div = mount(<EnhancedComponent />)
31 |   expect(div.html()).toBe(`<div i18n="zh-TW"></div>`)
32 | })
33 | 
34 | test('fromRenderProps passes additional props to base component with 2 RenderPropsComponents', () => {
35 |   const RenderPropsComponent1 = ({ children }) => children({ theme: 'dark' })
36 |   const RenderPropsComponent2 = ({ render }) => render({ i18n: 'zh-TW' })
37 |   const EnhancedComponent = compose(
38 |     fromRenderProps(
39 |       RenderPropsComponent1,
40 |       ({ theme }) => ({ theme }),
41 |       'children'
42 |     ),
43 |     fromRenderProps(
44 |       RenderPropsComponent2,
45 |       ({ i18n }) => ({ locale: i18n }),
46 |       'render'
47 |     )
48 |   )('div')
49 |   expect(EnhancedComponent.displayName).toBe(
50 |     'fromRenderProps(fromRenderProps(div))'
51 |   )
52 | 
53 |   const div = mount(<EnhancedComponent />)
54 |   expect(div.html()).toBe(`<div theme="dark" locale="zh-TW"></div>`)
55 | })
56 | 
57 | test('fromRenderProps meet toRenderProps', () => {
58 |   const RenderPropsComponent = toRenderProps(
59 |     defaultProps({ foo1: 'bar1', foo2: 'bar2' })
60 |   )
61 | 
62 |   const EnhancedComponent = fromRenderProps(
63 |     RenderPropsComponent,
64 |     ({ foo1 }) => ({
65 |       foo: foo1,
66 |     })
67 |   )('div')
68 |   expect(EnhancedComponent.displayName).toBe('fromRenderProps(div)')
69 | 
70 |   const div = mount(<EnhancedComponent />)
71 |   expect(div.html()).toBe(`<div foo="bar1"></div>`)
72 | })
73 | 
74 | test('fromRenderProps with multiple arguments #693', () => {
75 |   const RenderPropsComponent = ({ children }) =>
76 |     children({ theme: 'dark' }, { data: 'data' })
77 |   const EnhancedComponent = compose(
78 |     fromRenderProps(
79 |       RenderPropsComponent,
80 |       ({ theme }, { data }) => ({ theme, data }),
81 |       'children'
82 |     )
83 |   )('div')
84 |   expect(EnhancedComponent.displayName).toBe('fromRenderProps(div)')
85 | 
86 |   const div = mount(<EnhancedComponent />)
87 |   expect(div.html()).toBe(`<div theme="dark" data="data"></div>`)
88 | })
89 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/getContext-test.js:
--------------------------------------------------------------------------------
1 | // Tests for getContext() are covered by withContext-test.js
2 | // This is just a dummy test so Ava doesn't complain
3 | test('getContext works', () => expect(true).toBe(true))
4 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/getDisplayName-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { getDisplayName } from '../'
 3 | 
 4 | test('getDisplayName gets the display name of a React component', () => {
 5 |   class SomeComponent extends React.Component {
 6 |     render() {
 7 |       return <div />
 8 |     }
 9 |   }
10 | 
11 |   class SomeOtherComponent extends React.Component {
12 |     static displayName = 'CustomDisplayName'
13 |     render() {
14 |       return <div />
15 |     }
16 |   }
17 | 
18 |   function YetAnotherComponent() {
19 |     return <div />
20 |   }
21 | 
22 |   expect(getDisplayName(SomeComponent)).toBe('SomeComponent')
23 |   expect(getDisplayName(SomeOtherComponent)).toBe('CustomDisplayName')
24 |   expect(getDisplayName(YetAnotherComponent)).toBe('YetAnotherComponent')
25 |   expect(getDisplayName(() => <div />)).toBe('Component')
26 |   expect(getDisplayName('div')).toBe('div')
27 | })
28 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/hoistStatics-test.js:
--------------------------------------------------------------------------------
 1 | import React, { createFactory } from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { hoistStatics, mapProps } from '../'
 5 | 
 6 | test('copies non-React static properties from base component to new component', () => {
 7 |   const BaseComponent = sinon.spy(() => null)
 8 |   BaseComponent.foo = () => {}
 9 | 
10 |   const EnhancedComponent = hoistStatics(
11 |     mapProps(props => ({ n: props.n * 5 }))
12 |   )(BaseComponent)
13 | 
14 |   expect(EnhancedComponent.foo).toBe(BaseComponent.foo)
15 | 
16 |   mount(<EnhancedComponent n={3} />)
17 |   expect(BaseComponent.firstCall.args[0].n).toBe(15)
18 | })
19 | 
20 | test('does not copy blacklisted static properties to new component ', () => {
21 |   const BaseComponent = sinon.spy(() => null)
22 |   BaseComponent.foo = () => {}
23 |   BaseComponent.bar = () => {}
24 | 
25 |   const EnhancedComponent = hoistStatics(
26 |     comp => createFactory(comp),
27 |     { bar: true } // Blacklist
28 |   )(BaseComponent)
29 | 
30 |   expect(EnhancedComponent.foo).toBe(BaseComponent.foo)
31 |   expect(EnhancedComponent.bar).toBe(undefined)
32 | })
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/isClassComponent-test.js:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react'
 2 | import createReactClass from 'create-react-class'
 3 | import isClassComponent from '../isClassComponent'
 4 | 
 5 | test('isClassComponent returns false for functions', () => {
 6 |   const Foo = () => <div />
 7 | 
 8 |   expect(isClassComponent(Foo)).toBe(false)
 9 | })
10 | 
11 | test('isClassComponent returns true for React component classes', () => {
12 |   class Foo extends Component {
13 |     render() {
14 |       return <div />
15 |     }
16 |   }
17 | 
18 |   /* eslint-disable react/prefer-es6-class */
19 |   const Bar = createReactClass({
20 |     render() {
21 |       return <div />
22 |     },
23 |   })
24 |   /* eslint-enable react/prefer-es6-class */
25 | 
26 |   expect(isClassComponent(Foo)).toBe(true)
27 |   expect(isClassComponent(Bar)).toBe(true)
28 | })
29 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/lifecycle-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { lifecycle } from '../'
 4 | 
 5 | test('lifecycle is a higher-order component version of React.Component', () => {
 6 |   const enhance = lifecycle({
 7 |     componentWillMount() {
 8 |       this.setState({ 'data-bar': 'baz' })
 9 |     },
10 |   })
11 |   const Div = enhance('div')
12 |   expect(Div.displayName).toBe('lifecycle(div)')
13 | 
14 |   const div = mount(<Div data-foo="bar" />).find('div')
15 |   expect(div.prop('data-foo')).toBe('bar')
16 |   expect(div.prop('data-bar')).toBe('baz')
17 | })
18 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/mapProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { mapProps, withState, compose } from '../'
 5 | 
 6 | test('mapProps maps owner props to child props', () => {
 7 |   const component = sinon.spy(() => null)
 8 |   component.displayName = 'component'
 9 | 
10 |   const StringConcat = compose(
11 |     withState('strings', 'updateStrings', ['do', 're', 'mi']),
12 |     mapProps(({ strings, ...rest }) => ({
13 |       ...rest,
14 |       string: strings.join(''),
15 |     }))
16 |   )(component)
17 | 
18 |   expect(StringConcat.displayName).toBe('withState(mapProps(component))')
19 | 
20 |   mount(<StringConcat />)
21 |   const { updateStrings } = component.firstCall.args[0]
22 |   updateStrings(strings => [...strings, 'fa'])
23 | 
24 |   expect(component.firstCall.args[0].string).toBe('doremi')
25 |   expect(component.secondCall.args[0].string).toBe('doremifa')
26 | })
27 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/mapPropsStream-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import setObservableConfig from '../setObservableConfig'
 4 | import rxjs4Config from '../rxjs4ObservableConfig'
 5 | import { mapPropsStream } from '../'
 6 | 
 7 | setObservableConfig(rxjs4Config)
 8 | 
 9 | // Most of mapPropsStream's functionality is covered by componentFromStream
10 | test('mapPropsStream creates a higher-order component from a stream', () => {
11 |   const Double = mapPropsStream(props$ =>
12 |     props$.map(({ n }) => ({ children: n * 2 }))
13 |   )('div')
14 |   const wrapper = mount(<Double n={112} />)
15 |   const div = wrapper.find('div')
16 |   expect(div.text()).toBe('224')
17 |   wrapper.setProps({ n: 358 })
18 |   expect(div.text()).toBe('716')
19 | })
20 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/mapPropsStreamWithConfig-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { Stream as MostStream } from 'most'
 4 | import { Observable } from 'rxjs'
 5 | import { mapPropsStreamWithConfig } from '../'
 6 | import rxConfig from '../rxjsObservableConfig'
 7 | import mostConfig from '../mostObservableConfig'
 8 | 
 9 | // Most of mapPropsStreamConfig's functionality is covered by componentFromStream
10 | test('mapPropsStreamWithConfig creates a higher-order component from a stream and a observable config', () => {
11 |   const Double = mapPropsStreamWithConfig(rxConfig)(props$ =>
12 |     props$.map(({ n }) => ({ children: n * 2 }))
13 |   )('div')
14 |   const wrapper = mount(<Double n={112} />)
15 |   const div = wrapper.find('div')
16 |   expect(div.text()).toBe('224')
17 |   wrapper.setProps({ n: 358 })
18 |   expect(div.text()).toBe('716')
19 | })
20 | 
21 | test('mapPropsStreamWithConfig creates a stream with the correct config', () => {
22 |   const MostComponent = mapPropsStreamWithConfig(mostConfig)(props$ => {
23 |     expect(props$ instanceof MostStream).toBe(true)
24 |     return props$.map(v => v)
25 |   })('div')
26 | 
27 |   mount(<MostComponent />)
28 | 
29 |   const RXJSComponent = mapPropsStreamWithConfig(rxConfig)(props$ => {
30 |     expect(props$ instanceof Observable).toBe(true)
31 |     return props$.map(v => v)
32 |   })('div')
33 | 
34 |   mount(<RXJSComponent />)
35 | })
36 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/nest-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { shallow } from 'enzyme'
 3 | import { nest, setDisplayName, toClass } from '../'
 4 | 
 5 | test('nest nests components from outer to inner', () => {
 6 |   const A = setDisplayName('A')(toClass('div'))
 7 |   const B = setDisplayName('B')(toClass('div'))
 8 |   const C = setDisplayName('C')(toClass('div'))
 9 | 
10 |   const Nest = nest(A, B, C)
11 | 
12 |   expect(Nest.displayName).toBe('nest(A, B, C)')
13 | 
14 |   const wrapper = shallow(<Nest pass="through">Child</Nest>)
15 | 
16 |   expect(
17 |     wrapper.equals(
18 |       <A pass="through">
19 |         <B pass="through">
20 |           <C pass="through">Child</C>
21 |         </B>
22 |       </A>
23 |     )
24 |   ).toBe(true)
25 | })
26 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/onlyUpdateForKeys-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { onlyUpdateForKeys, compose, withState } from '../'
 5 | 
 6 | test('onlyUpdateForKeys implements shouldComponentUpdate()', () => {
 7 |   const component = sinon.spy(() => null)
 8 |   component.displayName = 'component'
 9 | 
10 |   const Counter = compose(
11 |     withState('counter', 'updateCounter', 0),
12 |     withState('foobar', 'updateFoobar', 'foobar'),
13 |     onlyUpdateForKeys(['counter'])
14 |   )(component)
15 | 
16 |   expect(Counter.displayName).toBe(
17 |     'withState(withState(onlyUpdateForKeys(component)))'
18 |   )
19 | 
20 |   mount(<Counter />)
21 |   const { updateCounter, updateFoobar } = component.firstCall.args[0]
22 | 
23 |   expect(component.lastCall.args[0].counter).toBe(0)
24 |   expect(component.lastCall.args[0].foobar).toBe('foobar')
25 | 
26 |   // Does not update
27 |   updateFoobar('barbaz')
28 |   expect(component.calledOnce).toBe(true)
29 | 
30 |   updateCounter(42)
31 |   expect(component.calledTwice).toBe(true)
32 |   expect(component.lastCall.args[0].counter).toBe(42)
33 |   expect(component.lastCall.args[0].foobar).toBe('barbaz')
34 | })
35 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/onlyUpdateForPropTypes-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import PropTypes from 'prop-types'
 3 | import sinon from 'sinon'
 4 | import { mount, shallow } from 'enzyme'
 5 | import { onlyUpdateForPropTypes, compose, withState, setPropTypes } from '../'
 6 | 
 7 | test('onlyUpdateForPropTypes only updates for props specified in propTypes', () => {
 8 |   const component = sinon.spy(() => null)
 9 |   component.displayName = 'component'
10 | 
11 |   const Counter = compose(
12 |     withState('counter', 'updateCounter', 0),
13 |     withState('foobar', 'updateFoobar', 'foobar'),
14 |     onlyUpdateForPropTypes,
15 |     setPropTypes({ counter: PropTypes.number })
16 |   )(component)
17 | 
18 |   expect(Counter.displayName).toBe(
19 |     'withState(withState(onlyUpdateForPropTypes(component)))'
20 |   )
21 | 
22 |   mount(<Counter />)
23 |   const { updateCounter, updateFoobar } = component.firstCall.args[0]
24 | 
25 |   expect(component.lastCall.args[0].counter).toBe(0)
26 |   expect(component.lastCall.args[0].foobar).toBe('foobar')
27 | 
28 |   // Does not update
29 |   updateFoobar('barbaz')
30 |   expect(component.calledOnce).toBe(true)
31 | 
32 |   updateCounter(42)
33 |   expect(component.calledTwice).toBe(true)
34 |   expect(component.lastCall.args[0].counter).toBe(42)
35 |   expect(component.lastCall.args[0].foobar).toBe('barbaz')
36 | })
37 | 
38 | test('onlyUpdateForPropTypes warns if BaseComponent does not have any propTypes', () => {
39 |   const error = sinon.stub(console, 'error')
40 |   const ShouldWarn = onlyUpdateForPropTypes('div')
41 | 
42 |   shallow(<ShouldWarn />)
43 | 
44 |   expect(error.firstCall.args[0]).toBe(
45 |     'A component without any `propTypes` was passed to ' +
46 |       '`onlyUpdateForPropTypes()`. Check the implementation of the component ' +
47 |       'with display name "div".'
48 |   )
49 | 
50 |   /* eslint-disable */
51 |   console.error.restore()
52 |   /* eslint-enable */
53 | })
54 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/pure-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { pure, compose, withState } from '../'
 5 | import { countRenders } from './utils'
 6 | 
 7 | test('pure implements shouldComponentUpdate() using shallowEqual()', () => {
 8 |   const component = sinon.spy(() => null)
 9 |   component.displayName = 'component'
10 | 
11 |   const initialTodos = ['eat', 'drink', 'sleep']
12 |   const Todos = compose(
13 |     withState('todos', 'updateTodos', initialTodos),
14 |     pure,
15 |     countRenders
16 |   )(component)
17 | 
18 |   expect(Todos.displayName).toBe('withState(pure(countRenders(component)))')
19 | 
20 |   mount(<Todos />)
21 |   const { updateTodos } = component.firstCall.args[0]
22 | 
23 |   expect(component.lastCall.args[0].todos).toBe(initialTodos)
24 |   expect(component.lastCall.args[0].renderCount).toBe(1)
25 | 
26 |   // Does not re-render
27 |   updateTodos(initialTodos)
28 |   expect(component.calledOnce).toBe(true)
29 | 
30 |   updateTodos(todos => todos.slice(0, -1))
31 |   expect(component.calledTwice).toBe(true)
32 |   expect(component.lastCall.args[0].todos).toEqual(['eat', 'drink'])
33 |   expect(component.lastCall.args[0].renderCount).toBe(2)
34 | })
35 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/renameProp-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { withProps, renameProp, compose } from '../'
 4 | 
 5 | test('renameProp renames a single prop', () => {
 6 |   const StringConcat = compose(
 7 |     withProps({ 'data-so': 123, 'data-la': 456 }),
 8 |     renameProp('data-so', 'data-do')
 9 |   )('div')
10 | 
11 |   expect(StringConcat.displayName).toBe('withProps(renameProp(div))')
12 | 
13 |   const div = mount(<StringConcat />).find('div')
14 |   expect(div.props()).toEqual({ 'data-do': 123, 'data-la': 456 })
15 | })
16 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/renameProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { withProps, renameProps, compose } from '../'
 4 | 
 5 | test('renameProps renames props', () => {
 6 |   const StringConcat = compose(
 7 |     withProps({ 'data-so': 123, 'data-la': 456 }),
 8 |     renameProps({ 'data-so': 'data-do', 'data-la': 'data-fa' })
 9 |   )('div')
10 | 
11 |   expect(StringConcat.displayName).toBe('withProps(renameProps(div))')
12 | 
13 |   const div = mount(<StringConcat />).find('div')
14 | 
15 |   expect(div.prop('data-do')).toBe(123)
16 |   expect(div.prop('data-fa')).toBe(456)
17 | })
18 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/renderComponent-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { renderComponent, withState, compose, branch } from '../'
 5 | 
 6 | test('renderComponent always renders the given component', () => {
 7 |   const componentA = sinon.spy(() => null)
 8 |   const componentB = sinon.spy(() => null)
 9 | 
10 |   const Foobar = compose(
11 |     withState('flip', 'updateFlip', false),
12 |     branch(
13 |       props => props.flip,
14 |       renderComponent(componentA),
15 |       renderComponent(componentB)
16 |     )
17 |   )(null)
18 | 
19 |   mount(<Foobar />)
20 |   const { updateFlip } = componentB.firstCall.args[0]
21 | 
22 |   expect(componentB.calledOnce).toBe(true)
23 |   expect(componentA.notCalled).toBe(true)
24 | 
25 |   updateFlip(true)
26 |   expect(componentB.calledOnce).toBe(true)
27 |   expect(componentA.calledOnce).toBe(true)
28 | })
29 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/renderNothing-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { shallow } from 'enzyme'
 3 | import { renderNothing } from '../'
 4 | 
 5 | test('renderNothing returns a component that renders null', () => {
 6 |   const Nothing = renderNothing('div')
 7 |   const wrapper = shallow(<Nothing />)
 8 | 
 9 |   const Parent = () => <Nothing />
10 |   const parentWrapper = shallow(<Parent />)
11 | 
12 |   expect(wrapper.type()).toBe(null)
13 |   expect(parentWrapper.text()).toBe('<Nothing />')
14 | })
15 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/setDisplayName-test.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import { setDisplayName } from '../'
3 | 
4 | test('setDisplayName sets a static property on the base component', () => {
5 |   const BaseComponent = () => <div />
6 |   const NewComponent = setDisplayName('Foo')(BaseComponent)
7 |   expect(NewComponent.displayName).toBe('Foo')
8 | })
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/setObservableConfig-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import rxjs5Config from '../rxjsObservableConfig'
 4 | import rxjs4Config from '../rxjs4ObservableConfig'
 5 | import mostConfig from '../mostObservableConfig'
 6 | import xstreamConfig from '../xstreamObservableConfig'
 7 | import baconConfig from '../baconObservableConfig'
 8 | import kefirConfig from '../kefirObservableConfig'
 9 | import flydConfig from '../flydObservableConfig'
10 | import setObservableConfig from '../setObservableConfig'
11 | import componentFromStream from '../componentFromStream'
12 | 
13 | const testTransform = transform => {
14 |   const Double = componentFromStream(transform)
15 |   const wrapper = mount(<Double n={112} />)
16 |   const div = wrapper.find('div')
17 |   expect(div.text()).toBe('224')
18 |   wrapper.setProps({ n: 358 })
19 |   expect(div.text()).toBe('716')
20 | }
21 | 
22 | test('works with RxJS 5', () => {
23 |   setObservableConfig(rxjs5Config)
24 |   testTransform(props$ =>
25 |     props$.map(({ n }) =>
26 |       <div>
27 |         {n * 2}
28 |       </div>
29 |     )
30 |   )
31 | })
32 | 
33 | test('works with RxJS 4', () => {
34 |   setObservableConfig(rxjs4Config)
35 |   testTransform(props$ =>
36 |     props$.map(({ n }) =>
37 |       <div>
38 |         {n * 2}
39 |       </div>
40 |     )
41 |   )
42 | })
43 | 
44 | test('works with most', () => {
45 |   setObservableConfig(mostConfig)
46 |   testTransform(props$ =>
47 |     props$.map(({ n }) =>
48 |       <div>
49 |         {n * 2}
50 |       </div>
51 |     )
52 |   )
53 | })
54 | 
55 | test('works with xstream', () => {
56 |   setObservableConfig(xstreamConfig)
57 |   testTransform(props$ =>
58 |     props$.map(({ n }) =>
59 |       <div>
60 |         {n * 2}
61 |       </div>
62 |     )
63 |   )
64 | })
65 | 
66 | test('works with bacon', () => {
67 |   setObservableConfig(baconConfig)
68 |   testTransform(props$ =>
69 |     props$.map(({ n }) =>
70 |       <div>
71 |         {n * 2}
72 |       </div>
73 |     )
74 |   )
75 | })
76 | 
77 | test('works with kefir', () => {
78 |   setObservableConfig(kefirConfig)
79 |   testTransform(props$ =>
80 |     props$.map(({ n }) =>
81 |       <div>
82 |         {n * 2}
83 |       </div>
84 |     )
85 |   )
86 | })
87 | 
88 | test('works with flyd', () => {
89 |   setObservableConfig(flydConfig)
90 |   testTransform(props$ =>
91 |     props$.map(({ n }) =>
92 |       <div>
93 |         {n * 2}
94 |       </div>
95 |     )
96 |   )
97 | })
98 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/setPropTypes-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import PropTypes from 'prop-types'
 3 | import { setPropTypes } from '../'
 4 | 
 5 | test('setPropTypes sets a static property on the base component', () => {
 6 |   const BaseComponent = () => <div />
 7 |   const NewComponent = setPropTypes({ foo: PropTypes.object })(BaseComponent)
 8 | 
 9 |   expect(NewComponent.propTypes).toEqual({
10 |     foo: PropTypes.object,
11 |   })
12 | })
13 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/setStatic-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import PropTypes from 'prop-types'
 3 | import { setStatic } from '../'
 4 | 
 5 | test('setStatic sets a static property on the base component', () => {
 6 |   const BaseComponent = () => <div />
 7 |   const NewComponent = setStatic('propTypes', { foo: PropTypes.object })(
 8 |     BaseComponent
 9 |   )
10 | 
11 |   expect(NewComponent.propTypes).toEqual({
12 |     foo: PropTypes.object,
13 |   })
14 | })
15 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/shallowEqual-test.js:
--------------------------------------------------------------------------------
 1 | import { shallowEqual } from '../'
 2 | 
 3 | // Adapted from https://github.com/rackt/react-redux/blob/master/test/utils/shallowEqual.spec.js
 4 | test('shallowEqual returns true if arguments are equal, without comparing properties', () => {
 5 |   const throwOnAccess = {
 6 |     get foo() {
 7 |       throw new Error('Property was accessed')
 8 |     },
 9 |   }
10 |   expect(shallowEqual(throwOnAccess, throwOnAccess)).toBe(true)
11 | })
12 | 
13 | test('shallowEqual returns true if arguments fields are equal', () => {
14 |   expect(
15 |     shallowEqual({ a: 1, b: 2, c: undefined }, { a: 1, b: 2, c: undefined })
16 |   ).toBe(true)
17 | 
18 |   expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2, c: 3 })).toBe(true)
19 | 
20 |   const o = {}
21 |   expect(shallowEqual({ a: 1, b: 2, c: o }, { a: 1, b: 2, c: o })).toBe(true)
22 | })
23 | 
24 | test('shallowEqual returns false if either argument is null or undefined', () => {
25 |   expect(shallowEqual(null, { a: 1, b: 2 })).toBe(false)
26 |   expect(shallowEqual({ a: 1, b: 2 }, null)).toBe(false)
27 | })
28 | 
29 | test('shallowEqual returns false if first argument has too many keys', () => {
30 |   expect(shallowEqual({ a: 1, b: 2, c: 3 }, { a: 1, b: 2 })).toBe(false)
31 | })
32 | 
33 | test('shallowEqual returns false if second argument has too many keys', () => {
34 |   expect(shallowEqual({ a: 1, b: 2 }, { a: 1, b: 2, c: 3 })).toBe(false)
35 | })
36 | 
37 | test('shallowEqual returns false if arguments have different keys', () => {
38 |   expect(
39 |     shallowEqual({ a: 1, b: 2, c: undefined }, { a: 1, bb: 2, c: undefined })
40 |   ).toBe(false)
41 | })
42 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/shouldUpdate-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { shouldUpdate, compose, withState } from '../'
 5 | import { countRenders } from './utils'
 6 | 
 7 | test('shouldUpdate implements shouldComponentUpdate', () => {
 8 |   const component = sinon.spy(() => null)
 9 |   component.displayName = 'component'
10 | 
11 |   const initialTodos = ['eat', 'drink', 'sleep']
12 |   const Todos = compose(
13 |     withState('todos', 'updateTodos', initialTodos),
14 |     shouldUpdate((props, nextProps) => props.todos !== nextProps.todos),
15 |     countRenders
16 |   )(component)
17 | 
18 |   expect(Todos.displayName).toBe(
19 |     'withState(shouldUpdate(countRenders(component)))'
20 |   )
21 | 
22 |   mount(<Todos />)
23 |   const { updateTodos } = component.firstCall.args[0]
24 | 
25 |   expect(component.lastCall.args[0].todos).toBe(initialTodos)
26 |   expect(component.lastCall.args[0].renderCount).toBe(1)
27 | 
28 |   // Does not re-render
29 |   updateTodos(initialTodos)
30 |   expect(component.calledOnce).toBe(true)
31 | 
32 |   updateTodos(todos => todos.slice(0, -1))
33 |   expect(component.calledTwice).toBe(true)
34 |   expect(component.lastCall.args[0].todos).toEqual(['eat', 'drink'])
35 |   expect(component.lastCall.args[0].renderCount).toBe(2)
36 | })
37 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/toClass-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import PropTypes from 'prop-types'
 3 | import { mount } from 'enzyme'
 4 | import sinon from 'sinon'
 5 | import { toClass, withContext, compose } from '../'
 6 | 
 7 | test('toClass returns the base component if it is already a class', () => {
 8 |   class BaseComponent extends React.Component {
 9 |     render() {
10 |       return <div />
11 |     }
12 |   }
13 | 
14 |   const TestComponent = toClass(BaseComponent)
15 |   expect(TestComponent).toBe(BaseComponent)
16 | })
17 | 
18 | test('toClass copies propTypes, displayName, contextTypes and defaultProps from base component', () => {
19 |   const StatelessComponent = () => <div />
20 | 
21 |   StatelessComponent.displayName = 'Stateless'
22 |   StatelessComponent.propTypes = { foo: PropTypes.string }
23 |   StatelessComponent.contextTypes = { bar: PropTypes.object }
24 |   StatelessComponent.defaultProps = { foo: 'bar', fizz: 'buzz' }
25 | 
26 |   const TestComponent = toClass(StatelessComponent)
27 | 
28 |   expect(TestComponent.displayName).toBe('Stateless')
29 |   expect(TestComponent.propTypes).toEqual({ foo: PropTypes.string })
30 |   expect(TestComponent.contextTypes).toEqual({ bar: PropTypes.object })
31 |   expect(TestComponent.defaultProps).toEqual({ foo: 'bar', fizz: 'buzz' })
32 | })
33 | 
34 | test('toClass passes defaultProps correctly', () => {
35 |   const StatelessComponent = sinon.spy(() => null)
36 | 
37 |   StatelessComponent.displayName = 'Stateless'
38 |   StatelessComponent.propTypes = { foo: PropTypes.string }
39 |   StatelessComponent.contextTypes = { bar: PropTypes.object }
40 |   StatelessComponent.defaultProps = { foo: 'bar', fizz: 'buzz' }
41 | 
42 |   const TestComponent = toClass(StatelessComponent)
43 | 
44 |   mount(<TestComponent />)
45 |   expect(StatelessComponent.lastCall.args[0].foo).toBe('bar')
46 |   expect(StatelessComponent.lastCall.args[0].fizz).toBe('buzz')
47 | })
48 | 
49 | test('toClass passes context and props correctly', () => {
50 |   const store = {}
51 | 
52 |   class Provider extends React.Component {
53 |     static propTypes = {
54 |       children: PropTypes.node,
55 |     }
56 | 
57 |     render() {
58 |       return this.props.children
59 |     }
60 |   }
61 | 
62 |   Provider = compose(
63 |     withContext({ store: PropTypes.object }, props => ({ store: props.store }))
64 |   )(Provider)
65 | 
66 |   const StatelessComponent = (props, context) =>
67 |     <div data-props={props} data-context={context} />
68 | 
69 |   StatelessComponent.contextTypes = { store: PropTypes.object }
70 | 
71 |   const TestComponent = toClass(StatelessComponent)
72 | 
73 |   const div = mount(
74 |     <Provider store={store}>
75 |       <TestComponent fizz="fizzbuzz" />
76 |     </Provider>
77 |   ).find('div')
78 | 
79 |   expect(div.prop('data-props').fizz).toBe('fizzbuzz')
80 |   expect(div.prop('data-context').store).toBe(store)
81 | })
82 | 
83 | test('toClass works with strings (DOM components)', () => {
84 |   const Div = toClass('div')
85 |   const div = mount(<Div>Hello</Div>)
86 |   expect(div.html()).toBe('<div>Hello</div>')
87 | })
88 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/toRenderProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import { toRenderProps, defaultProps } from '../'
 4 | 
 5 | test('toRenderProps creates a component from defaultProps HOC', () => {
 6 |   const enhance = defaultProps({ foo: 'bar' })
 7 |   const Enhanced = toRenderProps(enhance)
 8 | 
 9 |   expect(Enhanced.displayName).toBe('defaultProps(RenderPropsComponent)')
10 | 
11 |   const h1 = mount(
12 |     <Enhanced>
13 |       {({ foo }) =>
14 |         <h1>
15 |           {foo}
16 |         </h1>}
17 |     </Enhanced>
18 |   ).find('h1')
19 | 
20 |   expect(h1.html()).toBe(`<h1>bar</h1>`)
21 | })
22 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_branch.js:
--------------------------------------------------------------------------------
  1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
  2 | /* @flow */
  3 | import React from 'react'
  4 | import {
  5 |   compose,
  6 |   withProps,
  7 |   branch,
  8 |   renderNothing,
  9 |   renderComponent,
 10 |   onlyUpdateForKeys,
 11 | } from '../..'
 12 | 
 13 | import type { HOC } from '../..'
 14 | 
 15 | type EnhancedCompProps = { eA: 1 }
 16 | 
 17 | const Comp = ({ eA }) =>
 18 |   <div>
 19 |     {(eA: number)}
 20 |     {
 21 |       // $ExpectError eA nor any nor string
 22 |       (eA: string)
 23 |     }
 24 |   </div>
 25 | 
 26 | const enhacer: HOC<*, EnhancedCompProps> = compose(
 27 |   branch(({ eA }) => eA === 1, renderNothing),
 28 |   withProps(props => ({
 29 |     eA: (props.eA: number),
 30 |     // $ExpectError eA nor any nor string
 31 |     eAErr: (props.eA: string),
 32 |   })),
 33 |   withProps(props => ({
 34 |     // $ExpectError property not found
 35 |     err: props.iMNotExists,
 36 |   }))
 37 | )
 38 | 
 39 | const enhacerLoading: HOC<*, EnhancedCompProps> = compose(
 40 |   branch(({ eA }) => eA === 1, renderComponent(p => <div>Loading</div>)),
 41 |   withProps(props => ({
 42 |     eA: (props.eA: number),
 43 |     // $ExpectError eA nor any nor string
 44 |     eAErr: (props.eA: string),
 45 |   }))
 46 | )
 47 | 
 48 | // can work with onlyUpdateForKeys
 49 | const enhacerUpdating: HOC<*, EnhancedCompProps> = compose(
 50 |   branch(({ eA }) => eA === 1, onlyUpdateForKeys(['eA'])),
 51 |   withProps(props => ({
 52 |     eA: (props.eA: number),
 53 |     // $ExpectError eA nor any nor string
 54 |     eAErr: (props.eA: string),
 55 |   }))
 56 | )
 57 | 
 58 | // can infer withProps type
 59 | const enhacerWithProps: HOC<*, EnhancedCompProps> = compose(
 60 |   branch(({ eA }) => eA === 1, withProps(props => ({ x: 1 }))),
 61 |   withProps(props => ({
 62 |     eA: (props.eA: number),
 63 |     // $ExpectError eA nor any nor string
 64 |     eAErr: (props.eA: string),
 65 |   }))
 66 | )
 67 | 
 68 | // can infer compose types
 69 | const enhacerWithCompose: HOC<*, EnhancedCompProps> = compose(
 70 |   branch(
 71 |     ({ eA }) => eA === 1,
 72 |     compose(
 73 |       withProps(props => {
 74 |         // $ExpectError eA nor any nor string
 75 |         ;(props.eA: string)
 76 | 
 77 |         return { x: 1 }
 78 |       }),
 79 |       withProps(props => ({ y: 2 }))
 80 |     )
 81 |   ),
 82 |   withProps(props => ({
 83 |     // $ExpectError eA nor any nor string
 84 |     eAErr: (props.eA: string),
 85 |     // $ExpectError x nor any nor string
 86 |     xErr: (props.x: string),
 87 |     // $ExpectError y nor any nor string
 88 |     yErr: (props.y: string),
 89 |   }))
 90 | )
 91 | 
 92 | const enhacerLeftRight: HOC<*, EnhancedCompProps> = compose(
 93 |   branch(
 94 |     ({ eA }) => eA === 1,
 95 |     renderComponent(p => <div>A</div>),
 96 |     renderComponent(p => <div>B</div>)
 97 |   ),
 98 |   withProps(props => ({
 99 |     // $ExpectError eA nor any nor string
100 |     eAErr: (props.eA: string),
101 |     // $ExpectError x nor any nor string
102 |     xErr: (props.x: string),
103 |     // $ExpectError y nor any nor string
104 |     yErr: (props.y: string),
105 |   }))
106 | )
107 | 
108 | /*
109 | Wrong types of left right, this will cause an infinite recursion
110 | 
111 | const enhacerLeftRight2: HOC<*, EnhancedCompProps> = compose(
112 |   branch(
113 |     ({ eA }) => eA === 1,
114 |     renderComponent(p => <div>A</div>),
115 |     withProps(props => ({ y: 2 }))
116 |   )
117 | );
118 | */
119 | 
120 | const EnhancedComponent = enhacer(Comp)
121 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_classBasedEnhancer.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | import * as React from 'react'
 3 | import { compose, withProps } from '../..'
 4 | import type { HOC } from '../..'
 5 | 
 6 | // Example of very dirty written fetcher enhancer
 7 | function fetcher<Response: {}, Base: {}>(
 8 |   dest: string,
 9 |   nullRespType: ?Response
10 | ): HOC<{ ...$Exact<Base>, data?: Response }, Base> {
11 |   return BaseComponent =>
12 |     class Fetcher extends React.Component<Base, { data?: Response }> {
13 |       state = { data: undefined }
14 |       componentDidMount() {
15 |         fetch(dest)
16 |           .then(r => r.json())
17 |           .then((data: Response) => this.setState({ data }))
18 |       }
19 |       render() {
20 |         return <BaseComponent {...this.props} {...this.state} />
21 |       }
22 |     }
23 | }
24 | // Enhanced Component props type
25 | type EnhancedCompProps = { b: number }
26 | // response type
27 | type FetchResponseType = { hello: string, world: number }
28 | 
29 | // Now you can use it, let's check
30 | const enhancer: HOC<*, EnhancedCompProps> = compose(
31 |   // pass response type via typed null
32 |   fetcher('http://endpoint.ep', (null: ?FetchResponseType)),
33 |   // see here fully typed data
34 |   withProps(({ data }) => {
35 |     if (data !== undefined) {
36 |       return {
37 |         h: (data.hello: string),
38 |         // $ExpectError
39 |         hE: (data.hello: number),
40 |       }
41 |     }
42 | 
43 |     return {}
44 |   })
45 | )
46 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_componentFromStream.js:
--------------------------------------------------------------------------------
 1 | // @flow
 2 | import React from 'react'
 3 | import { componentFromStream } from '../..'
 4 | 
 5 | // $ExpectError
 6 | componentFromStream(1)
 7 | 
 8 | // $ExpectError
 9 | const result1: number = componentFromStream(() => React.createElement('div'))
10 | 
11 | componentFromStream(a => a)
12 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_createEventHandler.js:
--------------------------------------------------------------------------------
 1 | // @flow
 2 | import React from 'react'
 3 | import { createEventHandler } from '../..'
 4 | 
 5 | // $ExpectError
 6 | createEventHandler(1)
 7 | 
 8 | // $ExpectError
 9 | const result1: number = createEventHandler()
10 | 
11 | // $ExpectError
12 | const { stream1, handler1 } = createEventHandler()
13 | 
14 | const { stream, handler } = createEventHandler()
15 | 
16 | handler()
17 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_defaultProps.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, defaultProps } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ hello, eA }) =>
11 |   <div>
12 |     {(hello: string)}
13 |     {(eA: number)}
14 |     {
15 |       // $ExpectError eA nor any nor string
16 |       (eA: string)
17 |     }
18 |     {
19 |       // $ExpectError hello nor any nor number
20 |       (hello: number)
21 |     }
22 |   </div>
23 | 
24 | const enhacer: HOC<*, EnhancedCompProps> = compose(
25 |   defaultProps({
26 |     hello: 'world',
27 |   }),
28 |   withProps(props => ({
29 |     hello: (props.hello: string),
30 |     eA: (props.eA: number),
31 |     // $ExpectError hello nor any nor number
32 |     helloErr: (props.hello: number),
33 |     // $ExpectError eA nor any nor string
34 |     eAErr: (props.eA: string),
35 |   })),
36 |   withProps(props => ({
37 |     // $ExpectError property not found
38 |     err: props.iMNotExists,
39 |   }))
40 | )
41 | 
42 | const EnhancedComponent = enhacer(Comp)
43 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_fromRenderProps.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | import React from 'react'
 3 | import { compose, fromRenderProps } from '../..'
 4 | 
 5 | import type { HOC } from '../..'
 6 | 
 7 | const RenderPropsComponent1 = ({ children }) => children({ theme: 'dark' })
 8 | const RenderPropsComponent2 = ({ render }) => render({ i18n: 'zh-TW' })
 9 | const RenderPropsComponent3 = ({ children }) =>
10 |   children({ theme: 'dark' }, { data: 'data' })
11 | 
12 | type EnhancedCompProps = {||}
13 | 
14 | const Comp = ({ i18n, theme, data }) =>
15 |   <div>
16 |     {i18n}
17 |     {theme}
18 |     {data}
19 |     {
20 |       // $ExpectError
21 |       (i18n: number)
22 |     }
23 |     {
24 |       // $ExpectError
25 |       (theme: number)
26 |     }
27 |     {
28 |       // $ExpectError
29 |       (data: number)
30 |     }
31 |   </div>
32 | 
33 | const enhancer: HOC<*, EnhancedCompProps> = compose(
34 |   fromRenderProps(RenderPropsComponent1, props => ({
35 |     theme: props.theme,
36 |     // $ExpectError property not found
37 |     err: props.iMNotExists,
38 |   })),
39 |   fromRenderProps(
40 |     RenderPropsComponent2,
41 |     props => ({
42 |       i18n: props.i18n,
43 |       // $ExpectError property not found
44 |       err: props.iMNotExists,
45 |     }),
46 |     'render'
47 |   ),
48 |   fromRenderProps(RenderPropsComponent3, (props, data) => ({
49 |     theme: props.theme,
50 |     data: data.data,
51 |     // $ExpectError property not found
52 |     err: data.iMNotExists,
53 |   }))
54 | )
55 | 
56 | const EnhancedComponent = enhancer(Comp)
57 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_functionalEnhancer.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | 
 3 | import * as React from 'react'
 4 | import { compose, withProps } from '../..'
 5 | import type { HOC } from '../..'
 6 | 
 7 | function mapProps<BaseProps: {}, EnhancedProps>(
 8 |   mapperFn: EnhancedProps => BaseProps
 9 | ): (React.ComponentType<BaseProps>) => React.ComponentType<EnhancedProps> {
10 |   return Component => props => <Component {...mapperFn(props)} />
11 | }
12 | 
13 | type EnhancedProps = { hello: string }
14 | 
15 | const baseComponent = ({ hello, len }) =>
16 |   <div>
17 |     {(hello: string)}
18 | 
19 |     {
20 |       // $ExpectError
21 |       (hello: number)
22 |     }
23 | 
24 |     {(len: number)}
25 | 
26 |     {
27 |       // $ExpectError
28 |       (len: string)
29 |     }
30 |   </div>
31 | 
32 | const enhancer: HOC<*, EnhancedProps> = compose(
33 |   mapProps(({ hello }) => ({
34 |     hello: `${hello} world`,
35 |     len: hello.length,
36 |   })),
37 |   withProps(props => ({
38 |     helloAndLen: `${props.hello} ${props.len}`,
39 |     // $ExpectError
40 |     lE: (props.len: string),
41 |   }))
42 | )
43 | 
44 | enhancer(baseComponent)
45 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_getContext.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, getContext } from '../..'
 5 | // import PropTypes from 'prop-types'
 6 | import type { HOC } from '../..'
 7 | 
 8 | const PropTypes = {
 9 |   number: () => {},
10 |   string: () => {},
11 | }
12 | 
13 | type EnhancedCompProps = { eA: 1 }
14 | 
15 | const Comp = ({ eA }) =>
16 |   <div>
17 |     {(eA: number)}
18 |     {
19 |       // $ExpectError eA nor any nor string
20 |       (eA: string)
21 |     }
22 |   </div>
23 | 
24 | const enhacer: HOC<*, EnhancedCompProps> = compose(
25 |   getContext({
26 |     // as an idea is to use a hack like this
27 |     // so we can test all such types
28 |     color: ((PropTypes.string: any): string),
29 |     num: ((PropTypes.number: any): number),
30 |   }),
31 |   withProps(props => ({
32 |     eA: (props.eA: number),
33 |     color: (props.color: string),
34 |     // $ExpectError eA nor any nor string
35 |     eAErr: (props.eA: string),
36 |     // $ExpectError color nor any nor number
37 |     colorErr: (props.color: number),
38 |   })),
39 |   withProps(props => ({
40 |     // $ExpectError property not found
41 |     err: props.iMNotExists,
42 |   }))
43 | )
44 | 
45 | const EnhancedComponent = enhacer(Comp)
46 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_mapProps.js:
--------------------------------------------------------------------------------
 1 | /* globals */
 2 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 3 | /* @flow */
 4 | import React from 'react'
 5 | import { compose, mapProps, withProps } from '../..'
 6 | 
 7 | import type { HOC } from '../..'
 8 | 
 9 | type EnhancedCompProps = { eA: 1 }
10 | 
11 | const Comp = ({ a }) =>
12 |   <div>
13 |     {(a: string)}
14 |     {
15 |       // $ExpectError
16 |       (a: number)
17 |     }
18 |   </div>
19 | 
20 | const enhacer: HOC<*, EnhancedCompProps> = compose(
21 |   mapProps(p => ({
22 |     a: '1',
23 |   })),
24 |   // If you need to to detect erros after a mapProps HOC
25 |   // you need to explicitly set Types for all HOCs below
26 |   // seems like this https://github.com/facebook/flow/issues/4342 issue
27 |   withProps(props => ({
28 |     a: (props.a: string),
29 |     // $ExpectError but not
30 |     e: Math.round(props.a),
31 |   }))
32 | )
33 | 
34 | enhacer(Comp)
35 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_mapPropsStream.js:
--------------------------------------------------------------------------------
 1 | /* globals */
 2 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 3 | /* @flow */
 4 | import React from 'react'
 5 | // import { Observable } from 'rxjs'
 6 | import { compose, mapProps, withProps, mapPropsStream } from '../..'
 7 | 
 8 | import type { HOC } from '../..'
 9 | 
10 | type EnhancedCompProps = { eA: 1 }
11 | 
12 | const Observable = {
13 |   of: (a: Object) => Object,
14 | }
15 | 
16 | const Comp = ({ a }) =>
17 |   <div>
18 |     {(a: string)}
19 |     {
20 |       // $ExpectError
21 |       (a: number)
22 |     }
23 |   </div>
24 | 
25 | const enhacer: HOC<*, EnhancedCompProps> = compose(
26 |   (mapPropsStream((props$: Observable<EnhancedCompProps>) =>
27 |     Observable.of({ a: 1, b: '1' })
28 |   ): HOC<{ a: string, b: string }, *>),
29 |   // If you need to to detect erros after a mapPropsStream HOC (the same for mapProps and some others)
30 |   // you need to explicitly set Types for all HOCs below
31 |   // but because of this https://github.com/facebook/flow/issues/4342
32 |   withProps(props => ({
33 |     a: (props.a: string),
34 |     // $ExpectError but not
35 |     e: Math.round(props.a),
36 |   }))
37 | )
38 | 
39 | enhacer(Comp)
40 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_onlyUpdateForKeys.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, onlyUpdateForKeys } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   onlyUpdateForKeys(['eA']),
21 |   withProps(props => ({
22 |     eA: (props.eA: number),
23 |     // $ExpectError eA nor any nor string
24 |     eAErr: (props.eA: string),
25 |   })),
26 |   withProps(props => ({
27 |     // $ExpectError property not found
28 |     err: props.iMNotExists,
29 |   }))
30 | )
31 | 
32 | const enhacerErr: HOC<*, EnhancedCompProps> = compose(
33 |   // $ExpectError property not found
34 |   onlyUpdateForKeys(['eB'])
35 | )
36 | 
37 | const EnhancedComponent = enhacer(Comp)
38 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_onlyUpdateForPropTypes.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, onlyUpdateForPropTypes } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   onlyUpdateForPropTypes,
21 |   withProps(props => ({
22 |     eA: (props.eA: number),
23 |     // $ExpectError eA nor any nor string
24 |     eAErr: (props.eA: string),
25 |   })),
26 |   withProps(props => ({
27 |     // $ExpectError property not found
28 |     err: props.iMNotExists,
29 |   }))
30 | )
31 | 
32 | const EnhancedComponent = enhacer(Comp)
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_pure.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, pure } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   pure,
21 |   withProps(props => ({
22 |     eA: (props.eA: number),
23 |     // $ExpectError eA nor any nor string
24 |     eAErr: (props.eA: string),
25 |   })),
26 |   withProps(props => ({
27 |     // $ExpectError property not found
28 |     err: props.iMNotExists,
29 |   }))
30 | )
31 | 
32 | const EnhancedComponent = enhacer(Comp)
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_shouldUpdate.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, shouldUpdate } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   shouldUpdate((props, nextProps) => {
21 |     // $ExpectError eA nor any nor string
22 |     ;(props.eA: string)
23 |     // $ExpectError eA nor any nor string
24 |     ;(nextProps.eA: string)
25 | 
26 |     return props.eA === nextProps.eA
27 |   }),
28 |   withProps(props => ({
29 |     eA: (props.eA: number),
30 |     // $ExpectError eA nor any nor string
31 |     eAErr: (props.eA: string),
32 |   })),
33 |   withProps(props => ({
34 |     // $ExpectError property not found
35 |     err: props.iMNotExists,
36 |   }))
37 | )
38 | 
39 | const enhacerErr: HOC<*, EnhancedCompProps> = compose(
40 |   shouldUpdate(() => {
41 |     // $ExpectError must be boolean
42 |     return 1
43 |   })
44 | )
45 | 
46 | const EnhancedComponent = enhacer(Comp)
47 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_statics.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import {
 5 |   compose,
 6 |   withProps,
 7 |   setStatic,
 8 |   setPropTypes,
 9 |   setDisplayName,
10 | } from '../..'
11 | // import PropTypes from 'prop-types'
12 | import type { HOC } from '../..'
13 | 
14 | const PropTypes = {
15 |   string: () => {},
16 | }
17 | 
18 | type EnhancedCompProps = { eA: 1 }
19 | 
20 | const Comp = ({ eA }) =>
21 |   <div>
22 |     {(eA: number)}
23 |     {
24 |       // $ExpectError eA nor any nor string
25 |       (eA: string)
26 |     }
27 |   </div>
28 | 
29 | const enhacer: HOC<*, EnhancedCompProps> = compose(
30 |   setStatic('hello', 'world'),
31 |   setPropTypes({
32 |     a: PropTypes.string,
33 |   }),
34 |   setDisplayName('hello'),
35 |   withProps(props => ({
36 |     eA: (props.eA: number),
37 |     // $ExpectError eA nor any nor string
38 |     eAErr: (props.eA: string),
39 |   })),
40 |   withProps(props => ({
41 |     // $ExpectError property not found
42 |     err: props.iMNotExists,
43 |   }))
44 | )
45 | 
46 | // $ExpectError name is string
47 | setDisplayName(1)
48 | 
49 | // $ExpectError propTypes is object
50 | setPropTypes(1)
51 | 
52 | // $ExpectError name is string
53 | setStatic(1, 'world')
54 | 
55 | const EnhancedComponent = enhacer(Comp)
56 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_toClass.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, toClass } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   toClass,
21 |   withProps(props => ({
22 |     eA: (props.eA: number),
23 |     // $ExpectError eA nor any nor string
24 |     eAErr: (props.eA: string),
25 |   })),
26 |   withProps(props => ({
27 |     // $ExpectError property not found
28 |     err: props.iMNotExists,
29 |   }))
30 | )
31 | 
32 | const EnhancedComponent = enhacer(Comp)
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_toRenderProps.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | 
 3 | import * as React from 'react'
 4 | import { compose, withProps, toRenderProps, withHandlers } from '../..'
 5 | import type { HOC } from '../..'
 6 | 
 7 | const enhance: HOC<*, {| +x: number |}> = compose(
 8 |   withProps(props => ({
 9 |     y: props.x + 1,
10 |   })),
11 |   withHandlers({
12 |     sayHello: ({ y }) => () => {
13 |       console.log('Hello', y)
14 |     },
15 |   })
16 | )
17 | 
18 | const WithProps = toRenderProps(enhance)
19 | 
20 | const Comp = () =>
21 |   <WithProps x={1}>
22 |     {({ y, sayHello }) =>
23 |       <div onClick={() => sayHello()}>
24 |         {y}
25 |       </div>}
26 |   </WithProps>
27 | 
28 | const Comp2 = () =>
29 |   // $ExpectError
30 |   <WithProps x={'1'}>
31 |     {({ y, sayHello }) =>
32 |       <div onClick={() => sayHello()}>
33 |         {y}
34 |       </div>}
35 |   </WithProps>
36 | 
37 | // $ExpectError cannot create `WithProps` element because property `children` is missing in props
38 | const Comp3 = () => <WithProps x={1} />
39 | 
40 | const Comp4 = () =>
41 |   <WithProps x={1}>
42 |     {({ y, sayHello }) =>
43 |       <div
44 |         onClick={() => {
45 |           ;(sayHello: () => void)
46 | 
47 |           // $ExpectError
48 |           ;(sayHello: number)
49 |           sayHello()
50 |         }}
51 |       >
52 |         {(y: number)}
53 |         {
54 |           // $ExpectError
55 |           (y: string)
56 |         }
57 |       </div>}
58 |   </WithProps>
59 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_utils.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | 
 4 | import React from 'react'
 5 | import { compose, withProps, hoistStatics } from '../..'
 6 | 
 7 | import type { HOC } from '../..'
 8 | 
 9 | type EnhancedCompProps = { a: number }
10 | 
11 | const A = ({ a, b }) =>
12 |   <div>
13 |     {a}
14 |     {(b: string)}
15 |     {
16 |       // $ExpectError
17 |       (a: string)
18 |     }
19 |     {
20 |       // $ExpectError
21 |       (b: number)
22 |     }
23 |   </div>
24 | 
25 | A.displayName = 'HELLO WORLD'
26 | 
27 | const enhacer: HOC<*, EnhancedCompProps> = compose(
28 |   withProps(({ a }) => ({
29 |     hello: a,
30 |     b: `${a}`,
31 |   }))
32 | )
33 | 
34 | hoistStatics(enhacer)(A)
35 | 
36 | // I see no reason to test other utils, please add if you think otherwise
37 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_voodoo.js:
--------------------------------------------------------------------------------
  1 | /* globals $Exact, $PropertyType */
  2 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
  3 | /* @flow */
  4 | import React from 'react'
  5 | import {
  6 |   compose,
  7 |   withProps,
  8 |   flattenProp,
  9 |   renameProp,
 10 |   renameProps,
 11 |   withState,
 12 | } from '../..'
 13 | 
 14 | import type { HOC } from '../..'
 15 | 
 16 | type EnhancedCompProps = {
 17 |   eA: number,
 18 |   obj: { objPropA: string, objPropB: number },
 19 | }
 20 | 
 21 | const Comp = ({ eA, objPropA }) =>
 22 |   <div>
 23 |     {(eA: number)}
 24 |     {(objPropA: string)}
 25 |     {
 26 |       // $ExpectError eA nor any nor string
 27 |       (eA: string)
 28 |     }
 29 |     {
 30 |       // $ExpectError eA nor any nor string
 31 |       (objPropA: number)
 32 |     }
 33 |   </div>
 34 | 
 35 | const Comp2 = ({ eA, objPropA }) =>
 36 |   <div>
 37 |     {/* hack to preview types */}
 38 |     {/* :: eA, objPropA */}
 39 |   </div>
 40 | 
 41 | const flattenEnhacer: HOC<*, EnhancedCompProps> = compose(
 42 |   (flattenProp('obj'): HOC<
 43 |     {
 44 |       ...$Exact<EnhancedCompProps>,
 45 |       ...$Exact<$PropertyType<EnhancedCompProps, 'obj'>>,
 46 |     },
 47 |     EnhancedCompProps
 48 |   >),
 49 |   withProps(props => ({
 50 |     eA: (props.eA: number),
 51 |     // $ExpectError
 52 |     eB: (props.eA: string),
 53 |   }))
 54 | )
 55 | 
 56 | const EnhancedComponent = flattenEnhacer(Comp)
 57 | const EnhancedComponent2 = flattenEnhacer(Comp2)
 58 | 
 59 | // renameEnhacer voodoo (you don't need it, use withProps instead)
 60 | const RenameComp = ({ eA, objNew, obj }) =>
 61 |   <div>
 62 |     {(eA: number)}
 63 | 
 64 |     {
 65 |       // objNew has a type we need
 66 |       (objNew.objPropA: string)
 67 |     }
 68 |     {
 69 |       // $ExpectError eA nor any nor string
 70 |       (eA: string)
 71 |     }
 72 |     {
 73 |       // $ExpectError eA nor any nor string
 74 |       (objNew.objPropA: number)
 75 |     }
 76 |     {
 77 |       // obj is null
 78 |       (obj: null)
 79 |     }
 80 |     {
 81 |       // $ExpectError eA nor any nor string
 82 |       (obj: string)
 83 |     }
 84 |   </div>
 85 | 
 86 | const renameEnhacer: HOC<*, EnhancedCompProps> = compose(
 87 |   (renameProp('obj', 'objNew'): HOC<
 88 |     {
 89 |       ...$Exact<EnhancedCompProps>,
 90 |       ...$Exact<{ obj: null }>,
 91 |       // $PropertyType does not work here
 92 |       ...$Exact<{ objNew: { objPropA: string, objPropB: number } }>,
 93 |     },
 94 |     EnhancedCompProps
 95 |   >),
 96 |   withProps(props => ({
 97 |     eA: (props.eA: number),
 98 |     // $ExpectError
 99 |     eB: (props.eA: string),
100 |   }))
101 | )
102 | 
103 | renameEnhacer(RenameComp)
104 | 
105 | const renamePropsEnhacer: HOC<*, EnhancedCompProps> = compose(
106 |   (renameProps({ obj: 'objNew' }): HOC<
107 |     {
108 |       ...$Exact<EnhancedCompProps>,
109 |       // --- repeat for every key ---
110 |       ...$Exact<{ obj: null }>,
111 |       // $PropertyType does not work here
112 |       ...$Exact<{ objNew: { objPropA: string, objPropB: number } }>,
113 |     },
114 |     EnhancedCompProps
115 |   >),
116 |   withProps(props => ({
117 |     eA: (props.eA: number),
118 |     // $ExpectError
119 |     eB: (props.eA: string),
120 |   }))
121 | )
122 | 
123 | // use withStateHandlers instead
124 | const withStateEnhancer: HOC<*, EnhancedCompProps> = compose(
125 |   (withState('a', 'setA', { hello: 'world' }): HOC<
126 |     {
127 |       ...$Exact<EnhancedCompProps>,
128 |       ...$Exact<{ a: { hello: string }, setA: (a: { hello: string }) => void }>,
129 |     },
130 |     EnhancedCompProps
131 |   >),
132 |   withProps(props => ({
133 |     eA: (props.eA: number),
134 |     // $ExpectError
135 |     eB: (props.eA: string),
136 |   }))
137 | )
138 | 
139 | // withReducer see withState above
140 | // lifecycle see  withState above
141 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_withContext.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, withContext } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ eA }) =>
11 |   <div>
12 |     {(eA: number)}
13 |     {
14 |       // $ExpectError eA nor any nor string
15 |       (eA: string)
16 |     }
17 |   </div>
18 | 
19 | const enhacer: HOC<*, EnhancedCompProps> = compose(
20 |   withContext({}, props => {
21 |     // $ExpectError eA nor any nor string
22 |     ;(props.eA: string)
23 |     return {}
24 |   }),
25 |   withProps(props => ({
26 |     eA: (props.eA: number),
27 |     // $ExpectError eA nor any nor string
28 |     eAErr: (props.eA: string),
29 |   })),
30 |   withProps(props => ({
31 |     // $ExpectError property not found
32 |     err: props.iMNotExists,
33 |   }))
34 | )
35 | 
36 | const EnhancedComponent = enhacer(Comp)
37 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_withHandlers.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | 
 4 | import React from 'react'
 5 | import { compose, withProps, withHandlers } from '../..'
 6 | 
 7 | import type { HOC } from '../..'
 8 | 
 9 | type EnhancedCompProps = {
10 |   value: number,
11 |   onChange: (value: number) => void,
12 |   onOtherChange: (value: { id: string }) => void,
13 | }
14 | 
15 | const enhancer: HOC<*, EnhancedCompProps> = compose(
16 |   withHandlers({
17 |     onValueChange: props => value => {
18 |       props.onChange(value)
19 |       return true
20 |     },
21 |     onOtherValueChange: props => value => {
22 |       props.onOtherChange(value)
23 |       return true
24 |     },
25 |   }),
26 |   // here props itself will not be infered without explicit handler args types
27 |   withProps(props => ({
28 |     valueClone: (props.value: number),
29 |     resType: (props.onValueChange(0): boolean),
30 |     ee: props.onOtherValueChange({ id: 'aa' }),
31 | 
32 |     // $ExpectError result is not any or number
33 |     resTypeErr: (props.onValueChange(0): number),
34 |     // $ExpectError property not found
35 |     err: props.iMNotExists,
36 |   }))
37 | )
38 | 
39 | // check that factory init works as expected
40 | const enhancer2: HOC<*, EnhancedCompProps> = compose(
41 |   withHandlers(() => ({
42 |     onValueChange: props => value => {
43 |       props.onChange(value)
44 |       return true
45 |     },
46 |   })),
47 |   // here props itself will not be infered without explicit handler args types
48 |   withProps(props => ({
49 |     valueClone: (props.value: number),
50 |     resType: (props.onValueChange(0): boolean),
51 | 
52 |     // $ExpectError result is not any or number
53 |     resTypeErr: (props.onValueChange(0): number),
54 |     // $ExpectError property not found
55 |     err: props.iMNotExists,
56 |   }))
57 | )
58 | 
59 | const BaseComp = ({ value, onValueChange }) =>
60 |   <div
61 |     onClick={() => {
62 |       const res = onValueChange(1)
63 |       ;(res: boolean)
64 |       // $ExpectError
65 |       ;(res: number)
66 |     }}
67 |   >
68 |     {(value: number)}
69 |     {
70 |       // $ExpectError value is not any or string
71 |       (value: string)
72 |     }
73 |   </div>
74 | 
75 | const Enhanced = enhancer(BaseComp)
76 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_withProps.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { a: string, b: number }
 9 | 
10 | const Comp = ({ hello, b }) =>
11 |   <div>
12 |     {hello}
13 |     {b}
14 |     {
15 |       // $ExpectError
16 |       (b: number)
17 |     }
18 |     {
19 |       // $ExpectError
20 |       (hello: number)
21 |     }
22 |   </div>
23 | 
24 | const enhancer: HOC<*, EnhancedCompProps> = compose(
25 |   withProps(({ a, b }) => ({
26 |     hello: a,
27 |     b: `${b}`,
28 |   })),
29 |   withProps(({ b, hello }) => ({
30 |     hello: (hello: string),
31 |     // $ExpectError (This type is incompatible with number)
32 |     c: (b: number),
33 |   })),
34 |   // check non functional form of with props
35 |   withProps({
36 |     d: 'hi',
37 |   }),
38 |   withProps(props => ({
39 |     a: (props.a: string),
40 |     d: (props.d: string),
41 |     // $ExpectError property not found
42 |     err: props.iMNotExists,
43 |     // $ExpectError a not a number and not any
44 |     aErr: (props.a: number),
45 |     // $ExpectError d not a number and not any
46 |     dErr: (props.d: number),
47 |   }))
48 | )
49 | 
50 | const EnhancedComponent = enhancer(Comp)
51 | ;<EnhancedComponent a={'1'} b={1} />
52 | 
53 | // $ExpectError
54 | ;<EnhancedComponent a={'1'} b={'1'} />
55 | 
56 | // $ExpectError
57 | ;<EnhancedComponent a={'1'} />
58 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_withPropsOnChange.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-unused-vars, no-unused-expressions, arrow-body-style */
 2 | /* @flow */
 3 | import React from 'react'
 4 | import { compose, withProps, withPropsOnChange } from '../..'
 5 | 
 6 | import type { HOC } from '../..'
 7 | 
 8 | type EnhancedCompProps = { eA: 1 }
 9 | 
10 | const Comp = ({ hello, eA }) =>
11 |   <div>
12 |     {(hello: string)}
13 |     {(eA: number)}
14 |     {
15 |       // $ExpectError eA nor any nor string
16 |       (eA: string)
17 |     }
18 |     {
19 |       // $ExpectError hello nor any nor number
20 |       (hello: number)
21 |     }
22 |   </div>
23 | 
24 | const enhacer: HOC<*, EnhancedCompProps> = compose(
25 |   withPropsOnChange(['eA'], ({ eA }) => ({
26 |     hello: `${eA}`,
27 |   })),
28 |   withProps(props => ({
29 |     hello: (props.hello: string),
30 |     eA: (props.eA: number),
31 |     // $ExpectError hello nor any nor number
32 |     helloErr: (props.hello: number),
33 |     // $ExpectError eA nor any nor string
34 |     eAErr: (props.eA: string),
35 |   })),
36 |   withProps(props => ({
37 |     // $ExpectError property not found
38 |     err: props.iMNotExists,
39 |   }))
40 | )
41 | 
42 | const enhacerFn: HOC<*, EnhancedCompProps> = compose(
43 |   withPropsOnChange(
44 |     (props, nextProps) => {
45 |       ;(props.eA: number)
46 |       ;(nextProps.eA: number)
47 |       // $ExpectError eA nor any nor string
48 |       ;(props.eA: string)
49 |       // $ExpectError eA nor any nor string
50 |       ;(nextProps.eA: string)
51 |       return props.eA === props.eA
52 |     },
53 |     ({ eA }) => ({
54 |       hello: `${eA}`,
55 |     })
56 |   ),
57 |   withProps(props => ({
58 |     hello: (props.hello: string),
59 |     eA: (props.eA: number),
60 |     // $ExpectError hello nor any nor number
61 |     helloErr: (props.hello: number),
62 |     // $ExpectError eA nor any nor string
63 |     eAErr: (props.eA: string),
64 |   }))
65 | )
66 | 
67 | const enhacerErr: HOC<*, EnhancedCompProps> = compose(
68 |   // $ExpectError property property `eB` not found
69 |   withPropsOnChange(['eA', 'eB'], ({ eA }) => ({
70 |     hello: `${eA}`,
71 |   }))
72 | )
73 | 
74 | const enhacerFnErr: HOC<*, EnhancedCompProps> = compose(
75 |   withPropsOnChange(
76 |     (props, nextProps) => {
77 |       // $ExpectError boolean
78 |       return 1
79 |     },
80 |     ({ eA }) => ({
81 |       hello: `${eA}`,
82 |     })
83 |   ),
84 |   withProps(props => ({
85 |     hello: (props.hello: string),
86 |     eA: (props.eA: number),
87 |   }))
88 | )
89 | 
90 | const EnhancedComponent = enhacer(Comp)
91 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/types/test_withStateHandlers.js:
--------------------------------------------------------------------------------
  1 | /* eslint-disable no-unused-vars, no-unused-expressions */
  2 | /* @flow */
  3 | 
  4 | import React from 'react'
  5 | import { compose, withProps, withStateHandlers } from '../..'
  6 | 
  7 | import type { HOC } from '../..'
  8 | 
  9 | type EnhancedCompProps = {
 10 |   initialCounter: number,
 11 | }
 12 | 
 13 | const enhancer: HOC<*, EnhancedCompProps> = compose(
 14 |   withStateHandlers(
 15 |     { value: 'Hello', letIt: 'be', obj: ({}: { [key: string]: string }) },
 16 |     {
 17 |       // we need to set argument type so inference will work good
 18 |       setValue: (state, props) => (value: string) => ({
 19 |         value,
 20 |       }),
 21 |       changeValue: (state, props) => (
 22 |         { i, j }: { i: number, j: string },
 23 |         k: number
 24 |       ) => ({
 25 |         value: `world again ${i} ${j}`,
 26 |       }),
 27 |       inform: state => () => {},
 28 |     }
 29 |   ),
 30 |   // here props itself will not be infered without explicit handler args types
 31 |   withProps(props => ({
 32 |     hi: (props.value: string),
 33 |     ic: (props.initialCounter: number),
 34 |     cc: (props.obj.a: string),
 35 |     // $ExpectError value not a number or any
 36 |     ehi: (props.value: number),
 37 |     // $ExpectError not a number
 38 |     cn: (props.obj.a: number),
 39 |     // $ExpectError property not found (to detect that props is not any)
 40 |     err: props.iMNotExists,
 41 |     // $ExpectError initialCounter not any nor string
 42 |     icErr: (props.initialCounter: string),
 43 |   }))
 44 | )
 45 | 
 46 | const enhancerFuncInit: HOC<*, EnhancedCompProps> = compose(
 47 |   withStateHandlers(
 48 |     props => ({
 49 |       counter: props.initialCounter,
 50 |     }),
 51 |     {
 52 |       // it's better to set argument type with named props, easier to find an error
 53 |       // if you call it with wrong arguments
 54 |       incCounter: ({ counter }) => ({ value }: { value: number }) => ({
 55 |         counter: counter + value,
 56 |       }),
 57 |     }
 58 |   ),
 59 |   withProps(props => ({
 60 |     // check that result is void
 61 |     iVal: (props.incCounter({ value: 1 }): void),
 62 |     // $ExpectError check that incCounter is not any
 63 |     iVal2: (props.incCounter({ value: 1 }): number),
 64 |     // $ExpectError property not found
 65 |     err: props.iMNotExists,
 66 |   }))
 67 | )
 68 | 
 69 | const BaseComponent = ({ hi, changeValue, setValue }) =>
 70 |   <div
 71 |     onClick={() => {
 72 |       // check that supports few arguments
 73 |       const x = changeValue({ i: 1, j: '1' }, 1)
 74 | 
 75 |       setValue('ww')
 76 |       // Check that result is void
 77 |       ;(x: void)
 78 | 
 79 |       // $ExpectError check that x is not any
 80 |       ;(x: {})
 81 | 
 82 |       // Check hi
 83 |       ;(hi: string)
 84 | 
 85 |       // $ExpectError check that hi is not any
 86 |       ;(hi: number)
 87 |     }}
 88 |   >
 89 |     {hi}
 90 |   </div>
 91 | 
 92 | const EnhancedComponent = enhancer(BaseComponent)
 93 | ;<EnhancedComponent initialCounter={0} />
 94 | 
 95 | // Without $Exact<State> this will cause error
 96 | const enhancer3: HOC<*, EnhancedCompProps> = compose(
 97 |   withStateHandlers(
 98 |     ({
 99 |       mapA2B: {},
100 |     }: { mapA2B: { [key: string]: string } }),
101 |     {}
102 |   ),
103 |   withProps(props => ({
104 |     // check that result is void
105 |     iVal: props.mapA2B.c,
106 |   }))
107 | )
108 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/utils.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import setDisplayName from '../setDisplayName'
 3 | import wrapDisplayName from '../wrapDisplayName'
 4 | 
 5 | export const countRenders = BaseComponent => {
 6 |   class CountRenders extends React.Component {
 7 |     renderCount = 0
 8 | 
 9 |     render() {
10 |       this.renderCount += 1
11 |       return <BaseComponent renderCount={this.renderCount} {...this.props} />
12 |     }
13 |   }
14 | 
15 |   return setDisplayName(wrapDisplayName(BaseComponent, 'countRenders'))(
16 |     CountRenders
17 |   )
18 | }
19 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withContext-test.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable react/require-default-props */
 2 | import React, { Component } from 'react'
 3 | import PropTypes from 'prop-types'
 4 | import { mount } from 'enzyme'
 5 | import sinon from 'sinon'
 6 | import { withContext, getContext, compose, mapProps } from '../'
 7 | 
 8 | test('withContext + getContext adds to and grabs from context', () => {
 9 |   // Mini React Redux clone
10 |   const store = {
11 |     getState: () => ({
12 |       todos: ['eat', 'drink', 'sleep'],
13 |       counter: 12,
14 |     }),
15 |   }
16 | 
17 |   class BaseProvider extends Component {
18 |     static propTypes = {
19 |       children: PropTypes.node,
20 |     }
21 | 
22 |     render() {
23 |       return this.props.children
24 |     }
25 |   }
26 | 
27 |   const Provider = compose(
28 |     withContext({ store: PropTypes.object }, props => ({ store: props.store }))
29 |   )(BaseProvider)
30 | 
31 |   expect(Provider.displayName).toBe('withContext(BaseProvider)')
32 | 
33 |   const connect = selector =>
34 |     compose(
35 |       getContext({ store: PropTypes.object }),
36 |       mapProps(props => selector(props.store.getState()))
37 |     )
38 | 
39 |   const component = sinon.spy(() => null)
40 |   component.displayName = 'component'
41 | 
42 |   const TodoList = connect(({ todos }) => ({ todos }))(component)
43 | 
44 |   expect(TodoList.displayName).toBe('getContext(mapProps(component))')
45 | 
46 |   mount(
47 |     <Provider store={store}>
48 |       <TodoList />
49 |     </Provider>
50 |   )
51 | 
52 |   expect(component.lastCall.args[0].todos).toEqual(['eat', 'drink', 'sleep'])
53 | })
54 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withHandlers-test.js:
--------------------------------------------------------------------------------
  1 | import React from 'react'
  2 | import { mount } from 'enzyme'
  3 | import sinon from 'sinon'
  4 | import { withHandlers, withState, compose } from '../'
  5 | 
  6 | test('withHandlers passes handlers to base component', () => {
  7 |   let submittedFormValue
  8 |   const enhanceForm = compose(
  9 |     withState('value', 'updateValue', ''),
 10 |     withHandlers({
 11 |       onChange: props => event => {
 12 |         props.updateValue(event.target.value)
 13 |       },
 14 |       onSubmit: props => () => {
 15 |         submittedFormValue = props.value
 16 |       },
 17 |     })
 18 |   )
 19 | 
 20 |   const Form = enhanceForm(({ value, onChange, onSubmit }) =>
 21 |     <form onSubmit={onSubmit}>
 22 |       <label>
 23 |         Value
 24 |         <input type="text" value={value} onChange={onChange} />
 25 |       </label>
 26 |       <p>
 27 |         {value}
 28 |       </p>
 29 |     </form>
 30 |   )
 31 | 
 32 |   const wrapper = mount(<Form />)
 33 |   const input = wrapper.find('input')
 34 |   const output = wrapper.find('p')
 35 |   const form = wrapper.find('form')
 36 | 
 37 |   input.simulate('change', { target: { value: 'Yay' } })
 38 |   expect(output.text()).toBe('Yay')
 39 | 
 40 |   input.simulate('change', { target: { value: 'Yay!!' } })
 41 |   expect(output.text()).toBe('Yay!!')
 42 | 
 43 |   form.simulate('submit')
 44 |   expect(submittedFormValue).toBe('Yay!!')
 45 | })
 46 | 
 47 | test('withHandlers passes immutable handlers', () => {
 48 |   const enhance = withHandlers({
 49 |     handler: () => () => null,
 50 |   })
 51 |   const component = sinon.spy(() => null)
 52 |   const Div = enhance(component)
 53 | 
 54 |   const wrapper = mount(<Div />)
 55 |   wrapper.setProps({ foo: 'bar' })
 56 | 
 57 |   expect(component.calledTwice).toBe(true)
 58 |   expect(component.firstCall.args[0].handler).toBe(
 59 |     component.secondCall.args[0].handler
 60 |   )
 61 | })
 62 | 
 63 | test('withHandlers warns if handler is not a higher-order function', () => {
 64 |   const error = sinon.stub(console, 'error')
 65 | 
 66 |   const Button = withHandlers({
 67 |     onClick: () => {},
 68 |   })('button')
 69 | 
 70 |   const wrapper = mount(<Button />)
 71 |   const button = wrapper.find('button')
 72 | 
 73 |   expect(() => button.simulate('click')).toThrowError(/undefined/)
 74 | 
 75 |   expect(error.firstCall.args[0]).toBe(
 76 |     'withHandlers(): Expected a map of higher-order functions. Refer to ' +
 77 |       'the docs for more info.'
 78 |   )
 79 | 
 80 |   /* eslint-disable */
 81 |   console.error.restore()
 82 |   /* eslint-enable */
 83 | })
 84 | 
 85 | test('withHandlers allow handers to be a factory', () => {
 86 |   const enhance = withHandlers(initialProps => {
 87 |     let cache_
 88 | 
 89 |     return {
 90 |       handler: () => () => {
 91 |         if (cache_) {
 92 |           return cache_
 93 |         }
 94 |         cache_ = { ...initialProps }
 95 | 
 96 |         return cache_
 97 |       },
 98 |     }
 99 |   })
100 | 
101 |   const componentHandlers = []
102 |   const componentHandlers2 = []
103 | 
104 |   const Component = enhance(({ handler }) => {
105 |     componentHandlers.push(handler())
106 |     return null
107 |   })
108 | 
109 |   const Component2 = enhance(({ handler }) => {
110 |     componentHandlers2.push(handler())
111 |     return null
112 |   })
113 | 
114 |   const wrapper = mount(<Component hello={'foo'} />)
115 |   wrapper.setProps({ hello: 'bar' })
116 |   expect(componentHandlers[0]).toBe(componentHandlers[1])
117 | 
118 |   // check that cache is not shared
119 |   mount(<Component2 hello={'foo'} />)
120 |   expect(componentHandlers[0]).toEqual(componentHandlers2[0])
121 |   expect(componentHandlers[0]).not.toBe(componentHandlers2[0])
122 | })
123 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withProps-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { shallow } from 'enzyme'
 3 | import { withProps } from '../'
 4 | 
 5 | test('withProps passes additional props to base component', () => {
 6 |   const DoReMi = withProps({ 'data-so': 'do', 'data-la': 'fa' })('div')
 7 |   expect(DoReMi.displayName).toBe('withProps(div)')
 8 | 
 9 |   const div = shallow(<DoReMi />).find('div')
10 |   expect(div.prop('data-so')).toBe('do')
11 |   expect(div.prop('data-la')).toBe('fa')
12 | })
13 | 
14 | test('withProps takes precedent over owner props', () => {
15 |   const DoReMi = withProps({ 'data-so': 'do', 'data-la': 'fa' })('div')
16 | 
17 |   const div = shallow(<DoReMi data-la="ti" />).find('div')
18 |   expect(div.prop('data-so')).toBe('do')
19 |   expect(div.prop('data-la')).toBe('fa')
20 | })
21 | 
22 | test('withProps should accept function', () => {
23 |   const DoReMi = withProps(props => ({
24 |     'data-so': props['data-la'],
25 |   }))('div')
26 | 
27 |   const div = shallow(<DoReMi data-la="la" />).find('div')
28 |   expect(div.prop('data-so')).toBe('la')
29 | })
30 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withPropsOnChange-test.js:
--------------------------------------------------------------------------------
  1 | import * as React from 'react'
  2 | import { mount } from 'enzyme'
  3 | import sinon from 'sinon'
  4 | import {
  5 |   withPropsOnChange,
  6 |   withState,
  7 |   withStateHandlers,
  8 |   flattenProp,
  9 |   compose,
 10 | } from '../'
 11 | 
 12 | test('withPropsOnChange maps subset of owner props to child props', () => {
 13 |   const component = sinon.spy(() => null)
 14 |   component.displayName = 'component'
 15 | 
 16 |   const mapSpy = sinon.spy()
 17 |   const StringConcat = compose(
 18 |     withState('strings', 'updateStrings', { a: 'a', b: 'b', c: 'c' }),
 19 |     flattenProp('strings'),
 20 |     withPropsOnChange(['a', 'b'], ({ a, b, ...props }) => {
 21 |       mapSpy()
 22 |       return {
 23 |         ...props,
 24 |         foobar: a + b,
 25 |       }
 26 |     })
 27 |   )(component)
 28 | 
 29 |   expect(StringConcat.displayName).toBe(
 30 |     'withState(flattenProp(withPropsOnChange(component)))'
 31 |   )
 32 | 
 33 |   mount(<StringConcat />)
 34 |   const { updateStrings } = component.firstCall.args[0]
 35 |   expect(component.lastCall.args[0].foobar).toBe('ab')
 36 |   expect(component.calledOnce).toBe(true)
 37 |   expect(mapSpy.callCount).toBe(1)
 38 | 
 39 |   // Does not re-map for non-dependent prop updates
 40 |   updateStrings(strings => ({ ...strings, c: 'baz' }))
 41 |   expect(component.lastCall.args[0].foobar).toBe('ab')
 42 |   expect(component.lastCall.args[0].c).toBe('c')
 43 |   expect(component.calledTwice).toBe(true)
 44 |   expect(mapSpy.callCount).toBe(1)
 45 | 
 46 |   updateStrings(strings => ({ ...strings, a: 'foo', b: 'bar' }))
 47 |   expect(component.lastCall.args[0].foobar).toBe('foobar')
 48 |   expect(component.lastCall.args[0].c).toBe('baz')
 49 |   expect(component.calledThrice).toBe(true)
 50 |   expect(mapSpy.callCount).toBe(2)
 51 | })
 52 | 
 53 | test('withPropsOnChange maps subset of owner props to child props with custom predicate', () => {
 54 |   const component = sinon.spy(() => null)
 55 |   component.displayName = 'component'
 56 | 
 57 |   const mapSpy = sinon.spy()
 58 |   const shouldMapSpy = sinon.spy()
 59 |   const PageContainer = compose(
 60 |     withStateHandlers(
 61 |       { result: { hasError: false, loading: true, error: null } },
 62 |       {
 63 |         updateResult: ({ result }) => payload => ({
 64 |           result: { ...result, ...payload },
 65 |         }),
 66 |       }
 67 |     ),
 68 |     withPropsOnChange(
 69 |       ({ result }, { result: nextResult }) => {
 70 |         shouldMapSpy(result, nextResult)
 71 |         return !result.hasError && nextResult.hasError
 72 |       },
 73 |       ({ result: { hasError, error } }) => {
 74 |         mapSpy()
 75 | 
 76 |         if (hasError) {
 77 |           return {
 78 |             errorEverHappened: true,
 79 |             lastError: error,
 80 |           }
 81 |         }
 82 | 
 83 |         return {
 84 |           errorEverHappened: false,
 85 |         }
 86 |       }
 87 |     )
 88 |   )(component)
 89 | 
 90 |   expect(PageContainer.displayName).toBe(
 91 |     'withStateHandlers(withPropsOnChange(component))'
 92 |   )
 93 | 
 94 |   mount(<PageContainer />)
 95 |   const { updateResult } = component.firstCall.args[0]
 96 |   expect(component.lastCall.args[0].errorEverHappened).toBe(false)
 97 |   expect(component.lastCall.args[0].lastError).toBeUndefined()
 98 |   expect(component.calledOnce).toBe(true)
 99 |   expect(mapSpy.callCount).toBe(1)
100 |   expect(shouldMapSpy.callCount).toBe(1)
101 | 
102 |   updateResult({ loading: false, hasError: true, error: '1' })
103 |   expect(component.lastCall.args[0].errorEverHappened).toBe(true)
104 |   expect(component.lastCall.args[0].lastError).toBe('1')
105 |   expect(component.calledTwice).toBe(true)
106 |   expect(mapSpy.callCount).toBe(2)
107 | 
108 |   // Does not re-map for false map result
109 |   updateResult({ loading: true, hasError: false, error: null })
110 |   expect(component.lastCall.args[0].errorEverHappened).toBe(true)
111 |   expect(component.lastCall.args[0].lastError).toBe('1')
112 |   expect(component.calledThrice).toBe(true)
113 |   expect(mapSpy.callCount).toBe(2)
114 | 
115 |   updateResult({ loading: false, hasError: true, error: '2' })
116 |   expect(component.lastCall.args[0].errorEverHappened).toBe(true)
117 |   expect(component.lastCall.args[0].lastError).toBe('2')
118 |   expect(component.callCount).toBe(4)
119 |   expect(mapSpy.callCount).toBe(3)
120 | })
121 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withReducer-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | import { withReducer, compose, flattenProp } from '../'
 5 | 
 6 | const SET_COUNTER = 'SET_COUNTER'
 7 | 
 8 | test('adds a stateful value and a function for updating it', () => {
 9 |   const component = sinon.spy(() => null)
10 |   component.displayName = 'component'
11 | 
12 |   const initialState = { counter: 0 }
13 | 
14 |   const reducer = (state, action) =>
15 |     action.type === SET_COUNTER ? { counter: action.payload } : state
16 | 
17 |   const Counter = compose(
18 |     withReducer('state', 'dispatch', reducer, initialState),
19 |     flattenProp('state')
20 |   )(component)
21 | 
22 |   expect(Counter.displayName).toBe('withReducer(flattenProp(component))')
23 | 
24 |   mount(<Counter />)
25 |   const { dispatch } = component.firstCall.args[0]
26 | 
27 |   expect(component.lastCall.args[0].counter).toBe(0)
28 | 
29 |   dispatch({ type: SET_COUNTER, payload: 18 })
30 |   expect(component.lastCall.args[0].counter).toBe(18)
31 | })
32 | 
33 | test('calls initialState when it is a function', () => {
34 |   const component = sinon.spy(() => null)
35 |   component.displayName = 'component'
36 | 
37 |   const initialState = ({ initialCount }) => ({ counter: initialCount })
38 | 
39 |   const reducer = (state, action) =>
40 |     action.type === SET_COUNTER ? { counter: action.payload } : state
41 | 
42 |   const Counter = compose(
43 |     withReducer('state', 'dispatch', reducer, initialState),
44 |     flattenProp('state')
45 |   )(component)
46 | 
47 |   mount(<Counter initialCount={10} />)
48 | 
49 |   expect(component.lastCall.args[0].counter).toBe(10)
50 | })
51 | 
52 | test('receives state from reducer when initialState is not provided', () => {
53 |   const component = sinon.spy(() => null)
54 |   component.displayName = 'component'
55 | 
56 |   const initialState = { counter: 0 }
57 | 
58 |   const reducer = (state = initialState, action) =>
59 |     action.type === SET_COUNTER ? { counter: action.payload } : state
60 | 
61 |   const Counter = compose(
62 |     withReducer('state', 'dispatch', reducer),
63 |     flattenProp('state')
64 |   )(component)
65 | 
66 |   mount(<Counter />)
67 | 
68 |   expect(component.lastCall.args[0].counter).toBe(0)
69 | })
70 | 
71 | test('calls the given callback with new state after a dispatch call', () => {
72 |   const component = sinon.spy(() => null)
73 |   component.displayName = 'component'
74 | 
75 |   const initialState = { counter: 0 }
76 | 
77 |   const reducer = (state, action) =>
78 |     action.type === SET_COUNTER ? { counter: action.payload } : state
79 | 
80 |   const Counter = compose(
81 |     withReducer('state', 'dispatch', reducer, initialState),
82 |     flattenProp('state')
83 |   )(component)
84 | 
85 |   mount(<Counter />)
86 |   const dispatch = sinon.spy(component.firstCall.args[0].dispatch)
87 |   const callback = sinon.spy()
88 | 
89 |   dispatch({ type: SET_COUNTER, payload: 11 }, callback)
90 |   expect(dispatch.calledBefore(callback)).toBe(true)
91 |   expect(dispatch.calledOnce).toBe(true)
92 |   expect(callback.calledAfter(dispatch)).toBe(true)
93 |   expect(callback.calledOnce).toBe(true)
94 |   expect(callback.getCall(0).args.length).toBe(1)
95 |   expect(callback.getCall(0).args[0]).toEqual({ counter: 11 })
96 | })
97 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withState-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { mount } from 'enzyme'
 3 | import sinon from 'sinon'
 4 | 
 5 | import { withState } from '../'
 6 | 
 7 | test('withState adds a stateful value and a function for updating it', () => {
 8 |   const component = sinon.spy(() => null)
 9 |   component.displayName = 'component'
10 | 
11 |   const Counter = withState('counter', 'updateCounter', 0)(component)
12 |   expect(Counter.displayName).toBe('withState(component)')
13 | 
14 |   mount(<Counter pass="through" />)
15 |   const { updateCounter } = component.firstCall.args[0]
16 | 
17 |   expect(component.lastCall.args[0].counter).toBe(0)
18 |   expect(component.lastCall.args[0].pass).toBe('through')
19 | 
20 |   updateCounter(n => n + 9)
21 |   updateCounter(n => n * 2)
22 | 
23 |   expect(component.lastCall.args[0].counter).toBe(18)
24 |   expect(component.lastCall.args[0].pass).toBe('through')
25 | })
26 | 
27 | test('withState also accepts a non-function, which is passed directly to setState()', () => {
28 |   const component = sinon.spy(() => null)
29 |   component.displayName = 'component'
30 | 
31 |   const Counter = withState('counter', 'updateCounter', 0)(component)
32 |   mount(<Counter />)
33 |   const { updateCounter } = component.firstCall.args[0]
34 | 
35 |   updateCounter(18)
36 |   expect(component.lastCall.args[0].counter).toBe(18)
37 | })
38 | 
39 | test('withState accepts setState() callback', () => {
40 |   const component = sinon.spy(() => null)
41 |   component.displayName = 'component'
42 | 
43 |   const Counter = withState('counter', 'updateCounter', 0)(component)
44 |   mount(<Counter />)
45 |   const { updateCounter } = component.firstCall.args[0]
46 | 
47 |   const renderSpy = sinon.spy(() => {
48 |     expect(component.lastCall.args[0].counter).toBe(18)
49 |   })
50 | 
51 |   expect(component.lastCall.args[0].counter).toBe(0)
52 |   updateCounter(18, renderSpy)
53 | })
54 | 
55 | test('withState also accepts initialState as function of props', () => {
56 |   const component = sinon.spy(() => null)
57 |   component.displayName = 'component'
58 | 
59 |   const Counter = withState(
60 |     'counter',
61 |     'updateCounter',
62 |     props => props.initialCounter
63 |   )(component)
64 | 
65 |   mount(<Counter initialCounter={1} />)
66 |   const { updateCounter } = component.firstCall.args[0]
67 | 
68 |   expect(component.lastCall.args[0].counter).toBe(1)
69 |   updateCounter(n => n * 3)
70 |   expect(component.lastCall.args[0].counter).toBe(3)
71 | })
72 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/withStateHandlers-test.js:
--------------------------------------------------------------------------------
  1 | import React from 'react'
  2 | import { mount } from 'enzyme'
  3 | import sinon from 'sinon'
  4 | 
  5 | import { compose, withStateHandlers } from '../'
  6 | 
  7 | test('withStateHandlers should persist events passed as argument', () => {
  8 |   const component = ({ value, onChange }) =>
  9 |     <div>
 10 |       <input type="text" value={value} onChange={onChange} />
 11 |       <p>
 12 |         {value}
 13 |       </p>
 14 |     </div>
 15 | 
 16 |   const InputComponent = withStateHandlers(
 17 |     { value: '' },
 18 |     {
 19 |       onChange: () => e => ({
 20 |         value: e.target.value,
 21 |       }),
 22 |     }
 23 |   )(component)
 24 | 
 25 |   const wrapper = mount(<InputComponent />)
 26 |   const input = wrapper.find('input')
 27 |   const output = wrapper.find('p')
 28 |   // having that enzyme simulate does not simulate real situation
 29 |   // emulate persist
 30 |   input.simulate('change', {
 31 |     persist() {
 32 |       this.target = { value: 'Yay' }
 33 |     },
 34 |   })
 35 |   expect(output.text()).toBe('Yay')
 36 | 
 37 |   input.simulate('change', { target: { value: 'empty' } })
 38 |   expect(output.text()).toBe('empty')
 39 | })
 40 | 
 41 | test('withStateHandlers adds a stateful value and a function for updating it', () => {
 42 |   const component = sinon.spy(() => null)
 43 |   component.displayName = 'component'
 44 | 
 45 |   const Counter = withStateHandlers(
 46 |     { counter: 0 },
 47 |     {
 48 |       updateCounter: ({ counter }) => increment => ({
 49 |         counter: counter + increment,
 50 |       }),
 51 |     }
 52 |   )(component)
 53 |   expect(Counter.displayName).toBe('withStateHandlers(component)')
 54 | 
 55 |   mount(<Counter pass="through" />)
 56 |   const { updateCounter } = component.firstCall.args[0]
 57 | 
 58 |   expect(component.lastCall.args[0].counter).toBe(0)
 59 |   expect(component.lastCall.args[0].pass).toBe('through')
 60 | 
 61 |   updateCounter(9)
 62 |   expect(component.lastCall.args[0].counter).toBe(9)
 63 |   updateCounter(1)
 64 |   updateCounter(10)
 65 | 
 66 |   expect(component.lastCall.args[0].counter).toBe(20)
 67 |   expect(component.lastCall.args[0].pass).toBe('through')
 68 | })
 69 | 
 70 | test('withStateHandlers accepts initialState as function of props', () => {
 71 |   const component = sinon.spy(() => null)
 72 |   component.displayName = 'component'
 73 | 
 74 |   const Counter = withStateHandlers(
 75 |     ({ initialCounter }) => ({
 76 |       counter: initialCounter,
 77 |     }),
 78 |     {
 79 |       updateCounter: ({ counter }) => increment => ({
 80 |         counter: counter + increment,
 81 |       }),
 82 |     }
 83 |   )(component)
 84 | 
 85 |   const initialCounter = 101
 86 | 
 87 |   mount(<Counter initialCounter={initialCounter} />)
 88 |   expect(component.lastCall.args[0].counter).toBe(initialCounter)
 89 | })
 90 | 
 91 | test('withStateHandlers initial state must be function or object or null or undefined', () => {
 92 |   const component = sinon.spy(() => null)
 93 |   component.displayName = 'component'
 94 | 
 95 |   const Counter = withStateHandlers(1, {})(component)
 96 |   // React throws an error
 97 |   // expect(() => mount(<Counter />)).toThrow()
 98 |   const error = sinon.stub(console, 'error')
 99 |   mount(<Counter />)
100 |   expect(error.called).toBe(true)
101 | })
102 | 
103 | test('withStateHandlers have access to props', () => {
104 |   const component = sinon.spy(() => null)
105 |   component.displayName = 'component'
106 | 
107 |   const Counter = withStateHandlers(
108 |     ({ initialCounter }) => ({
109 |       counter: initialCounter,
110 |     }),
111 |     {
112 |       increment: ({ counter }, { incrementValue }) => () => ({
113 |         counter: counter + incrementValue,
114 |       }),
115 |     }
116 |   )(component)
117 | 
118 |   const initialCounter = 101
119 |   const incrementValue = 37
120 | 
121 |   mount(
122 |     <Counter initialCounter={initialCounter} incrementValue={incrementValue} />
123 |   )
124 | 
125 |   const { increment } = component.firstCall.args[0]
126 | 
127 |   increment()
128 |   expect(component.lastCall.args[0].counter).toBe(
129 |     initialCounter + incrementValue
130 |   )
131 | })
132 | 
133 | test('withStateHandlers passes immutable state updaters', () => {
134 |   const component = sinon.spy(() => null)
135 |   component.displayName = 'component'
136 | 
137 |   const Counter = withStateHandlers(
138 |     ({ initialCounter }) => ({
139 |       counter: initialCounter,
140 |     }),
141 |     {
142 |       increment: ({ counter }, { incrementValue }) => () => ({
143 |         counter: counter + incrementValue,
144 |       }),
145 |     }
146 |   )(component)
147 | 
148 |   const initialCounter = 101
149 |   const incrementValue = 37
150 | 
151 |   mount(
152 |     <Counter initialCounter={initialCounter} incrementValue={incrementValue} />
153 |   )
154 | 
155 |   const { increment } = component.firstCall.args[0]
156 | 
157 |   increment()
158 |   expect(component.lastCall.args[0].counter).toBe(
159 |     initialCounter + incrementValue
160 |   )
161 | })
162 | 
163 | test('withStateHandlers does not rerender if state updater returns undefined', () => {
164 |   const component = sinon.spy(() => null)
165 |   component.displayName = 'component'
166 | 
167 |   const Counter = withStateHandlers(
168 |     ({ initialCounter }) => ({
169 |       counter: initialCounter,
170 |     }),
171 |     {
172 |       updateCounter: ({ counter }) => increment =>
173 |         increment === 0
174 |           ? undefined
175 |           : {
176 |               counter: counter + increment,
177 |             },
178 |     }
179 |   )(component)
180 | 
181 |   const initialCounter = 101
182 | 
183 |   mount(<Counter initialCounter={initialCounter} />)
184 |   expect(component.callCount).toBe(1)
185 | 
186 |   const { updateCounter } = component.firstCall.args[0]
187 | 
188 |   updateCounter(1)
189 |   expect(component.callCount).toBe(2)
190 | 
191 |   updateCounter(0)
192 |   expect(component.callCount).toBe(2)
193 | })
194 | 
195 | test('withStateHandlers rerenders if parent props changed', () => {
196 |   const component = sinon.spy(() => null)
197 |   component.displayName = 'component'
198 | 
199 |   const Counter = compose(
200 |     withStateHandlers(
201 |       ({ initialCounter }) => ({
202 |         counter: initialCounter,
203 |       }),
204 |       {
205 |         increment: ({ counter }) => incrementValue => ({
206 |           counter: counter + incrementValue,
207 |         }),
208 |       }
209 |     ),
210 |     withStateHandlers(
211 |       { incrementValue: 1 },
212 |       {
213 |         // updates parent state and return undefined
214 |         updateParentIncrement: ({ incrementValue }, { increment }) => () => {
215 |           increment(incrementValue)
216 |           return undefined
217 |         },
218 |       }
219 |     )
220 |   )(component)
221 | 
222 |   const initialCounter = 101
223 | 
224 |   mount(<Counter initialCounter={initialCounter} />)
225 | 
226 |   const { updateParentIncrement } = component.firstCall.args[0]
227 | 
228 |   updateParentIncrement()
229 |   expect(component.lastCall.args[0].counter).toBe(initialCounter + 1)
230 | })
231 | 


--------------------------------------------------------------------------------
/src/packages/recompose/__tests__/wrapDisplayName-test.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import { wrapDisplayName } from '../'
 3 | 
 4 | test('wrapDisplayName wraps the display name of a React component with the name of an HoC, Relay-style', () => {
 5 |   class SomeComponent extends React.Component {
 6 |     render() {
 7 |       return <div />
 8 |     }
 9 |   }
10 | 
11 |   expect(wrapDisplayName(SomeComponent, 'someHoC')).toBe(
12 |     'someHoC(SomeComponent)'
13 |   )
14 | })
15 | 


--------------------------------------------------------------------------------
/src/packages/recompose/baconObservableConfig.js:
--------------------------------------------------------------------------------
 1 | import $observable from 'symbol-observable'
 2 | import Bacon from 'baconjs'
 3 | 
 4 | const config = {
 5 |   fromESObservable: observable =>
 6 |     Bacon.fromBinder(sink => {
 7 |       const { unsubscribe } = observable.subscribe({
 8 |         next: val => sink(new Bacon.Next(val)),
 9 |         error: err => sink(new Bacon.Error(err)),
10 |         complete: () => sink(new Bacon.End()),
11 |       })
12 |       return unsubscribe
13 |     }),
14 |   toESObservable: stream => ({
15 |     subscribe: observer => {
16 |       const unsubscribe = stream.subscribe(event => {
17 |         if (event.hasValue()) {
18 |           observer.next(event.value())
19 |         } else if (event.isError()) {
20 |           observer.error(event.error)
21 |         } else if (event.isEnd()) {
22 |           observer.complete()
23 |         }
24 |       })
25 |       return { unsubscribe }
26 |     },
27 |     [$observable]() {
28 |       return this
29 |     },
30 |   }),
31 | }
32 | 
33 | export default config
34 | 


--------------------------------------------------------------------------------
/src/packages/recompose/branch.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const identity = Component => Component
 6 | 
 7 | const branch = (test, left, right = identity) => BaseComponent => {
 8 |   let leftFactory
 9 |   let rightFactory
10 |   const Branch = props => {
11 |     if (test(props)) {
12 |       leftFactory = leftFactory || createFactory(left(BaseComponent))
13 |       return leftFactory(props)
14 |     }
15 |     rightFactory = rightFactory || createFactory(right(BaseComponent))
16 |     return rightFactory(props)
17 |   }
18 | 
19 |   if (process.env.NODE_ENV !== 'production') {
20 |     return setDisplayName(wrapDisplayName(BaseComponent, 'branch'))(Branch)
21 |   }
22 |   return Branch
23 | }
24 | 
25 | export default branch
26 | 


--------------------------------------------------------------------------------
/src/packages/recompose/componentFromProp.js:
--------------------------------------------------------------------------------
 1 | import { createElement } from 'react'
 2 | import omit from './utils/omit'
 3 | 
 4 | const componentFromProp = propName => {
 5 |   const Component = props =>
 6 |     createElement(props[propName], omit(props, [propName]))
 7 |   Component.displayName = `componentFromProp(${propName})`
 8 |   return Component
 9 | }
10 | 
11 | export default componentFromProp
12 | 


--------------------------------------------------------------------------------
/src/packages/recompose/componentFromStream.js:
--------------------------------------------------------------------------------
 1 | import { Component } from 'react'
 2 | import { createChangeEmitter } from 'change-emitter'
 3 | import $observable from 'symbol-observable'
 4 | import { config as globalConfig } from './setObservableConfig'
 5 | 
 6 | export const componentFromStreamWithConfig = config => propsToVdom =>
 7 |   class ComponentFromStream extends Component {
 8 |     state = { vdom: null }
 9 | 
10 |     propsEmitter = createChangeEmitter()
11 | 
12 |     // Stream of props
13 |     props$ = config.fromESObservable({
14 |       subscribe: observer => {
15 |         const unsubscribe = this.propsEmitter.listen(props => {
16 |           if (props) {
17 |             observer.next(props)
18 |           } else {
19 |             observer.complete()
20 |           }
21 |         })
22 |         return { unsubscribe }
23 |       },
24 |       [$observable]() {
25 |         return this
26 |       },
27 |     })
28 | 
29 |     // Stream of vdom
30 |     vdom$ = config.toESObservable(propsToVdom(this.props$))
31 | 
32 |     componentWillMount() {
33 |       // Subscribe to child prop changes so we know when to re-render
34 |       this.subscription = this.vdom$.subscribe({
35 |         next: vdom => {
36 |           this.setState({ vdom })
37 |         },
38 |       })
39 |       this.propsEmitter.emit(this.props)
40 |     }
41 | 
42 |     componentWillReceiveProps(nextProps) {
43 |       // Receive new props from the owner
44 |       this.propsEmitter.emit(nextProps)
45 |     }
46 | 
47 |     shouldComponentUpdate(nextProps, nextState) {
48 |       return nextState.vdom !== this.state.vdom
49 |     }
50 | 
51 |     componentWillUnmount() {
52 |       // Call without arguments to complete stream
53 |       this.propsEmitter.emit()
54 | 
55 |       // Clean-up subscription before un-mounting
56 |       this.subscription.unsubscribe()
57 |     }
58 | 
59 |     render() {
60 |       return this.state.vdom
61 |     }
62 |   }
63 | 
64 | const componentFromStream = propsToVdom =>
65 |   componentFromStreamWithConfig(globalConfig)(propsToVdom)
66 | 
67 | export default componentFromStream
68 | 


--------------------------------------------------------------------------------
/src/packages/recompose/compose.js:
--------------------------------------------------------------------------------
1 | const compose = (...funcs) =>
2 |   funcs.reduce((a, b) => (...args) => a(b(...args)), arg => arg)
3 | 
4 | export default compose
5 | 


--------------------------------------------------------------------------------
/src/packages/recompose/createEventHandler.js:
--------------------------------------------------------------------------------
 1 | import $observable from 'symbol-observable'
 2 | import { createChangeEmitter } from 'change-emitter'
 3 | import { config as globalConfig } from './setObservableConfig'
 4 | 
 5 | export const createEventHandlerWithConfig = config => () => {
 6 |   const emitter = createChangeEmitter()
 7 |   const stream = config.fromESObservable({
 8 |     subscribe(observer) {
 9 |       const unsubscribe = emitter.listen(value => observer.next(value))
10 |       return { unsubscribe }
11 |     },
12 |     [$observable]() {
13 |       return this
14 |     },
15 |   })
16 |   return {
17 |     handler: emitter.emit,
18 |     stream,
19 |   }
20 | }
21 | 
22 | const createEventHandler = createEventHandlerWithConfig(globalConfig)
23 | 
24 | export default createEventHandler
25 | 


--------------------------------------------------------------------------------
/src/packages/recompose/createSink.js:
--------------------------------------------------------------------------------
 1 | import { Component } from 'react'
 2 | import { polyfill } from 'react-lifecycles-compat'
 3 | 
 4 | const createSink = callback => {
 5 |   class Sink extends Component {
 6 |     state = {}
 7 | 
 8 |     static getDerivedStateFromProps(nextProps) {
 9 |       callback(nextProps)
10 |       return null
11 |     }
12 | 
13 |     render() {
14 |       return null
15 |     }
16 |   }
17 | 
18 |   polyfill(Sink)
19 |   return Sink
20 | }
21 | 
22 | export default createSink
23 | 


--------------------------------------------------------------------------------
/src/packages/recompose/defaultProps.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const defaultProps = props => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   const DefaultProps = ownerProps => factory(ownerProps)
 8 |   DefaultProps.defaultProps = props
 9 |   if (process.env.NODE_ENV !== 'production') {
10 |     return setDisplayName(wrapDisplayName(BaseComponent, 'defaultProps'))(
11 |       DefaultProps
12 |     )
13 |   }
14 |   return DefaultProps
15 | }
16 | 
17 | export default defaultProps
18 | 


--------------------------------------------------------------------------------
/src/packages/recompose/flattenProp.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const flattenProp = propName => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   const FlattenProp = props =>
 8 |     factory({
 9 |       ...props,
10 |       ...props[propName],
11 |     })
12 | 
13 |   if (process.env.NODE_ENV !== 'production') {
14 |     return setDisplayName(wrapDisplayName(BaseComponent, 'flattenProp'))(
15 |       FlattenProp
16 |     )
17 |   }
18 |   return FlattenProp
19 | }
20 | 
21 | export default flattenProp
22 | 


--------------------------------------------------------------------------------
/src/packages/recompose/flydObservableConfig.js:
--------------------------------------------------------------------------------
 1 | import $observable from 'symbol-observable'
 2 | import flyd from 'flyd'
 3 | 
 4 | const noop = () => {}
 5 | 
 6 | const config = {
 7 |   fromESObservable: observable => {
 8 |     const stream = flyd.stream()
 9 |     const { unsubscribe } = observable.subscribe({
10 |       next: value => stream(value),
11 |       error: error => stream({ error }),
12 |       complete: () => stream.end(true),
13 |     })
14 | 
15 |     flyd.on(unsubscribe, stream.end)
16 |     return stream
17 |   },
18 | 
19 |   toESObservable: stream => ({
20 |     subscribe: observer => {
21 |       const sub = flyd.on(observer.next || noop, stream)
22 |       flyd.on(_ => observer.complete(), sub.end)
23 |       return {
24 |         unsubscribe: () => sub.end(true),
25 |       }
26 |     },
27 |     [$observable]() {
28 |       return this
29 |     },
30 |   }),
31 | }
32 | 
33 | export default config
34 | 


--------------------------------------------------------------------------------
/src/packages/recompose/fromRenderProps.js:
--------------------------------------------------------------------------------
 1 | import React from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const fromRenderProps = (
 6 |   RenderPropsComponent,
 7 |   propsMapper,
 8 |   renderPropName = 'children'
 9 | ) => BaseComponent => {
10 |   const baseFactory = React.createFactory(BaseComponent)
11 |   const renderPropsFactory = React.createFactory(RenderPropsComponent)
12 | 
13 |   const FromRenderProps = ownerProps =>
14 |     renderPropsFactory({
15 |       [renderPropName]: (...props) =>
16 |         baseFactory({ ...ownerProps, ...propsMapper(...props) }),
17 |     })
18 | 
19 |   if (process.env.NODE_ENV !== 'production') {
20 |     return setDisplayName(wrapDisplayName(BaseComponent, 'fromRenderProps'))(
21 |       FromRenderProps
22 |     )
23 |   }
24 | 
25 |   return FromRenderProps
26 | }
27 | 
28 | export default fromRenderProps
29 | 


--------------------------------------------------------------------------------
/src/packages/recompose/getContext.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const getContext = contextTypes => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   const GetContext = (ownerProps, context) =>
 8 |     factory({
 9 |       ...ownerProps,
10 |       ...context,
11 |     })
12 | 
13 |   GetContext.contextTypes = contextTypes
14 | 
15 |   if (process.env.NODE_ENV !== 'production') {
16 |     return setDisplayName(wrapDisplayName(BaseComponent, 'getContext'))(
17 |       GetContext
18 |     )
19 |   }
20 |   return GetContext
21 | }
22 | 
23 | export default getContext
24 | 


--------------------------------------------------------------------------------
/src/packages/recompose/getDisplayName.js:
--------------------------------------------------------------------------------
 1 | const getDisplayName = Component => {
 2 |   if (typeof Component === 'string') {
 3 |     return Component
 4 |   }
 5 | 
 6 |   if (!Component) {
 7 |     return undefined
 8 |   }
 9 | 
10 |   return Component.displayName || Component.name || 'Component'
11 | }
12 | 
13 | export default getDisplayName
14 | 


--------------------------------------------------------------------------------
/src/packages/recompose/hoistStatics.js:
--------------------------------------------------------------------------------
 1 | import hoistNonReactStatics from 'hoist-non-react-statics'
 2 | 
 3 | const hoistStatics = (higherOrderComponent, blacklist) => BaseComponent => {
 4 |   const NewComponent = higherOrderComponent(BaseComponent)
 5 |   hoistNonReactStatics(NewComponent, BaseComponent, blacklist)
 6 |   return NewComponent
 7 | }
 8 | 
 9 | export default hoistStatics
10 | 


--------------------------------------------------------------------------------
/src/packages/recompose/index.js:
--------------------------------------------------------------------------------
 1 | // Higher-order component helpers
 2 | export { default as mapProps } from './mapProps'
 3 | export { default as withProps } from './withProps'
 4 | export { default as withPropsOnChange } from './withPropsOnChange'
 5 | export { default as withHandlers } from './withHandlers'
 6 | export { default as defaultProps } from './defaultProps'
 7 | export { default as renameProp } from './renameProp'
 8 | export { default as renameProps } from './renameProps'
 9 | export { default as flattenProp } from './flattenProp'
10 | export { default as withState } from './withState'
11 | export { default as withStateHandlers } from './withStateHandlers'
12 | export { default as withReducer } from './withReducer'
13 | export { default as branch } from './branch'
14 | export { default as renderComponent } from './renderComponent'
15 | export { default as renderNothing } from './renderNothing'
16 | export { default as shouldUpdate } from './shouldUpdate'
17 | export { default as pure } from './pure'
18 | export { default as onlyUpdateForKeys } from './onlyUpdateForKeys'
19 | export { default as onlyUpdateForPropTypes } from './onlyUpdateForPropTypes'
20 | export { default as withContext } from './withContext'
21 | export { default as getContext } from './getContext'
22 | export { default as lifecycle } from './lifecycle'
23 | export { default as toClass } from './toClass'
24 | export { default as toRenderProps } from './toRenderProps'
25 | export { default as fromRenderProps } from './fromRenderProps'
26 | 
27 | // Static property helpers
28 | export { default as setStatic } from './setStatic'
29 | export { default as setPropTypes } from './setPropTypes'
30 | export { default as setDisplayName } from './setDisplayName'
31 | 
32 | // Composition function
33 | export { default as compose } from './compose'
34 | 
35 | // Other utils
36 | export { default as getDisplayName } from './getDisplayName'
37 | export { default as wrapDisplayName } from './wrapDisplayName'
38 | export { default as shallowEqual } from './shallowEqual'
39 | export { default as isClassComponent } from './isClassComponent'
40 | export { default as createSink } from './createSink'
41 | export { default as componentFromProp } from './componentFromProp'
42 | export { default as nest } from './nest'
43 | export { default as hoistStatics } from './hoistStatics'
44 | 
45 | // Observable helpers
46 | export {
47 |   default as componentFromStream,
48 |   componentFromStreamWithConfig,
49 | } from './componentFromStream'
50 | export {
51 |   default as mapPropsStream,
52 |   mapPropsStreamWithConfig,
53 | } from './mapPropsStream'
54 | export {
55 |   default as createEventHandler,
56 |   createEventHandlerWithConfig,
57 | } from './createEventHandler'
58 | export { default as setObservableConfig } from './setObservableConfig'
59 | 


--------------------------------------------------------------------------------
/src/packages/recompose/index.js.flow:
--------------------------------------------------------------------------------
  1 | /* eslint-disable */
  2 | 
  3 | /* @flow strict */
  4 | 
  5 | /**
  6 |  * 1) Types give additional constraint on a language, recompose was written on the untyped language
  7 |  * as a consequence of this fact
  8 |  * for some recompose HOCs is near impossible to add correct typings.
  9 |  * 2) flow sometimes does not work as expected.
 10 |  *
 11 |  *  So any help and suggestions will be very appreciated.
 12 |  *
 13 |  * -----------------------------------------------------------------------------------
 14 |  * Type definition of recompose HOCs are splitted into 2 parts,
 15 |  * "HOCs with good flow support" - in most cases you can use them without big issues,
 16 |  * see `test_${hocName}.js` for the idea.
 17 |  * Some known issues:
 18 |  * see test_mapProps.js - inference work but type errors are not detected in hocs
 19 |  *
 20 |  * SUPPORTED HOCs:
 21 |  * defaultProps, mapProps, withProps, withStateHandlers, withHandlers, pure,
 22 |  * onlyUpdateForKeys, shouldUpdate, renderNothing, renderComponent, branch, withPropsOnChange,
 23 |  * onlyUpdateForPropTypes, toClass, withContext, getContext,
 24 |  * setStatic, setPropTypes, setDisplayName,
 25 |  * -----------------------------------------------------------------------------------
 26 |  * "TODO (UNSUPPORTED) HOCs" - you need to provide type information
 27 |  * (no automatic type inference), voodoo dancing etc
 28 |  * see `test_voodoo.js` for the idea
 29 |  *
 30 |  * remember that:
 31 |  * flattenProp,renameProp, renameProps can easily be replaced with withProps
 32 |  * withReducer, withState -> use withStateHandlers instead
 33 |  * lifecycle -> you don't need recompose if you need a lifecycle, just use React class instead
 34 |  * mapPropsStream -> see test_mapPropsStream.js
 35 |  * -----------------------------------------------------------------------------------
 36 |  *
 37 |  * utils:
 38 |  * getDisplayName, wrapDisplayName, shallowEqual,
 39 |  * isClassComponent, createSink, componentFromProp,
 40 |  * nest, hoistStatics,
 41 |  */
 42 | 
 43 | //-------------------
 44 | 
 45 | // -----------------------------------------------------------------
 46 | // Private declarations
 47 | // -----------------------------------------------------------------
 48 | 
 49 | declare type ExtractToVoid = <A, B, C, R>(
 50 |   v: (a: A, b: B, c: C) => R
 51 | ) => (A, B, C) => void
 52 | 
 53 | declare type ExtractStateHandlersCodomain = <State, Enhanced, V>(
 54 |   v: (state: State, props: Enhanced) => V
 55 | ) => V
 56 | 
 57 | declare type ExtractHandlersCodomain = <Enhanced, V>(
 58 |   v: (props: Enhanced) => V
 59 | ) => V
 60 | 
 61 | declare type UnaryFn<A, R> = (a: A) => R
 62 | 
 63 | // -----------------------------------------------------------------
 64 | // Public declarations
 65 | // -----------------------------------------------------------------
 66 | 
 67 | export type Component<A> = React$ComponentType<A>
 68 | 
 69 | export type HOC<Base, Enhanced> = UnaryFn<Component<Base>, Component<Enhanced>>
 70 | 
 71 | declare export var compose: $Compose
 72 | 
 73 | // ---------------------------------------------------------------------------
 74 | // ----------------===<<<HOCs with good flow support>>>===--------------------
 75 | // ---------------------------------------------------------------------------
 76 | 
 77 | declare export function defaultProps<Default, Enhanced>(
 78 |   defProps: Default
 79 | ): HOC<{ ...$Exact<Enhanced>, ...Default }, Enhanced>
 80 | 
 81 | declare export function mapProps<Base, Enhanced>(
 82 |   propsMapper: (ownerProps: Enhanced) => Base
 83 | ): HOC<Base, Enhanced>
 84 | 
 85 | declare export function withProps<BaseAdd, Enhanced>(
 86 |   propsMapper: ((ownerProps: Enhanced) => BaseAdd) | BaseAdd
 87 | ): HOC<{ ...$Exact<Enhanced>, ...BaseAdd }, Enhanced>
 88 | 
 89 | declare export function withStateHandlers<
 90 |   State,
 91 |   Enhanced,
 92 |   StateHandlers: {
 93 |     [key: string]: (
 94 |       state: State,
 95 |       props: Enhanced
 96 |     ) => (...payload: any[]) => $Shape<State>,
 97 |   }
 98 | >(
 99 |   initialState: ((props: Enhanced) => State) | State,
100 |   stateUpdaters: StateHandlers
101 | ): HOC<
102 |   {
103 |     ...$Exact<Enhanced>,
104 |     ...$Exact<State>,
105 |     ...$ObjMap<
106 |       $ObjMap<StateHandlers, ExtractStateHandlersCodomain>,
107 |       ExtractToVoid
108 |     >,
109 |   },
110 |   Enhanced
111 | >
112 | 
113 | declare export function withHandlers<
114 |   Enhanced,
115 |   Handlers:
116 |     | ((
117 |         props: Enhanced
118 |       ) => {
119 |         [key: string]: (props: Enhanced) => Function,
120 |       })
121 |     | {
122 |         [key: string]: (props: Enhanced) => Function,
123 |       }
124 | >(
125 |   handlers: ((props: Enhanced) => Handlers) | Handlers
126 | ): HOC<
127 |   {
128 |     ...$Exact<Enhanced>,
129 |     ...$ObjMap<Handlers, ExtractHandlersCodomain>,
130 |   },
131 |   Enhanced
132 | >
133 | 
134 | declare export function pure<A>(a: Component<A>): Component<A>
135 | declare export function onlyUpdateForPropTypes<A>(a: Component<A>): Component<A>
136 | declare export function onlyUpdateForKeys<A>(Array<$Keys<A>>): HOC<A, A>
137 | declare export function shouldUpdate<A>(
138 |   (props: A, nextProps: A) => boolean
139 | ): HOC<A, A>
140 | 
141 | declare export function toClass<A>(a: Component<A>): Component<A>
142 | 
143 | declare export function withContext<A, ContextPropTypes, ContextObj>(
144 |   childContextTypes: ContextPropTypes,
145 |   getChildContext: (props: A) => ContextObj
146 | ): HOC<A, A>
147 | 
148 | declare export function getContext<CtxTypes, Enhanced>(
149 |   contextTypes: CtxTypes
150 | ): HOC<{ ...$Exact<Enhanced>, ...CtxTypes }, Enhanced>
151 | 
152 | /**
153 |  * It's wrong declaration but having that renderNothing and renderComponent are somehow useless
154 |  * outside branch enhancer, we just give it an id type
155 |  * so common way of using branch like
156 |  * `branch(testFn, renderNothing | renderComponent(Comp))` will work as expected.
157 |  * Tests are placed at test_branch.
158 |  */
159 | declare export function renderNothing<A>(C: Component<A>): Component<A>
160 | declare export function renderComponent<A>(a: Component<A>): HOC<A, A>
161 | 
162 | /**
163 |  * We make an assumtion that left and right have the same type if exists
164 |  */
165 | declare export function branch<Base, Enhanced>(
166 |   testFn: (props: Enhanced) => boolean,
167 |   // not a HOC because of inference problems, this works but HOC<Base, Enhanced> is not
168 |   left: (Component<Base>) => Component<Enhanced>,
169 |   // I never use right part and it can be a problem with inference as should be same type as left
170 |   right?: (Component<Base>) => Component<Enhanced>
171 | ): HOC<Base, Enhanced>
172 | 
173 | // test_statics
174 | declare export function setStatic<A>(key: string, value: any): HOC<A, A>
175 | declare export function setPropTypes<A>(propTypes: Object): HOC<A, A>
176 | declare export function setDisplayName<A>(displayName: string): HOC<A, A>
177 | 
178 | declare export function withPropsOnChange<BaseAdd, Enhanced>(
179 |   shouldMapOrKeys:
180 |     | ((props: Enhanced, nextProps: Enhanced) => boolean)
181 |     | Array<$Keys<Enhanced>>,
182 |   propsMapper: (ownerProps: Enhanced) => BaseAdd
183 | ): HOC<{ ...$Exact<Enhanced>, ...BaseAdd }, Enhanced>
184 | 
185 | // ---------------------------------------------------------------------------
186 | // ----------------===<<<TODO (UNSUPPORTED) HOCs>>>===------------------------
187 | // ---------------------------------------------------------------------------
188 | 
189 | // use withProps instead
190 | declare export function flattenProp<Base, Enhanced>(
191 |   propName: $Keys<Enhanced>
192 | ): HOC<Base, Enhanced>
193 | 
194 | // use withProps instead
195 | declare export function renameProp<Base, Enhanced>(
196 |   oldName: $Keys<Enhanced>,
197 |   newName: $Keys<Base>
198 | ): HOC<Base, Enhanced>
199 | 
200 | // use withProps instead
201 | declare export function renameProps<Base, Enhanced>(nameMap: {
202 |   [key: $Keys<Enhanced>]: $Keys<Base>,
203 | }): HOC<Base, Enhanced>
204 | 
205 | // use withStateHandlers instead
206 | declare export function withState<Base, Enhanced, T>(
207 |   stateName: string,
208 |   stateUpdaterName: string,
209 |   initialState: T | ((props: Enhanced) => T)
210 | ): HOC<Base, Enhanced>
211 | 
212 | // use withStateHandlers instead
213 | declare export function withReducer<A, B, Action, State>(
214 |   stateName: string,
215 |   dispatchName: string,
216 |   reducer: (state: State, action: Action) => State,
217 |   initialState: State
218 | ): HOC<A, B>
219 | 
220 | // lifecycle use React instead
221 | declare export function lifecycle<A, B>(spec: Object): HOC<A, B>
222 | 
223 | // Help needed, as explicitly providing the type
224 | // errors not detected, see TODO at test_mapPropsStream.js
225 | declare export function mapPropsStream<Base, Enhanced>(
226 |   (props$: any) => any
227 | ): HOC<Base, Enhanced>
228 | 
229 | // ---------------------------------------------------------------------------
230 | // -----------------------------===<<<Utils>>>===-----------------------------
231 | // ---------------------------------------------------------------------------
232 | 
233 | declare export function getDisplayName<A>(C: Component<A>): string
234 | 
235 | declare export function wrapDisplayName<A>(
236 |   C: Component<A>,
237 |   wrapperName: string
238 | ): string
239 | 
240 | declare export function shallowEqual(objA: mixed, objB: mixed): boolean
241 | 
242 | declare export function isClassComponent(value: any): boolean
243 | 
244 | declare export function createSink<A>(
245 |   callback: (props: A) => void
246 | ): Component<A>
247 | 
248 | declare export function componentFromProp<A>(propName: string): Component<A>
249 | 
250 | declare export function nest<A>(
251 |   ...Components: Array<Component<any> | string>
252 | ): Component<A>
253 | 
254 | declare export function hoistStatics<A, B, H: HOC<A, B>>(hoc: H): H
255 | 
256 | declare export function componentFromStream<T>(
257 |   (props$: any) => any
258 | ): T => React$Element<any>
259 | 
260 | declare export function createEventHandler(): {
261 |   stream: any,
262 |   handler: Function,
263 | }
264 | 
265 | declare export function toRenderProps<B, E>(
266 |   hoc: HOC<B, E>
267 | ): React$ComponentType<{|
268 |   ...$Exact<E>,
269 |   children: (b: B) => React$Node,
270 | |}>
271 | 
272 | declare export function fromRenderProps<B, E, RenderPropName, Props>(
273 |   RenderPropsComponent: Component<{
274 |     [RenderPropName]: (...props: Props) => React$Node,
275 |   }>,
276 |   propsMapper: ((...props: Props) => B),
277 |   renderPropName?: RenderPropName
278 | ): HOC<{ ...$Exact<E>, ...B }, E>
279 | 


--------------------------------------------------------------------------------
/src/packages/recompose/isClassComponent.js:
--------------------------------------------------------------------------------
1 | const isClassComponent = Component =>
2 |   Boolean(
3 |     Component &&
4 |       Component.prototype &&
5 |       typeof Component.prototype.render === 'function'
6 |   )
7 | 
8 | export default isClassComponent
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/kefirObservableConfig.js:
--------------------------------------------------------------------------------
1 | import Kefir from 'kefir'
2 | 
3 | const config = {
4 |   fromESObservable: Kefir.fromESObservable,
5 |   toESObservable: stream => stream.toESObservable(),
6 | }
7 | 
8 | export default config
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/lifecycle.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-console */
 2 | import { createFactory, Component } from 'react'
 3 | import setDisplayName from './setDisplayName'
 4 | import wrapDisplayName from './wrapDisplayName'
 5 | 
 6 | const lifecycle = spec => BaseComponent => {
 7 |   const factory = createFactory(BaseComponent)
 8 | 
 9 |   if (process.env.NODE_ENV !== 'production' && spec.hasOwnProperty('render')) {
10 |     console.error(
11 |       'lifecycle() does not support the render method; its behavior is to ' +
12 |         'pass all props and state to the base component.'
13 |     )
14 |   }
15 | 
16 |   class Lifecycle extends Component {
17 |     render() {
18 |       return factory({
19 |         ...this.props,
20 |         ...this.state,
21 |       })
22 |     }
23 |   }
24 | 
25 |   Object.keys(spec).forEach(hook => (Lifecycle.prototype[hook] = spec[hook]))
26 | 
27 |   if (process.env.NODE_ENV !== 'production') {
28 |     return setDisplayName(wrapDisplayName(BaseComponent, 'lifecycle'))(
29 |       Lifecycle
30 |     )
31 |   }
32 |   return Lifecycle
33 | }
34 | 
35 | export default lifecycle
36 | 


--------------------------------------------------------------------------------
/src/packages/recompose/mapProps.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const mapProps = propsMapper => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   const MapProps = props => factory(propsMapper(props))
 8 |   if (process.env.NODE_ENV !== 'production') {
 9 |     return setDisplayName(wrapDisplayName(BaseComponent, 'mapProps'))(MapProps)
10 |   }
11 |   return MapProps
12 | }
13 | 
14 | export default mapProps
15 | 


--------------------------------------------------------------------------------
/src/packages/recompose/mapPropsStream.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import $observable from 'symbol-observable'
 3 | import { componentFromStreamWithConfig } from './componentFromStream'
 4 | import setDisplayName from './setDisplayName'
 5 | import wrapDisplayName from './wrapDisplayName'
 6 | import { config as globalConfig } from './setObservableConfig'
 7 | 
 8 | const identity = t => t
 9 | 
10 | export const mapPropsStreamWithConfig = config => {
11 |   const componentFromStream = componentFromStreamWithConfig({
12 |     fromESObservable: identity,
13 |     toESObservable: identity,
14 |   })
15 |   return transform => BaseComponent => {
16 |     const factory = createFactory(BaseComponent)
17 |     const { fromESObservable, toESObservable } = config
18 |     return componentFromStream(props$ => ({
19 |       subscribe(observer) {
20 |         const subscription = toESObservable(
21 |           transform(fromESObservable(props$))
22 |         ).subscribe({
23 |           next: childProps => observer.next(factory(childProps)),
24 |         })
25 |         return {
26 |           unsubscribe: () => subscription.unsubscribe(),
27 |         }
28 |       },
29 |       [$observable]() {
30 |         return this
31 |       },
32 |     }))
33 |   }
34 | }
35 | 
36 | const mapPropsStream = transform => {
37 |   const hoc = mapPropsStreamWithConfig(globalConfig)(transform)
38 | 
39 |   if (process.env.NODE_ENV !== 'production') {
40 |     return BaseComponent =>
41 |       setDisplayName(wrapDisplayName(BaseComponent, 'mapPropsStream'))(
42 |         hoc(BaseComponent)
43 |       )
44 |   }
45 |   return hoc
46 | }
47 | 
48 | export default mapPropsStream
49 | 


--------------------------------------------------------------------------------
/src/packages/recompose/mostObservableConfig.js:
--------------------------------------------------------------------------------
1 | import { from, Stream } from 'most'
2 | 
3 | const config = {
4 |   fromESObservable: from || Stream.from,
5 |   toESObservable: stream => stream,
6 | }
7 | 
8 | export default config
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/nest.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import getDisplayName from './getDisplayName'
 3 | 
 4 | const nest = (...Components) => {
 5 |   const factories = Components.map(createFactory)
 6 |   const Nest = ({ children, ...props }) =>
 7 |     factories.reduceRight((child, factory) => factory(props, child), children)
 8 | 
 9 |   if (process.env.NODE_ENV !== 'production') {
10 |     const displayNames = Components.map(getDisplayName)
11 |     Nest.displayName = `nest(${displayNames.join(', ')})`
12 |   }
13 | 
14 |   return Nest
15 | }
16 | 
17 | export default nest
18 | 


--------------------------------------------------------------------------------
/src/packages/recompose/onlyUpdateForKeys.js:
--------------------------------------------------------------------------------
 1 | import shouldUpdate from './shouldUpdate'
 2 | import shallowEqual from './shallowEqual'
 3 | import setDisplayName from './setDisplayName'
 4 | import wrapDisplayName from './wrapDisplayName'
 5 | import pick from './utils/pick'
 6 | 
 7 | const onlyUpdateForKeys = propKeys => {
 8 |   const hoc = shouldUpdate(
 9 |     (props, nextProps) =>
10 |       !shallowEqual(pick(nextProps, propKeys), pick(props, propKeys))
11 |   )
12 | 
13 |   if (process.env.NODE_ENV !== 'production') {
14 |     return BaseComponent =>
15 |       setDisplayName(wrapDisplayName(BaseComponent, 'onlyUpdateForKeys'))(
16 |         hoc(BaseComponent)
17 |       )
18 |   }
19 |   return hoc
20 | }
21 | 
22 | export default onlyUpdateForKeys
23 | 


--------------------------------------------------------------------------------
/src/packages/recompose/onlyUpdateForPropTypes.js:
--------------------------------------------------------------------------------
 1 | import onlyUpdateForKeys from './onlyUpdateForKeys'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | import getDisplayName from './getDisplayName'
 5 | 
 6 | const onlyUpdateForPropTypes = BaseComponent => {
 7 |   const propTypes = BaseComponent.propTypes
 8 | 
 9 |   if (process.env.NODE_ENV !== 'production') {
10 |     if (!propTypes) {
11 |       /* eslint-disable */
12 |       console.error(
13 |         'A component without any `propTypes` was passed to ' +
14 |           '`onlyUpdateForPropTypes()`. Check the implementation of the ' +
15 |           `component with display name "${getDisplayName(BaseComponent)}".`
16 |       )
17 |       /* eslint-enable */
18 |     }
19 |   }
20 | 
21 |   const propKeys = Object.keys(propTypes || {})
22 |   const OnlyUpdateForPropTypes = onlyUpdateForKeys(propKeys)(BaseComponent)
23 | 
24 |   if (process.env.NODE_ENV !== 'production') {
25 |     return setDisplayName(
26 |       wrapDisplayName(BaseComponent, 'onlyUpdateForPropTypes')
27 |     )(OnlyUpdateForPropTypes)
28 |   }
29 |   return OnlyUpdateForPropTypes
30 | }
31 | 
32 | export default onlyUpdateForPropTypes
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "description": "A React utility belt for function components and higher-order components",
 3 |   "keywords": [
 4 |     "react",
 5 |     "higher-order",
 6 |     "components",
 7 |     "microcomponentization",
 8 |     "toolkit",
 9 |     "utilities",
10 |     "composition"
11 |   ],
12 |   "main": "dist/Recompose.cjs.js",
13 |   "module": "dist/Recompose.esm.js",
14 |   "dependencies": {
15 |     "@babel/runtime": "^7.0.0",
16 |     "change-emitter": "^0.1.2",
17 |     "hoist-non-react-statics": "^2.3.1",
18 |     "react-lifecycles-compat": "^3.0.2",
19 |     "symbol-observable": "^1.0.4"
20 |   },
21 |   "peerDependencies": {
22 |     "react": "^0.14.0 || ^15.0.0 || ^16.0.0"
23 |   }
24 | }
25 | 


--------------------------------------------------------------------------------
/src/packages/recompose/pure.js:
--------------------------------------------------------------------------------
 1 | import shouldUpdate from './shouldUpdate'
 2 | import shallowEqual from './shallowEqual'
 3 | import setDisplayName from './setDisplayName'
 4 | import wrapDisplayName from './wrapDisplayName'
 5 | 
 6 | const pure = BaseComponent => {
 7 |   const hoc = shouldUpdate(
 8 |     (props, nextProps) => !shallowEqual(props, nextProps)
 9 |   )
10 | 
11 |   if (process.env.NODE_ENV !== 'production') {
12 |     return setDisplayName(wrapDisplayName(BaseComponent, 'pure'))(
13 |       hoc(BaseComponent)
14 |     )
15 |   }
16 | 
17 |   return hoc(BaseComponent)
18 | }
19 | 
20 | export default pure
21 | 


--------------------------------------------------------------------------------
/src/packages/recompose/renameProp.js:
--------------------------------------------------------------------------------
 1 | import omit from './utils/omit'
 2 | import mapProps from './mapProps'
 3 | import setDisplayName from './setDisplayName'
 4 | import wrapDisplayName from './wrapDisplayName'
 5 | 
 6 | const renameProp = (oldName, newName) => {
 7 |   const hoc = mapProps(props => ({
 8 |     ...omit(props, [oldName]),
 9 |     [newName]: props[oldName],
10 |   }))
11 |   if (process.env.NODE_ENV !== 'production') {
12 |     return BaseComponent =>
13 |       setDisplayName(wrapDisplayName(BaseComponent, 'renameProp'))(
14 |         hoc(BaseComponent)
15 |       )
16 |   }
17 |   return hoc
18 | }
19 | 
20 | export default renameProp
21 | 


--------------------------------------------------------------------------------
/src/packages/recompose/renameProps.js:
--------------------------------------------------------------------------------
 1 | import omit from './utils/omit'
 2 | import pick from './utils/pick'
 3 | import mapProps from './mapProps'
 4 | import setDisplayName from './setDisplayName'
 5 | import wrapDisplayName from './wrapDisplayName'
 6 | 
 7 | const { keys } = Object
 8 | 
 9 | const mapKeys = (obj, func) =>
10 |   keys(obj).reduce((result, key) => {
11 |     const val = obj[key]
12 |     /* eslint-disable no-param-reassign */
13 |     result[func(val, key)] = val
14 |     /* eslint-enable no-param-reassign */
15 |     return result
16 |   }, {})
17 | 
18 | const renameProps = nameMap => {
19 |   const hoc = mapProps(props => ({
20 |     ...omit(props, keys(nameMap)),
21 |     ...mapKeys(pick(props, keys(nameMap)), (_, oldName) => nameMap[oldName]),
22 |   }))
23 |   if (process.env.NODE_ENV !== 'production') {
24 |     return BaseComponent =>
25 |       setDisplayName(wrapDisplayName(BaseComponent, 'renameProps'))(
26 |         hoc(BaseComponent)
27 |       )
28 |   }
29 |   return hoc
30 | }
31 | 
32 | export default renameProps
33 | 


--------------------------------------------------------------------------------
/src/packages/recompose/renderComponent.js:
--------------------------------------------------------------------------------
 1 | import { createFactory } from 'react'
 2 | import wrapDisplayName from './wrapDisplayName'
 3 | 
 4 | const renderComponent = Component => _ => {
 5 |   const factory = createFactory(Component)
 6 |   const RenderComponent = props => factory(props)
 7 |   if (process.env.NODE_ENV !== 'production') {
 8 |     RenderComponent.displayName = wrapDisplayName(Component, 'renderComponent')
 9 |   }
10 |   return RenderComponent
11 | }
12 | 
13 | export default renderComponent
14 | 


--------------------------------------------------------------------------------
/src/packages/recompose/renderNothing.js:
--------------------------------------------------------------------------------
 1 | import { Component } from 'react'
 2 | 
 3 | class Nothing extends Component {
 4 |   render() {
 5 |     return null
 6 |   }
 7 | }
 8 | 
 9 | const renderNothing = _ => Nothing
10 | 
11 | export default renderNothing
12 | 


--------------------------------------------------------------------------------
/src/packages/recompose/rxjs4ObservableConfig.js:
--------------------------------------------------------------------------------
 1 | import $observable from 'symbol-observable'
 2 | import Rx from 'rx'
 3 | 
 4 | const config = {
 5 |   fromESObservable: observable =>
 6 |     Rx.Observable.create(observer => {
 7 |       const { unsubscribe } = observable.subscribe({
 8 |         next: val => observer.onNext(val),
 9 |         error: error => observer.onError(error),
10 |         complete: () => observer.onCompleted(),
11 |       })
12 |       return unsubscribe
13 |     }),
14 |   toESObservable: rxObservable => ({
15 |     subscribe: observer => {
16 |       const subscription = rxObservable.subscribe(
17 |         val => observer.next(val),
18 |         error => observer.error(error),
19 |         () => observer.complete()
20 |       )
21 |       return { unsubscribe: () => subscription.dispose() }
22 |     },
23 |     [$observable]() {
24 |       return this
25 |     },
26 |   }),
27 | }
28 | 
29 | export default config
30 | 


--------------------------------------------------------------------------------
/src/packages/recompose/rxjsObservableConfig.js:
--------------------------------------------------------------------------------
1 | import Rx from 'rxjs'
2 | 
3 | const config = {
4 |   fromESObservable: Rx.Observable.from,
5 |   toESObservable: stream => stream,
6 | }
7 | 
8 | export default config
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/setDisplayName.js:
--------------------------------------------------------------------------------
1 | import setStatic from './setStatic'
2 | 
3 | const setDisplayName = displayName => setStatic('displayName', displayName)
4 | 
5 | export default setDisplayName
6 | 


--------------------------------------------------------------------------------
/src/packages/recompose/setObservableConfig.js:
--------------------------------------------------------------------------------
 1 | let _config = {
 2 |   fromESObservable: null,
 3 |   toESObservable: null,
 4 | }
 5 | 
 6 | const configureObservable = c => {
 7 |   _config = c
 8 | }
 9 | 
10 | export const config = {
11 |   fromESObservable: observable =>
12 |     typeof _config.fromESObservable === 'function'
13 |       ? _config.fromESObservable(observable)
14 |       : observable,
15 |   toESObservable: stream =>
16 |     typeof _config.toESObservable === 'function'
17 |       ? _config.toESObservable(stream)
18 |       : stream,
19 | }
20 | 
21 | export default configureObservable
22 | 


--------------------------------------------------------------------------------
/src/packages/recompose/setPropTypes.js:
--------------------------------------------------------------------------------
1 | import setStatic from './setStatic'
2 | 
3 | const setPropTypes = propTypes => setStatic('propTypes', propTypes)
4 | 
5 | export default setPropTypes
6 | 


--------------------------------------------------------------------------------
/src/packages/recompose/setStatic.js:
--------------------------------------------------------------------------------
1 | const setStatic = (key, value) => BaseComponent => {
2 |   /* eslint-disable no-param-reassign */
3 |   BaseComponent[key] = value
4 |   /* eslint-enable no-param-reassign */
5 |   return BaseComponent
6 | }
7 | 
8 | export default setStatic
9 | 


--------------------------------------------------------------------------------
/src/packages/recompose/shallowEqual.js:
--------------------------------------------------------------------------------
 1 | /**
 2 |  * Copyright (c) 2013-present, Facebook, Inc.
 3 |  *
 4 |  * This source code is licensed under the MIT license found in the
 5 |  * LICENSE file in the root directory of this source tree.
 6 |  *
 7 |  * @providesModule shallowEqual
 8 |  * @typechecks
 9 |  */
10 | 
11 | /* eslint-disable no-self-compare */
12 | 
13 | const hasOwnProperty = Object.prototype.hasOwnProperty
14 | 
15 | /**
16 |  * inlined Object.is polyfill to avoid requiring consumers ship their own
17 |  * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
18 |  */
19 | function is(x, y) {
20 |   // SameValue algorithm
21 |   if (x === y) {
22 |     // Steps 1-5, 7-10
23 |     // Steps 6.b-6.e: +0 != -0
24 |     // Added the nonzero y check to make Flow happy, but it is redundant
25 |     return x !== 0 || y !== 0 || 1 / x === 1 / y
26 |   }
27 |   // Step 6.a: NaN == NaN
28 |   return x !== x && y !== y
29 | }
30 | 
31 | /**
32 |  * Performs equality by iterating through keys on an object and returning false
33 |  * when any key has values which are not strictly equal between the arguments.
34 |  * Returns true when the values of all keys are strictly equal.
35 |  */
36 | function shallowEqual(objA, objB) {
37 |   if (is(objA, objB)) {
38 |     return true
39 |   }
40 | 
41 |   if (
42 |     typeof objA !== 'object' ||
43 |     objA === null ||
44 |     typeof objB !== 'object' ||
45 |     objB === null
46 |   ) {
47 |     return false
48 |   }
49 | 
50 |   const keysA = Object.keys(objA)
51 |   const keysB = Object.keys(objB)
52 | 
53 |   if (keysA.length !== keysB.length) {
54 |     return false
55 |   }
56 | 
57 |   // Test for A's keys different from B.
58 |   for (let i = 0; i < keysA.length; i++) {
59 |     if (
60 |       !hasOwnProperty.call(objB, keysA[i]) ||
61 |       !is(objA[keysA[i]], objB[keysA[i]])
62 |     ) {
63 |       return false
64 |     }
65 |   }
66 | 
67 |   return true
68 | }
69 | 
70 | export default shallowEqual
71 | 


--------------------------------------------------------------------------------
/src/packages/recompose/shouldUpdate.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const shouldUpdate = test => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   class ShouldUpdate extends Component {
 8 |     shouldComponentUpdate(nextProps) {
 9 |       return test(this.props, nextProps)
10 |     }
11 | 
12 |     render() {
13 |       return factory(this.props)
14 |     }
15 |   }
16 | 
17 |   if (process.env.NODE_ENV !== 'production') {
18 |     return setDisplayName(wrapDisplayName(BaseComponent, 'shouldUpdate'))(
19 |       ShouldUpdate
20 |     )
21 |   }
22 |   return ShouldUpdate
23 | }
24 | 
25 | export default shouldUpdate
26 | 


--------------------------------------------------------------------------------
/src/packages/recompose/toClass.js:
--------------------------------------------------------------------------------
 1 | import React, { Component } from 'react'
 2 | import getDisplayName from './getDisplayName'
 3 | import isClassComponent from './isClassComponent'
 4 | 
 5 | const toClass = baseComponent =>
 6 |   isClassComponent(baseComponent)
 7 |     ? baseComponent
 8 |     : class ToClass extends Component {
 9 |         static displayName = getDisplayName(baseComponent)
10 |         static propTypes = baseComponent.propTypes
11 |         static contextTypes = baseComponent.contextTypes
12 |         static defaultProps = baseComponent.defaultProps
13 |         render() {
14 |           if (typeof baseComponent === 'string') {
15 |             return React.createElement(baseComponent, this.props)
16 |           }
17 |           return baseComponent(this.props, this.context)
18 |         }
19 |       }
20 | export default toClass
21 | 


--------------------------------------------------------------------------------
/src/packages/recompose/toRenderProps.js:
--------------------------------------------------------------------------------
1 | export default function toRenderProps(hoc) {
2 |   const RenderPropsComponent = props => props.children(props)
3 |   return hoc(RenderPropsComponent)
4 | }
5 | 


--------------------------------------------------------------------------------
/src/packages/recompose/utils/mapValues.js:
--------------------------------------------------------------------------------
 1 | const mapValues = (obj, func) => {
 2 |   const result = {}
 3 |   /* eslint-disable no-restricted-syntax */
 4 |   for (const key in obj) {
 5 |     if (obj.hasOwnProperty(key)) {
 6 |       result[key] = func(obj[key], key)
 7 |     }
 8 |   }
 9 |   /* eslint-enable no-restricted-syntax */
10 |   return result
11 | }
12 | 
13 | export default mapValues
14 | 


--------------------------------------------------------------------------------
/src/packages/recompose/utils/omit.js:
--------------------------------------------------------------------------------
 1 | const omit = (obj, keys) => {
 2 |   const { ...rest } = obj
 3 |   for (let i = 0; i < keys.length; i++) {
 4 |     const key = keys[i]
 5 |     if (rest.hasOwnProperty(key)) {
 6 |       delete rest[key]
 7 |     }
 8 |   }
 9 |   return rest
10 | }
11 | 
12 | export default omit
13 | 


--------------------------------------------------------------------------------
/src/packages/recompose/utils/pick.js:
--------------------------------------------------------------------------------
 1 | const pick = (obj, keys) => {
 2 |   const result = {}
 3 |   for (let i = 0; i < keys.length; i++) {
 4 |     const key = keys[i]
 5 |     if (obj.hasOwnProperty(key)) {
 6 |       result[key] = obj[key]
 7 |     }
 8 |   }
 9 |   return result
10 | }
11 | 
12 | export default pick
13 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withContext.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const withContext = (childContextTypes, getChildContext) => BaseComponent => {
 6 |   const factory = createFactory(BaseComponent)
 7 |   class WithContext extends Component {
 8 |     getChildContext = () => getChildContext(this.props)
 9 | 
10 |     render() {
11 |       return factory(this.props)
12 |     }
13 |   }
14 | 
15 |   WithContext.childContextTypes = childContextTypes
16 | 
17 |   if (process.env.NODE_ENV !== 'production') {
18 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withContext'))(
19 |       WithContext
20 |     )
21 |   }
22 |   return WithContext
23 | }
24 | 
25 | export default withContext
26 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withHandlers.js:
--------------------------------------------------------------------------------
 1 | /* eslint-disable no-console */
 2 | import { createFactory, Component } from 'react'
 3 | import setDisplayName from './setDisplayName'
 4 | import wrapDisplayName from './wrapDisplayName'
 5 | import mapValues from './utils/mapValues'
 6 | 
 7 | const withHandlers = handlers => BaseComponent => {
 8 |   const factory = createFactory(BaseComponent)
 9 |   class WithHandlers extends Component {
10 |     handlers = mapValues(
11 |       typeof handlers === 'function' ? handlers(this.props) : handlers,
12 |       createHandler => (...args) => {
13 |         const handler = createHandler(this.props)
14 | 
15 |         if (
16 |           process.env.NODE_ENV !== 'production' &&
17 |           typeof handler !== 'function'
18 |         ) {
19 |           console.error(
20 |             // eslint-disable-line no-console
21 |             'withHandlers(): Expected a map of higher-order functions. ' +
22 |               'Refer to the docs for more info.'
23 |           )
24 |         }
25 | 
26 |         return handler(...args)
27 |       }
28 |     )
29 | 
30 |     render() {
31 |       return factory({
32 |         ...this.props,
33 |         ...this.handlers,
34 |       })
35 |     }
36 |   }
37 | 
38 |   if (process.env.NODE_ENV !== 'production') {
39 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withHandlers'))(
40 |       WithHandlers
41 |     )
42 |   }
43 |   return WithHandlers
44 | }
45 | 
46 | export default withHandlers
47 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withProps.js:
--------------------------------------------------------------------------------
 1 | import wrapDisplayName from './wrapDisplayName'
 2 | import setDisplayName from './setDisplayName'
 3 | import mapProps from './mapProps'
 4 | 
 5 | const withProps = input => {
 6 |   const hoc = mapProps(props => ({
 7 |     ...props,
 8 |     ...(typeof input === 'function' ? input(props) : input),
 9 |   }))
10 |   if (process.env.NODE_ENV !== 'production') {
11 |     return BaseComponent =>
12 |       setDisplayName(wrapDisplayName(BaseComponent, 'withProps'))(
13 |         hoc(BaseComponent)
14 |       )
15 |   }
16 |   return hoc
17 | }
18 | 
19 | export default withProps
20 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withPropsOnChange.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import { polyfill } from 'react-lifecycles-compat'
 3 | import pick from './utils/pick'
 4 | import shallowEqual from './shallowEqual'
 5 | import setDisplayName from './setDisplayName'
 6 | import wrapDisplayName from './wrapDisplayName'
 7 | 
 8 | const withPropsOnChange = (shouldMapOrKeys, propsMapper) => BaseComponent => {
 9 |   const factory = createFactory(BaseComponent)
10 |   const shouldMap =
11 |     typeof shouldMapOrKeys === 'function'
12 |       ? shouldMapOrKeys
13 |       : (props, nextProps) =>
14 |           !shallowEqual(
15 |             pick(props, shouldMapOrKeys),
16 |             pick(nextProps, shouldMapOrKeys)
17 |           )
18 | 
19 |   class WithPropsOnChange extends Component {
20 |     state = {
21 |       computedProps: propsMapper(this.props),
22 |       prevProps: this.props,
23 |     }
24 | 
25 |     static getDerivedStateFromProps(nextProps, prevState) {
26 |       if (shouldMap(prevState.prevProps, nextProps)) {
27 |         return {
28 |           computedProps: propsMapper(nextProps),
29 |           prevProps: nextProps,
30 |         }
31 |       }
32 | 
33 |       return {
34 |         prevProps: nextProps,
35 |       }
36 |     }
37 | 
38 |     render() {
39 |       return factory({
40 |         ...this.props,
41 |         ...this.state.computedProps,
42 |       })
43 |     }
44 |   }
45 | 
46 |   polyfill(WithPropsOnChange)
47 | 
48 |   if (process.env.NODE_ENV !== 'production') {
49 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withPropsOnChange'))(
50 |       WithPropsOnChange
51 |     )
52 |   }
53 | 
54 |   return WithPropsOnChange
55 | }
56 | 
57 | export default withPropsOnChange
58 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withReducer.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const noop = () => {}
 6 | 
 7 | const withReducer = (
 8 |   stateName,
 9 |   dispatchName,
10 |   reducer,
11 |   initialState
12 | ) => BaseComponent => {
13 |   const factory = createFactory(BaseComponent)
14 |   class WithReducer extends Component {
15 |     state = {
16 |       stateValue: this.initializeStateValue(),
17 |     }
18 | 
19 |     initializeStateValue() {
20 |       if (initialState !== undefined) {
21 |         return typeof initialState === 'function'
22 |           ? initialState(this.props)
23 |           : initialState
24 |       }
25 |       return reducer(undefined, { type: '@@recompose/INIT' })
26 |     }
27 | 
28 |     dispatch = (action, callback = noop) =>
29 |       this.setState(
30 |         ({ stateValue }) => ({
31 |           stateValue: reducer(stateValue, action),
32 |         }),
33 |         () => callback(this.state.stateValue)
34 |       )
35 | 
36 |     render() {
37 |       return factory({
38 |         ...this.props,
39 |         [stateName]: this.state.stateValue,
40 |         [dispatchName]: this.dispatch,
41 |       })
42 |     }
43 |   }
44 | 
45 |   if (process.env.NODE_ENV !== 'production') {
46 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withReducer'))(
47 |       WithReducer
48 |     )
49 |   }
50 |   return WithReducer
51 | }
52 | 
53 | export default withReducer
54 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withState.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | 
 5 | const withState = (
 6 |   stateName,
 7 |   stateUpdaterName,
 8 |   initialState
 9 | ) => BaseComponent => {
10 |   const factory = createFactory(BaseComponent)
11 |   class WithState extends Component {
12 |     state = {
13 |       stateValue:
14 |         typeof initialState === 'function'
15 |           ? initialState(this.props)
16 |           : initialState,
17 |     }
18 | 
19 |     updateStateValue = (updateFn, callback) =>
20 |       this.setState(
21 |         ({ stateValue }) => ({
22 |           stateValue:
23 |             typeof updateFn === 'function' ? updateFn(stateValue) : updateFn,
24 |         }),
25 |         callback
26 |       )
27 | 
28 |     render() {
29 |       return factory({
30 |         ...this.props,
31 |         [stateName]: this.state.stateValue,
32 |         [stateUpdaterName]: this.updateStateValue,
33 |       })
34 |     }
35 |   }
36 | 
37 |   if (process.env.NODE_ENV !== 'production') {
38 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withState'))(
39 |       WithState
40 |     )
41 |   }
42 |   return WithState
43 | }
44 | 
45 | export default withState
46 | 


--------------------------------------------------------------------------------
/src/packages/recompose/withStateHandlers.js:
--------------------------------------------------------------------------------
 1 | import { createFactory, Component } from 'react'
 2 | import setDisplayName from './setDisplayName'
 3 | import wrapDisplayName from './wrapDisplayName'
 4 | import mapValues from './utils/mapValues'
 5 | 
 6 | const withStateHandlers = (initialState, stateUpdaters) => BaseComponent => {
 7 |   const factory = createFactory(BaseComponent)
 8 | 
 9 |   class WithStateHandlers extends Component {
10 |     state = typeof initialState === 'function'
11 |       ? initialState(this.props)
12 |       : initialState
13 | 
14 |     stateUpdaters = mapValues(
15 |       stateUpdaters,
16 |       handler => (mayBeEvent, ...args) => {
17 |         // Having that functional form of setState can be called async
18 |         // we need to persist SyntheticEvent
19 |         if (mayBeEvent && typeof mayBeEvent.persist === 'function') {
20 |           mayBeEvent.persist()
21 |         }
22 | 
23 |         this.setState((state, props) =>
24 |           handler(state, props)(mayBeEvent, ...args)
25 |         )
26 |       }
27 |     )
28 | 
29 |     render() {
30 |       return factory({
31 |         ...this.props,
32 |         ...this.state,
33 |         ...this.stateUpdaters,
34 |       })
35 |     }
36 |   }
37 | 
38 |   if (process.env.NODE_ENV !== 'production') {
39 |     return setDisplayName(wrapDisplayName(BaseComponent, 'withStateHandlers'))(
40 |       WithStateHandlers
41 |     )
42 |   }
43 |   return WithStateHandlers
44 | }
45 | 
46 | export default withStateHandlers
47 | 


--------------------------------------------------------------------------------
/src/packages/recompose/wrapDisplayName.js:
--------------------------------------------------------------------------------
1 | import getDisplayName from './getDisplayName'
2 | 
3 | const wrapDisplayName = (BaseComponent, hocName) =>
4 |   `${hocName}(${getDisplayName(BaseComponent)})`
5 | 
6 | export default wrapDisplayName
7 | 


--------------------------------------------------------------------------------
/src/packages/recompose/xstreamObservableConfig.js:
--------------------------------------------------------------------------------
 1 | import $observable from 'symbol-observable'
 2 | import xstream from 'xstream'
 3 | 
 4 | const noop = () => {}
 5 | 
 6 | const config = {
 7 |   fromESObservable: observable =>
 8 |     xstream.create({
 9 |       subscription: null,
10 |       start(listener) {
11 |         this.subscription = observable.subscribe(listener)
12 |       },
13 |       stop() {
14 |         this.subscription.unsubscribe()
15 |       },
16 |     }),
17 |   toESObservable: stream => ({
18 |     subscribe: observer => {
19 |       const listener = {
20 |         next: observer.next || noop,
21 |         error: observer.error || noop,
22 |         complete: observer.complete || noop,
23 |       }
24 |       stream.addListener(listener)
25 |       return {
26 |         unsubscribe: () => stream.removeListener(listener),
27 |       }
28 |     },
29 |     [$observable]() {
30 |       return this
31 |     },
32 |   }),
33 | }
34 | 
35 | export default config
36 | 


--------------------------------------------------------------------------------
/src/packages/recompose/yarn.lock:
--------------------------------------------------------------------------------
 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
 2 | # yarn lockfile v1
 3 | 
 4 | 
 5 | "@babel/runtime@^7.0.0":
 6 |   version "7.0.0"
 7 |   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.0.0.tgz#adeb78fedfc855aa05bc041640f3f6f98e85424c"
 8 |   integrity sha512-7hGhzlcmg01CvH1EHdSPVXYX1aJ8KCEyz6I9xYIi/asDtzBPMyMhVibhM/K6g/5qnKBwjZtp10bNZIEFTRW1MA==
 9 |   dependencies:
10 |     regenerator-runtime "^0.12.0"
11 | 
12 | change-emitter@^0.1.2:
13 |   version "0.1.6"
14 |   resolved "https://registry.yarnpkg.com/change-emitter/-/change-emitter-0.1.6.tgz#e8b2fe3d7f1ab7d69a32199aff91ea6931409515"
15 |   integrity sha1-6LL+PX8at9aaMhma/5HqaTFAlRU=
16 | 
17 | hoist-non-react-statics@^2.3.1:
18 |   version "2.3.1"
19 |   resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.3.1.tgz#343db84c6018c650778898240135a1420ee22ce0"
20 |   integrity sha1-ND24TGAYxlB3iJgkATWhQg7iLOA=
21 | 
22 | react-lifecycles-compat@^3.0.2:
23 |   version "3.0.2"
24 |   resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-3.0.2.tgz#7279047275bd727a912e25f734c0559527e84eff"
25 |   integrity sha512-pbZOSMVVkvppW7XRn9fcHK5OgEDnYLwMva7P6TgS44/SN9uGGjfh3Z1c8tomO+y4IsHQ6Fsz2EGwmE7sMeNZgQ==
26 | 
27 | regenerator-runtime@^0.12.0:
28 |   version "0.12.0"
29 |   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.0.tgz#8052ac952d85b10f3425192cd0c53f45cf65c6cb"
30 |   integrity sha512-SpV2LhF5Dm9UYMEprB3WwsBnWwqTrmjrm2UZb42cl2G02WVGgx7Mg8aa9pdLEKp6hZ+/abcMc2NxKA8f02EG2w==
31 | 
32 | symbol-observable@^1.0.4:
33 |   version "1.0.4"
34 |   resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.4.tgz#29bf615d4aa7121bdd898b22d4b3f9bc4e2aa03d"
35 |   integrity sha1-Kb9hXUqnEhvdiYsi1LP5vE4qoD0=
36 | 


--------------------------------------------------------------------------------
/src/packages/rx-recompose/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 | 
4 | 
5 | 


--------------------------------------------------------------------------------
/types/README.md:
--------------------------------------------------------------------------------
  1 | # Flow support for recompose
  2 | 
  3 | ## How it works
  4 | 
  5 | In most cases all you need is to declare a props type of enhanced Component.
  6 | Flow will infer all other types you need.
  7 | 
  8 | Example:
  9 | 
 10 | ```javascript
 11 | import type { HOC } from 'recompose';
 12 | 
 13 | type EnhancedComponentProps = {
 14 |   text?: string,
 15 | };
 16 | 
 17 | const baseComponent = ({ text }) => <div>{text}</div>;
 18 | 
 19 | const enhance:HOC<*, EnhancedComponentProps> = compose(
 20 |   defaultProps({
 21 |     text: 'world',
 22 |   }),
 23 |   withProps(({ text }) => ({
 24 |     text: `Hello ${text}`
 25 |   }))
 26 | );
 27 | 
 28 | export default enhance(baseComponent);
 29 | 
 30 | ```
 31 | 
 32 | See it in action.
 33 | 
 34 | ![recompose-flow](https://user-images.githubusercontent.com/5077042/28116959-0c96ae2c-6714-11e7-930e-b1454c629908.gif)
 35 | 
 36 | ## How to start
 37 | 
 38 | The easiest way is to start from example.
 39 | 
 40 | Look at [this](http://grader-meets-16837.netlify.com/) app [source](./flow-example)
 41 | 
 42 | Look at [library definitions and tests](./flow-typed/recompose_v0.24.x-/flow_v0.49.x-)
 43 | 
 44 | To add into project you can download library definitions [here](./flow-typed/recompose_v0.24.x/flow_v0.53.x-/recompose_v0.24.x.js) and add a path to it into `[lib]` section of `.flowconfig`.
 45 | 
 46 | Or use [flow-typed](https://github.com/flowtype/flow-typed)
 47 | 
 48 | ```bash
 49 | flow-typed install recompose@0.24.x
 50 | ```
 51 | 
 52 | ## Support
 53 | 
 54 | Type definitions of recompose HOCs are splitted into 2 parts.
 55 | 
 56 | ### Part 1 - HOCs with good flow support
 57 | 
 58 | In most cases you can use them without big issues.
 59 | Type inference and errors detection works near well.
 60 | 
 61 | These HOCs are: *defaultProps, mapProps, withProps, withStateHandlers, withHandlers, pure, onlyUpdateForKeys, shouldUpdate, renderNothing, renderComponent, branch, withPropsOnChange, onlyUpdateForPropTypes, toClass, withContext, getContext, setStatic, setPropTypes, setDisplayName*
 62 | 
 63 | #### Known issues for "good" HOCs
 64 | 
 65 | see `test_mapProps.js` - inference work but type errors are not detected in hocs
 66 | 
 67 | ### Part 2 - other HOCs
 68 | 
 69 | To use these HOCs - you need to provide type information (no automatic type inference).
 70 | You must be a good voodoo dancer.
 71 | 
 72 | See `test_voodoo.js` for the idea.
 73 | 
 74 | Some recomendations:
 75 | 
 76 | - *flattenProp,renameProp, renameProps* can easily be replaced with _withProps_
 77 | - *withReducer, withState* -> use _withStateHandlers_ instead
 78 | - _lifecycle_ -> you don't need recompose if you need a _lifecycle_, just use React class instead
 79 | - _mapPropsStream_ -> see `test_mapPropsStream.js`
 80 | 
 81 | #### Known issues for above HOCs
 82 | 
 83 | See `test_voodoo.js`, `test_mapPropsStream.js`
 84 | 
 85 | ### Utils
 86 | 
 87 | *getDisplayName, wrapDisplayName, shallowEqual,isClassComponent, createSink, componentFromProp, nest, hoistStatics.*
 88 | 
 89 | ### Articles 
 90 | 
 91 | [Typing Higher-order Components in Recompose With Flow](https://medium.com/flow-type/flow-support-in-recompose-1b76f58f4cfc)
 92 | 
 93 | ### Faq
 94 | 
 95 | Why to use existential type with `HOC<*, Blbla>` isn't it possible to avoid this?
 96 | 
 97 | *I tried to use type alias but haven't found how to make it work.*
 98 | 
 99 | ## Thanks
100 | 
101 | Big thanks to [@gcanti](https://github.com/gcanti) for his work on PR [#241](https://github.com/acdlite/recompose/pull/241), it was nice and clear base for current definitions.
102 | 


--------------------------------------------------------------------------------
/types/flow-example/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 |   "extends": "react-app"
3 | }
4 | 


--------------------------------------------------------------------------------
/types/flow-example/.flowconfig:
--------------------------------------------------------------------------------
 1 | [ignore]
 2 | .*/node_modules/eslint-plugin-jsx-a11y/.*
 3 | # TODO: remove after react-motion will be updated with new flow typedefs
 4 | .*/node_modules/react-motion/lib/*
 5 | 
 6 | [include]
 7 | 
 8 | [libs]
 9 | ../flow-typed/recompose_v0.24.x/flow_v0.55.x-/recompose_v0.24.x.js
10 | 
11 | [options]
12 | suppress_comment=\\(.\\|\n\\)*\\$ExpectError
13 | 
14 | [lints]
15 | 


--------------------------------------------------------------------------------
/types/flow-example/.gitignore:
--------------------------------------------------------------------------------
 1 | # See https://help.github.com/ignore-files/ for more about ignoring files.
 2 | 
 3 | # dependencies
 4 | /node_modules
 5 | 
 6 | # testing
 7 | /coverage
 8 | 
 9 | # production
10 | /build
11 | 
12 | # misc
13 | .DS_Store
14 | .env.local
15 | .env.development.local
16 | .env.test.local
17 | .env.production.local
18 | 
19 | npm-debug.log*
20 | yarn-debug.log*
21 | yarn-error.log*
22 | 


--------------------------------------------------------------------------------
/types/flow-example/README.md:
--------------------------------------------------------------------------------
1 | # recompose with flow usage example
2 | 
3 | This project was bootstrapped with [Create React App](https://github.com/facebookincubator/create-react-app).
4 | 


--------------------------------------------------------------------------------
/types/flow-example/flow-typed/glamor.js:
--------------------------------------------------------------------------------
 1 | declare module 'glamor' {
 2 |   declare type CSSF = (...style: Object[]) => Object
 3 |   declare type CSS = {
 4 |     insert: (css: string) => void,
 5 |     // hack https://github.com/facebook/flow/issues/2966
 6 |     $call: (...style: Object[]) => Object,
 7 |   }
 8 | 
 9 |   declare export var css: CSS
10 | }
11 | 


--------------------------------------------------------------------------------
/types/flow-example/flow-typed/react-motion.js:
--------------------------------------------------------------------------------
 1 | // TODO: remove after react-motion will be updated with new flow typedefs
 2 | declare module 'react-motion' {
 3 |   declare export function spring<A>(
 4 |     val: number,
 5 |     config?: A
 6 |   ): { val: number, ...$Exact<A> }
 7 | 
 8 |   declare export var TransitionMotion: React$ComponentType<{ styles: any }>
 9 | }
10 | 


--------------------------------------------------------------------------------
/types/flow-example/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "name": "coolmenu",
 3 |   "version": "0.1.0",
 4 |   "private": true,
 5 |   "dependencies": {
 6 |     "change-emitter": "^0.1.6",
 7 |     "flow": "^0.2.3",
 8 |     "flow-bin": "^0.55.0",
 9 |     "glamor": "^3.0.0-3",
10 |     "glamor-reset": "^3.0.0-2",
11 |     "hoist-non-react-statics": "^2.0.0",
12 |     "react": "^15.6.1",
13 |     "react-dom": "^15.6.1",
14 |     "react-motion": "^0.5.0",
15 |     "recompose": "^0.24.0"
16 |   },
17 |   "devDependencies": {
18 |     "react-scripts": "1.0.10"
19 |   },
20 |   "scripts": {
21 |     "start": "react-scripts start",
22 |     "build": "react-scripts build",
23 |     "flow": "flow"
24 |   }
25 | }
26 | 


--------------------------------------------------------------------------------
/types/flow-example/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/acdlite/recompose/3db12ce7121a050b533476958ff3d66ded1c4bb8/types/flow-example/public/favicon.ico


--------------------------------------------------------------------------------
/types/flow-example/public/index.html:
--------------------------------------------------------------------------------
 1 | <!doctype html>
 2 | <html lang="en">
 3 | 
 4 | <head>
 5 |   <meta charset="utf-8">
 6 |   <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
 7 |   <meta name="theme-color" content="#000000">
 8 |   <!--
 9 |       manifest.json provides metadata used when your web app is added to the
10 |       homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
11 |     -->
12 |   <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
13 |   <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
14 |   <!--
15 |       Notice the use of %PUBLIC_URL% in the tags above.
16 |       It will be replaced with the URL of the `public` folder during the build.
17 |       Only files inside the `public` folder can be referenced from the HTML.
18 | 
19 |       Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
20 |       work correctly both with client-side routing and a non-root public URL.
21 |       Learn how to configure a non-root public URL by running `npm run build`.
22 |     -->
23 |   <title>Recompose coolmenu</title>
24 | </head>
25 | 
26 | <body>
27 |   <noscript>
28 |     You need to enable JavaScript to run this app.
29 |   </noscript>
30 |   <div id="root"></div>
31 |   <!--
32 |       This HTML file is a template.
33 |       If you open it directly in the browser, you will see an empty page.
34 | 
35 |       You can add webfonts, meta tags, or analytics to this file.
36 |       The build step will place the bundled scripts into the <body> tag.
37 | 
38 |       To begin the development, run `npm start` or `yarn start`.
39 |       To create a production bundle, use `npm run build` or `yarn build`.
40 |     -->
41 | </body>
42 | 
43 | </html>


--------------------------------------------------------------------------------
/types/flow-example/public/manifest.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "short_name": "React App",
 3 |   "name": "Create React App Sample",
 4 |   "icons": [
 5 |     {
 6 |       "src": "favicon.ico",
 7 |       "sizes": "192x192",
 8 |       "type": "image/png"
 9 |     }
10 |   ],
11 |   "start_url": "./index.html",
12 |   "display": "standalone",
13 |   "theme_color": "#000000",
14 |   "background_color": "#ffffff"
15 | }
16 | 


--------------------------------------------------------------------------------
/types/flow-example/src/App.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | import React from 'react'
 3 | import { css } from 'glamor'
 4 | import { compose, defaultProps } from 'recompose'
 5 | import MouseDetector from './MouseDetector'
 6 | import ItemsAnimator from './ItemsAnimator'
 7 | import type { HOC } from 'recompose'
 8 | import type { MousePosition } from './MouseDetector'
 9 | 
10 | // Enhanced component props type
11 | type AppProps = {}
12 | 
13 | const app = ({ styles, items }) =>
14 |   <div {...styles.app}>
15 |     <div {...styles.header}>
16 |       <a href={'https://github.com/acdlite/recompose/types/flow-example'}>
17 |         Coolmenu
18 |       </a>{' '}
19 |       <span>recompose flow typed example</span>
20 |     </div>
21 |     <div {...styles.content}>
22 |       <MouseDetector>
23 |         {({ x, y }: MousePosition) =>
24 |           <ItemsAnimator items={items} spacing={-10} mousePos={{ x, y }} />}
25 |       </MouseDetector>
26 |     </div>
27 |     <div {...styles.footer}>
28 |       <span>created by</span>{' '}
29 |       <a href={'https://github.com/istarkov'}>Ivan Starkov</a>
30 |     </div>
31 |   </div>
32 | 
33 | const appEnhancer: HOC<*, AppProps> = compose(
34 |   defaultProps({
35 |     items: [
36 |       { id: 1, title: 'Recompose', color: '#FFB02E' },
37 |       { id: 2, title: 'Has', color: '#FFB02E' },
38 |       { id: 3, title: 'Flow', color: '#FFB02E' },
39 |       { id: 4, title: 'Support', color: '#FFB02E' },
40 |       { id: 5, title: 'Now!', color: '#FFB02E' },
41 |     ],
42 |     styles: {
43 |       app: css({
44 |         display: 'flex',
45 |         flex: 1,
46 |         flexDirection: 'column',
47 |       }),
48 |       header: css({
49 |         padding: '1rem 5rem',
50 |         borderBottom: '1px solid rgba(255,255,255,0.2)',
51 |         fontSize: '1.2rem',
52 |         backgroundColor: 'rgba(0,0,0,0.05)',
53 |         '>SPAN': {
54 |           fontSize: '0.8rem',
55 |         },
56 |         '>A': {
57 |           color: '#CCCCFF',
58 |           textDecoration: 'none',
59 |         },
60 |       }),
61 |       content: css({
62 |         display: 'flex',
63 |         flex: 1,
64 |         alignItems: 'center',
65 |         justifyContent: 'center',
66 |       }),
67 |       footer: css({
68 |         padding: '0.5rem 5rem',
69 |         marginTop: 'auto',
70 |         borderTop: '1px solid rgba(255,255,255,0.2)',
71 |         backgroundColor: 'rgba(0,0,0,0.05)',
72 |         textAlign: 'right',
73 |         '>SPAN': {
74 |           fontSize: '0.8rem',
75 |         },
76 |         '>A': {
77 |           color: '#CCCCFF',
78 |           textDecoration: 'none',
79 |         },
80 |       }),
81 |     },
82 |   })
83 | )
84 | 
85 | export default appEnhancer(app)
86 | 


--------------------------------------------------------------------------------
/types/flow-example/src/Item.js:
--------------------------------------------------------------------------------
  1 | /* @flow */
  2 | 
  3 | import React from 'react'
  4 | import { css } from 'glamor'
  5 | import { compose, defaultProps, withProps, withPropsOnChange } from 'recompose'
  6 | import type { HOC } from 'recompose'
  7 | 
  8 | // Props type of enhanced component
  9 | // It's the only props type we need to declare using supporting recompose enhancers
 10 | type ItemProps = {
 11 |   title: string,
 12 |   styles?: {
 13 |     component: Object,
 14 |     title: Object,
 15 |     border: Object,
 16 |   },
 17 |   size?: number,
 18 |   x?: number,
 19 |   y?: number,
 20 |   borderCount?: number,
 21 |   hovered?: boolean,
 22 |   color?: string,
 23 |   textColor?: string,
 24 |   hoveredColor?: string,
 25 | }
 26 | 
 27 | const item = ({ title, componentDynamicStyle, styles, borders }) =>
 28 |   <div {...styles.component} style={componentDynamicStyle}>
 29 |     <div {...styles.title}>
 30 |       {title}
 31 |     </div>
 32 |     {borders.map(({ style, id }) =>
 33 |       <div key={id} style={style} {...styles.border} />
 34 |     )}
 35 |   </div>
 36 | 
 37 | // set existential * type for base component,
 38 | // flow is smart enough to infer base component and enhancers props types
 39 | const enhanceItem: HOC<*, ItemProps> = compose(
 40 |   defaultProps({
 41 |     title: '',
 42 |     styles: {
 43 |       component: css({
 44 |         position: 'absolute',
 45 |         display: 'flex',
 46 |       }),
 47 |       title: css({
 48 |         margin: 'auto',
 49 |         color: 'deeppink',
 50 |         fontWeight: '600',
 51 |       }),
 52 |       border: css({
 53 |         position: 'absolute',
 54 |         border: '1px solid deeppink',
 55 |         left: 0,
 56 |         right: 0,
 57 |         top: 0,
 58 |         bottom: 0,
 59 |         borderRadius: 5,
 60 |         cursor: 'pointer',
 61 |       }),
 62 |     },
 63 |     size: 100,
 64 |     x: 0,
 65 |     y: 0,
 66 |     borderCount: 9,
 67 |     borderK: 2,
 68 |     hovered: false,
 69 |     color: '#CCCCFF',
 70 |     textColor: 'white',
 71 |     hoveredColor: 'white',
 72 |   }),
 73 |   /**
 74 |    * calculate css based on hovered prop
 75 |    * better to use withProps as glamour uses class caching
 76 |    * BTW it's flow example
 77 |    */
 78 |   withPropsOnChange(
 79 |     ['hovered', 'styles', 'color', 'hoveredColor', 'textColor'],
 80 |     ({ hovered, styles, color, textColor, hoveredColor }) => ({
 81 |       styles: {
 82 |         ...styles,
 83 |         title: hovered
 84 |           ? css(styles.title, { color: hoveredColor })
 85 |           : css(styles.title, { color: textColor }),
 86 | 
 87 |         border: hovered
 88 |           ? css(styles.border, { borderColor: hoveredColor })
 89 |           : css(styles.border, { borderColor: color }),
 90 |       },
 91 |     })
 92 |   ),
 93 |   /**
 94 |    * calculate component dynamic style
 95 |    */
 96 |   withProps(({ size, x, y, hovered }) => ({
 97 |     componentDynamicStyle: {
 98 |       width: size,
 99 |       height: size,
100 |       left: x - size / 2,
101 |       top: y - size / 2,
102 |       zIndex: hovered ? 1 : 0,
103 |     },
104 |   })),
105 |   /**
106 |    * generate borders props
107 |    */
108 |   withProps(({ borderCount, borderK }) => ({
109 |     borders: Array(borderCount).fill(0).map((_, index) => ({
110 |       id: index,
111 |       style: {
112 |         transform: `rotate(${borderK * Math.PI * index / borderCount}rad)`,
113 |         borderRadius: 5,
114 |       },
115 |     })),
116 |   }))
117 | )
118 | 
119 | export default enhanceItem(item)
120 | 


--------------------------------------------------------------------------------
/types/flow-example/src/ItemsAnimator.js:
--------------------------------------------------------------------------------
  1 | /* @flow */
  2 | 
  3 | import React from 'react'
  4 | import { css } from 'glamor'
  5 | import { compose, defaultProps, withHandlers, withProps } from 'recompose'
  6 | import Item from './Item'
  7 | import { TransitionMotion, spring } from 'react-motion'
  8 | // types
  9 | import type { HOC } from 'recompose'
 10 | import type { MousePosition } from './MouseDetector'
 11 | 
 12 | type ItemT = {
 13 |   id: number,
 14 |   title: string,
 15 |   color?: string,
 16 | }
 17 | 
 18 | // Props type of enhanced component
 19 | // It's the only props type we need to declare using supporting recompose enhancers
 20 | type ItemsAnimatorProps = {
 21 |   items: Array<ItemT>,
 22 |   config?: {
 23 |     size: number,
 24 |     hoverSize: number,
 25 |     hoverRotation: number,
 26 |     spacing: number,
 27 |   },
 28 |   mousePos: MousePosition,
 29 | }
 30 | 
 31 | // set existential * type for base component,
 32 | // flow is smart enough to infer base component and enhancers props types
 33 | const itemsAnimator = ({ styles, animStyles }) =>
 34 |   <TransitionMotion styles={animStyles}>
 35 |     {(
 36 |       interpolated: Array<{
 37 |         key: string,
 38 |         style: { x: number, y: number, size: number, borderK: number },
 39 |         data: { ...$Exact<ItemT>, hovered: boolean },
 40 |       }>
 41 |     ) =>
 42 |       <div {...styles.component}>
 43 |         {interpolated.map(({ key, data, style }) =>
 44 |           <Item
 45 |             key={key}
 46 |             color={data.color}
 47 |             title={data.title}
 48 |             size={style.size}
 49 |             hovered={data.hovered}
 50 |             x={style.x}
 51 |             y={style.y}
 52 |             borderK={style.borderK}
 53 |           />
 54 |         )}
 55 |       </div>}
 56 |   </TransitionMotion>
 57 | 
 58 | const enhanceItemsAnimator: HOC<*, ItemsAnimatorProps> = compose(
 59 |   /**
 60 |    * Defaults
 61 |    */
 62 |   defaultProps({
 63 |     styles: {
 64 |       component: css({
 65 |         position: 'absolute',
 66 |       }),
 67 |     },
 68 |     config: {
 69 |       size: 110,
 70 |       hoverSize: 150,
 71 |       hoverRotation: 2 * Math.PI,
 72 |       spacing: -10,
 73 |     },
 74 |     springConfig: {
 75 |       stiffness: 170,
 76 |       damping: 4,
 77 |       precision: 0.001,
 78 |     },
 79 |   }),
 80 |   /**
 81 |    * Function to calculate items positions size and hover
 82 |    * based on mouse position and previously hovered item
 83 |    */
 84 |   withHandlers(() => {
 85 |     let hoveredItemId_ = -1
 86 | 
 87 |     return {
 88 |       getItemsViewProps: ({ mousePos, items, config }) => () => {
 89 |         if (items.length === 0) return []
 90 | 
 91 |         const itemMaxWidth = config.size * Math.sqrt(2)
 92 |         const cIdx = (items.length - 1) / 2
 93 |         const itemsD = items
 94 |           .map((item, index) => ({
 95 |             ...item,
 96 |             size: hoveredItemId_ === item.id ? config.hoverSize : config.size,
 97 |             x: (index - cIdx) * (itemMaxWidth + config.spacing),
 98 |             y: 0,
 99 |           }))
100 |           .map(item => ({
101 |             ...item,
102 |             x:
103 |               hoveredItemId_ === item.id
104 |                 ? item.x + (mousePos.x - item.x) / 3
105 |                 : item.x,
106 |             y:
107 |               hoveredItemId_ === item.id
108 |                 ? item.y + (mousePos.y - item.y) / 3
109 |                 : item.y,
110 |           }))
111 |           .map(item => ({
112 |             ...item,
113 |             distance:
114 |               Math.sqrt(
115 |                 Math.pow(mousePos.x - item.x, 2) + Math.pow(mousePos.y, 2)
116 |               ) /
117 |               (item.size * Math.sqrt(2) / 2),
118 |           }))
119 |         const nearestItem = [...itemsD].sort(
120 |           (a, b) => a.distance - b.distance
121 |         )[0]
122 | 
123 |         if (nearestItem && nearestItem.distance < 1) {
124 |           hoveredItemId_ = nearestItem.id
125 |           // console.log('nearestItem', nearestItem);
126 |         } else {
127 |           hoveredItemId_ = -1
128 |         }
129 | 
130 |         return itemsD.map(item => ({
131 |           ...item,
132 |           hovered: item.id === hoveredItemId_,
133 |         }))
134 |       },
135 |     }
136 |   }),
137 |   /**
138 |    * Recalculate items positions, size, hover
139 |    */
140 |   withProps(({ getItemsViewProps }) => ({
141 |     items: getItemsViewProps(),
142 |   })),
143 |   /**
144 |    * Prepare data for react-motion
145 |    */
146 |   withProps(({ items, springConfig }) => ({
147 |     animStyles: items.map(item => ({
148 |       key: `${item.id}`,
149 |       data: item,
150 |       style: {
151 |         x: spring(item.x, springConfig),
152 |         y: spring(item.y, springConfig),
153 |         size: spring(item.size, springConfig),
154 |         borderK: spring(item.hovered ? 3 : 2, springConfig),
155 |       },
156 |     })),
157 |   }))
158 | )
159 | 
160 | export default enhanceItemsAnimator(itemsAnimator)
161 | 


--------------------------------------------------------------------------------
/types/flow-example/src/MouseDetector.js:
--------------------------------------------------------------------------------
  1 | /* @flow */
  2 | import React from 'react'
  3 | import {
  4 |   compose,
  5 |   defaultProps,
  6 |   withHandlers,
  7 |   withProps,
  8 |   withStateHandlers,
  9 | } from 'recompose'
 10 | import { css } from 'glamor'
 11 | import type { HOC } from 'recompose'
 12 | 
 13 | // shared type
 14 | export type MousePosition = { x: number, y: number }
 15 | 
 16 | // Props type of enhanced component
 17 | // It's the only props type we need to declare using supporting recompose enhancers
 18 | type EnhancedMouseDetectorProps = {
 19 |   styles?: { component: Object },
 20 |   children: (mousePos: MousePosition) => ?React$Element<any>,
 21 | }
 22 | 
 23 | // base component
 24 | const mouseDetector = ({ styles, registerChild, children, mousePos }) =>
 25 |   <div ref={registerChild} {...styles.component}>
 26 |     {children(mousePos)}
 27 |   </div>
 28 | 
 29 | // set existential * type for base component i.e. mouseDetector,
 30 | // flow is smart enough to infer base component and enhancers props types
 31 | const enhanceMouseDetector: HOC<*, EnhancedMouseDetectorProps> = compose(
 32 |   /**
 33 |    * styles can be overwritten by parent component
 34 |    */
 35 |   defaultProps({
 36 |     styles: {
 37 |       component: css({
 38 |         backgroundColor: 'red',
 39 |         position: 'relative',
 40 |         width: 0,
 41 |         height: 0,
 42 |       }),
 43 |     },
 44 |   }),
 45 |   /**
 46 |    * Component state and state handlers needed to calculate mouse position
 47 |    * relative to current component
 48 |    */
 49 |   withStateHandlers(
 50 |     // flow is smart enough to detect state type
 51 |     { mousePos: { x: Infinity, y: Infinity }, offset: { x: 0, y: 0 } },
 52 |     {
 53 |       // flow infers state and props types but
 54 |       // we need to declare type for handler argument i.e. x,y here
 55 |       // otherwise type inference will not work for following enhancers
 56 |       setMousePosition: (state, props) => (x: number, y: number) => ({
 57 |         mousePos: { x, y },
 58 |       }),
 59 |       // the same as above, we need to declare arg type
 60 |       setInitialOffsetYAndScrollY: () => (x: number, y: number) => ({
 61 |         offset: {
 62 |           x,
 63 |           y,
 64 |         },
 65 |       }),
 66 |     }
 67 |   ),
 68 |   /**
 69 |    * withHandlers hack to intercept document events
 70 |    */
 71 |   withHandlers(() => {
 72 |     let resizeHandler_
 73 |     let mouseMoveHandler_
 74 | 
 75 |     return {
 76 |       // hovering on state updater functions gives you a type like
 77 |       // Void<SomeFunctionType>, Void type helper transforms function result type to void
 78 |       // See libdef and tests, I haven't found more prettier solution
 79 |       registerChild: ({ setInitialOffsetYAndScrollY, setMousePosition }) => (
 80 |         ref: ?HTMLDivElement
 81 |       ) => {
 82 |         // I have no idea why window has any type so this is not covered
 83 |         const window: Node = document.defaultView
 84 | 
 85 |         if (ref) {
 86 |           // like ComponentDidMount if ref is not null
 87 |           resizeHandler_ = () => {
 88 |             if (!ref) return
 89 |             const refRect = ref.getBoundingClientRect()
 90 | 
 91 |             const docRect =
 92 |               document.documentElement &&
 93 |               document.documentElement.getBoundingClientRect()
 94 | 
 95 |             if (docRect) {
 96 |               // documentElement can be null so flow asks to check;
 97 |               const offsetX = refRect.left - docRect.left
 98 |               const offsetY = refRect.top - docRect.top
 99 | 
100 |               setInitialOffsetYAndScrollY(offsetX, offsetY)
101 |             }
102 |           }
103 | 
104 |           // call initially to update state
105 |           resizeHandler_()
106 | 
107 |           mouseMoveHandler_ = (evt: MouseEvent) =>
108 |             setMousePosition(evt.pageX, evt.pageY)
109 | 
110 |           window.addEventListener('resize', resizeHandler_)
111 |           document.addEventListener('mousemove', mouseMoveHandler_)
112 |         } else {
113 |           // like ComponentWillUnmount if ref is null
114 | 
115 |           if (resizeHandler_)
116 |             window.removeEventListener('resize', resizeHandler_)
117 |           if (mouseMoveHandler_)
118 |             document.removeEventListener('mousemove', mouseMoveHandler_)
119 | 
120 |           resizeHandler_ = undefined
121 |           mouseMoveHandler_ = undefined
122 |         }
123 |       },
124 |     }
125 |   }),
126 |   /**
127 |    * convert mouse coordinates into local
128 |   */
129 |   withProps(({ mousePos, offset }) => ({
130 |     mousePos: {
131 |       x: mousePos.x - offset.x,
132 |       y: mousePos.y - offset.y,
133 |     },
134 |   }))
135 | )
136 | 
137 | export default enhanceMouseDetector(mouseDetector)
138 | 


--------------------------------------------------------------------------------
/types/flow-example/src/index.js:
--------------------------------------------------------------------------------
 1 | /* @flow */
 2 | import React from 'react'
 3 | import ReactDOM from 'react-dom'
 4 | import App from './App'
 5 | import { css } from 'glamor'
 6 | import 'glamor-reset'
 7 | 
 8 | css.insert(`
 9 |   body, html {
10 |     height: 100vh;
11 |     font-size: 16px;
12 |     color: #666;
13 |     -webkit-font-smoothing: antialiased;
14 |     background-color: indigo;
15 |   }
16 | `)
17 | 
18 | css.insert(`
19 |   * {
20 |     min-width: 0;
21 |     min-height: 0;
22 |     box-sizing: border-box;
23 |   }
24 | `)
25 | 
26 | css.insert(`
27 |   #root {
28 |     min-height: 100%; /* not 100 vh because of mobile chrome */
29 |     display: flex;
30 |   }
31 | `)
32 | 
33 | const mountNode = document.getElementById('root')
34 | ReactDOM.render(<App />, mountNode)
35 | 
36 | if (module.hot) {
37 |   ;((module.hot: any): {
38 |     accept: (a: string, b: () => void) => void,
39 |   }).accept('./App', () => {
40 |     const NextApp = require('./App').default // eslint-disable-line
41 |     ReactDOM.render(<NextApp />, mountNode)
42 |   })
43 | }
44 | 


--------------------------------------------------------------------------------