├── .nvmrc ├── .gitignore ├── tests ├── sanity.test.js ├── renderNothing.test.js ├── createSink.test.js ├── renameProp.test.js ├── flattenProps.test.js ├── renameProps.test.js ├── mapProps.test.js ├── withProps.test.js ├── defaultProps.test.js └── withHandlers.test.js ├── .editorconfig ├── .prettierrc ├── codeclimate.yml ├── .babelrc ├── src ├── renderNothing.js ├── createSink.js ├── wrapDisplayName.js ├── rxjsObservableConfig.js ├── mostObservableConfig.js ├── compose.js ├── kefirObservableConfig.js ├── utils │ └── pick.js ├── getDisplayName.js ├── mapProps.js ├── withHandlers.js ├── defaultProps.js ├── withProps.js ├── renameProps.js ├── setObservableConfig.js ├── renameProp.js ├── renderComponent.js ├── branch.js ├── shouldUpdate.js ├── flattenProps.js ├── nest.js ├── createEventHandler.js ├── createHelper.js ├── rxjs4ObservableConfig.js ├── xstreamObservableConfig.js ├── flydObservableConfig.js ├── pure.js ├── baconObservableConfig.js ├── withPropsOnChange.js ├── withState.js ├── withReducer.js ├── withLifecycle.js ├── index.js ├── componentFromStream.js └── shallowEqual.js ├── jest.config.js ├── docs ├── pure.md ├── renderNothing.md ├── createSink.md ├── renameProp.md ├── withProps.md ├── mapProps.md ├── defaultProps.md ├── renameProps.md ├── renderComponent.md ├── branch.md ├── nest.md ├── withLifecycle.md ├── flattenProps.md ├── createEventHandler.md ├── withHandlers.md ├── componentFromStream.md ├── withState.md ├── compose.md ├── shouldUpdate.md ├── withPropsOnChange.md ├── withReducer.md └── setObservableConfig.md ├── dist ├── renderNothing.js ├── isClassComponent.js ├── mostObservableConfig.js ├── utils │ ├── pick.js │ └── createEagerElementUtil.js ├── getDisplayName.js ├── wrapDisplayName.js ├── createSink.js ├── rxjsObservableConfig.js ├── kefirObservableConfig.js ├── compose.js ├── isReferentiallyTransparentFunctionComponent.js ├── setObservableConfig.js ├── shouldUpdate.js ├── createEagerFactory.js ├── branch.js ├── pure.js ├── withHandlers.js ├── mapProps.js ├── createHelper.js ├── defaultProps.js ├── withProps.js ├── createEventHandler.js ├── renameProps.js ├── renameProp.js ├── xstreamObservableConfig.js ├── renderComponent.js ├── rxjs4ObservableConfig.js ├── flydObservableConfig.js ├── baconObservableConfig.js ├── flattenProps.js ├── withLifecycle.js ├── nest.js ├── shallowEqual.js ├── withPropsOnChange.js ├── withState.js ├── index.js ├── withReducer.js └── componentFromStream.js ├── .eslintrc ├── jest.babel.transform.js ├── cSpell.json ├── LICENSE.md ├── package.json ├── CHANGELOG.md └── README.md /.nvmrc: -------------------------------------------------------------------------------- 1 | 10.12.0 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | node_modules/ 3 | npm-debug.log -------------------------------------------------------------------------------- /tests/sanity.test.js: -------------------------------------------------------------------------------- 1 | test('sanity test', () => { 2 | expect(1 + 1).toBe(2); 3 | }); 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | indent_style=space 6 | indent_size=2 7 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babylon", 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "trailingComma": "all", 6 | "useTabs": true 7 | } 8 | -------------------------------------------------------------------------------- /codeclimate.yml: -------------------------------------------------------------------------------- 1 | engines: 2 | eslint: 3 | enabled: true 4 | channel: "eslint-3" 5 | ratings: 6 | paths: 7 | - "**.js" 8 | exclude_paths: 9 | - "**/*.test.js" -------------------------------------------------------------------------------- /tests/renderNothing.test.js: -------------------------------------------------------------------------------- 1 | import renderNothing from '../src/renderNothing'; 2 | 3 | test('should return null', () => { 4 | expect(renderNothing()()).toBeNull(); 5 | }); 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env"], 3 | "plugins": [ 4 | ["inferno", {"imports": true}], 5 | "@babel/plugin-proposal-class-properties", 6 | "@babel/plugin-proposal-object-rest-spread" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /src/renderNothing.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file renderNothing 3 | * @desc a higher order component that always renders null 4 | * @author Roman Zanettin 5 | * @date 2017-02-07 6 | */ 7 | 8 | export default () => () => null; 9 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | testURL: 'http://localhost/', 3 | globals: { 4 | usingJSDOM: true, 5 | usingJest: true, 6 | }, 7 | rootDir: __dirname, 8 | transform: { 9 | '^.+\\.js?$': '/jest.babel.transform.js', 10 | }, 11 | }; 12 | -------------------------------------------------------------------------------- /src/createSink.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file createSink 3 | * @author Roman Zanettin 4 | * @date 2017-02-08 5 | */ 6 | 7 | export default (callback = () => null) => (props = {}) => { 8 | callback(props); 9 | return null; 10 | }; 11 | -------------------------------------------------------------------------------- /src/wrapDisplayName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import getDisplayName from './getDisplayName'; 6 | 7 | const wrapDisplayName = (BaseComponent, hocName) => 8 | `${hocName}(${getDisplayName(BaseComponent)})`; 9 | 10 | export default wrapDisplayName; 11 | -------------------------------------------------------------------------------- /src/rxjsObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import Rx from 'rxjs'; // eslint-disable-line import/no-unresolved 6 | 7 | const config = { 8 | fromESObservable: Rx.Observable.from, 9 | toESObservable: stream => stream, 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /tests/createSink.test.js: -------------------------------------------------------------------------------- 1 | import createSink from '../src/createSink'; 2 | 3 | test('should call callback, every time the base props change', () => { 4 | const cb = jest.fn(); 5 | const props = { check: 'okay' }; 6 | 7 | const handler = createSink(cb)(props); 8 | 9 | expect(cb.mock.calls[0][0]).toEqual(props); 10 | }); 11 | -------------------------------------------------------------------------------- /src/mostObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import { from, Stream } from 'most'; // eslint-disable-line import/no-unresolved 6 | 7 | const config = { 8 | fromESObservable: from || Stream.from, 9 | toESObservable: stream => stream, 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /src/compose.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | export default function compose(...funcs) { 6 | if (funcs.length === 0) { 7 | return arg => arg; 8 | } 9 | 10 | if (funcs.length === 1) { 11 | return funcs[0]; 12 | } 13 | 14 | return funcs.reduce((a, b) => (...args) => a(b(...args))); 15 | } 16 | -------------------------------------------------------------------------------- /src/kefirObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import Kefir from 'kefir'; // eslint-disable-line import/no-unresolved 6 | 7 | const config = { 8 | fromESObservable: Kefir.fromESObservable, 9 | toESObservable: stream => stream.toESObservable(), 10 | }; 11 | 12 | export default config; 13 | -------------------------------------------------------------------------------- /src/utils/pick.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | const pick = (obj, keys) => { 6 | const result = {}; 7 | for (let i = 0; i < keys.length; i++) { 8 | const key = keys[i]; 9 | if (obj && obj[key]) { 10 | result[key] = obj[key]; 11 | } 12 | } 13 | return result; 14 | }; 15 | 16 | export default pick; 17 | -------------------------------------------------------------------------------- /src/getDisplayName.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | const getDisplayName = Component => { 6 | if (typeof Component === 'string') { 7 | return Component; 8 | } 9 | 10 | if (!Component) { 11 | return undefined; 12 | } 13 | 14 | return Component.displayName || Component.name || 'Component'; 15 | }; 16 | 17 | export default getDisplayName; 18 | -------------------------------------------------------------------------------- /tests/renameProp.test.js: -------------------------------------------------------------------------------- 1 | import renameProp from '../src/renameProp'; 2 | 3 | const originalProps = { 4 | a: 1, 5 | b: 2, 6 | c: 3, 7 | }; 8 | 9 | const component = props => ({ props }); 10 | 11 | test('should rename prop `a` to `z`', () => { 12 | const { props } = renameProp('a', 'z')(component)(originalProps); 13 | expect(props).toEqual({ 14 | z: 1, 15 | b: 2, 16 | c: 3, 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /tests/flattenProps.test.js: -------------------------------------------------------------------------------- 1 | import flattenProps from '../src/flattenProps'; 2 | 3 | const originalProps = { 4 | object: { a: 1, b: 2 }, 5 | c: 3, 6 | }; 7 | 8 | const component = props => ({ props }); 9 | 10 | test('should flatten prop `object`', () => { 11 | const { props } = flattenProps('object')(component)(originalProps); 12 | expect(props).toEqual({ 13 | a: 1, 14 | b: 2, 15 | c: 3, 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /docs/pure.md: -------------------------------------------------------------------------------- 1 | # pure 2 | ## Description 3 | Prevents the component from updating unless a prop has changed. Uses `shallowEqual()` to test for changes. 4 | 5 | ## API 6 | ``` 7 | pure : Function 8 | ``` 9 | 10 | ## Example 11 | ```jsx 12 | import { 13 | compose, 14 | pure, 15 | } from 'incompose'; 16 | 17 | const A = (props) => ( 18 |

a

19 | ); 20 | 21 | export default compose( 22 | pure, 23 | )(A); 24 | ``` 25 | -------------------------------------------------------------------------------- /tests/renameProps.test.js: -------------------------------------------------------------------------------- 1 | import renameProps from '../src/renameProps'; 2 | 3 | const originalProps = { 4 | a: 1, 5 | b: 2, 6 | c: 3, 7 | }; 8 | 9 | const component = props => ({ props }); 10 | 11 | test('should rename prop `a` to `z` and `b` to `y`', () => { 12 | const{ props } = renameProps({ a: 'z', b: 'y' })(component)(originalProps); 13 | expect(props).toEqual({ 14 | z: 1, 15 | y: 2, 16 | c: 3, 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /src/mapProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file mapProps 3 | * @desc maps props on component init 4 | * @author Zoltan Dalmadi 5 | * @date 2018-10-18 6 | */ 7 | 8 | /** 9 | * @param {Object} - mapper function 10 | * @param {Function} - component 11 | * @param {Object} - component props 12 | * @returns {Function} 13 | */ 14 | export default mapper => Component => props => ; 15 | -------------------------------------------------------------------------------- /src/withHandlers.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file withHandlers 3 | * @author Roman Zanettin 4 | * @date 2017-02-07 5 | */ 6 | 7 | export default handlerCreators => Component => props => { 8 | const composed = Object.keys(handlerCreators).reduce((acc, key) => { 9 | acc[key] = handlerCreators[key](props); 10 | return acc; 11 | }, {}); 12 | 13 | return ; 14 | }; 15 | -------------------------------------------------------------------------------- /docs/renderNothing.md: -------------------------------------------------------------------------------- 1 | # renderNothing 2 | ## Description 3 | A higher-order component that always renders `null`. 4 | 5 | ## API 6 | ``` 7 | renderNothing() : Function 8 | ``` 9 | 10 | ## Example 11 | ```jsx 12 | import { 13 | compose, 14 | renderNothing 15 | } from 'incompose'; 16 | 17 | const Counter = (props) => ( 18 |
will never be rendered!
19 | ); 20 | 21 | export default compose( 22 | renderNothing, 23 | )(Counter); 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/createSink.md: -------------------------------------------------------------------------------- 1 | # createSink 2 | ## Description 3 | Creates a component that renders nothing (`null`) but calls a callback when receiving new props. 4 | 5 | ## API 6 | ``` 7 | createSink( 8 | callback : (props : Object) => void, 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```javascript 14 | import { createSink } from 'incompose'; 15 | 16 | const cb = (props) => console.warn('props are updated', props); 17 | 18 | export default createSink(cb); 19 | ``` -------------------------------------------------------------------------------- /src/defaultProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file defaultProps 3 | * @desc sets default values for owner props 4 | * @author Roman Zanettin 5 | * @date 2017-01-06 6 | */ 7 | 8 | /** 9 | * @param {Object} - default props config 10 | * @param {Function} - component 11 | * @param {Object} - component props 12 | * @returns {Function} 13 | */ 14 | export default config => Component => props => ( 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /dist/renderNothing.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @file renderNothing 10 | * @desc a higher order component that always renders null 11 | * @author Roman Zanettin 12 | * @date 2017-02-07 13 | */ 14 | var _default = function _default() { 15 | return function () { 16 | return null; 17 | }; 18 | }; 19 | 20 | exports.default = _default; -------------------------------------------------------------------------------- /src/withProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file withProps 3 | * @desc appends props on component init (does overwrite existing props) 4 | * @author Roman Zanettin 5 | * @date 2017-01-06 6 | */ 7 | 8 | /** 9 | * @param {Object} - default props config 10 | * @param {Function} - component 11 | * @param {Object} - component props 12 | * @returns {Function} 13 | */ 14 | export default config => Component => props => ( 15 | 16 | ); 17 | -------------------------------------------------------------------------------- /dist/isClassComponent.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _inferno = require('inferno'); 8 | 9 | var isClassComponent = function isClassComponent(ComponentArg) { 10 | return Boolean(ComponentArg && ComponentArg.prototype && typeof ComponentArg.prototype.render === 'function' && _inferno.Component.isPrototypeOf(ComponentArg)); 11 | }; /** 12 | * @author recompose (https://github.com/acdlite/recompose) 13 | */ 14 | 15 | exports.default = isClassComponent; -------------------------------------------------------------------------------- /tests/mapProps.test.js: -------------------------------------------------------------------------------- 1 | import mapProps from '../src/mapProps'; 2 | 3 | const originalProps = { 4 | a: 1, 5 | b: 2, 6 | c: 3, 7 | }; 8 | 9 | const mappedProps = { 10 | d: 3, 11 | e: 6, 12 | }; 13 | 14 | const component = props => ({ props }); 15 | 16 | const mapper = ({ a, b, c }) => ({ 17 | d: a + b, 18 | e: c * 2, 19 | }); 20 | 21 | test('should map components original props to different props', () => { 22 | const { props } = mapProps(mapper)(component)(originalProps); 23 | expect(props).toEqual(mappedProps); 24 | }); 25 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "parserOptions": { 4 | "ecmaVersion": 6, 5 | "sourceType": "module", 6 | "ecmaFeatures": { 7 | "jsx": true 8 | } 9 | }, 10 | "plugins": [ 11 | "inferno", 12 | "import" 13 | ], 14 | "extends": "eslint:recommended", 15 | "rules": { 16 | "semi": 2, 17 | "inferno/jsx-uses-inferno": 2, 18 | "inferno/jsx-uses-vars": 2, 19 | "import/no-unresolved": 2, 20 | "no-console": 0 21 | }, 22 | "env": { 23 | "browser": true, 24 | "node": true 25 | } 26 | } -------------------------------------------------------------------------------- /dist/mostObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _most = require("most"); 9 | 10 | /** 11 | * @author recompose (https://github.com/acdlite/recompose) 12 | */ 13 | // eslint-disable-line import/no-unresolved 14 | var config = { 15 | fromESObservable: _most.from || _most.Stream.from, 16 | toESObservable: function toESObservable(stream) { 17 | return stream; 18 | } 19 | }; 20 | var _default = config; 21 | exports.default = _default; -------------------------------------------------------------------------------- /dist/utils/pick.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @author recompose (https://github.com/acdlite/recompose) 10 | */ 11 | var pick = function pick(obj, keys) { 12 | var result = {}; 13 | 14 | for (var i = 0; i < keys.length; i++) { 15 | var key = keys[i]; 16 | 17 | if (obj && obj[key]) { 18 | result[key] = obj[key]; 19 | } 20 | } 21 | 22 | return result; 23 | }; 24 | 25 | var _default = pick; 26 | exports.default = _default; -------------------------------------------------------------------------------- /docs/renameProp.md: -------------------------------------------------------------------------------- 1 | # renameProp 2 | ## Description 3 | Renames a single prop. 4 | 5 | ## API 6 | ``` 7 | renameProp( 8 | oldPropName : string, 9 | newPropName : string, 10 | ) : Function 11 | ``` 12 | 13 | ## Example 14 | ```jsx 15 | import { 16 | compose, 17 | renameProp 18 | } from 'incompose'; 19 | 20 | const LeaderBoard = (props) => ( 21 |
22 |

{props.name} has a score of {props.score}

23 |
24 | ); 25 | 26 | export default compose( 27 | renameProp('count', 'score'), // rename prop `count` to `score` 28 | )(LeaderBoard); 29 | ``` 30 | -------------------------------------------------------------------------------- /dist/getDisplayName.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @author recompose (https://github.com/acdlite/recompose) 10 | */ 11 | var getDisplayName = function getDisplayName(Component) { 12 | if (typeof Component === 'string') { 13 | return Component; 14 | } 15 | 16 | if (!Component) { 17 | return undefined; 18 | } 19 | 20 | return Component.displayName || Component.name || 'Component'; 21 | }; 22 | 23 | var _default = getDisplayName; 24 | exports.default = _default; -------------------------------------------------------------------------------- /tests/withProps.test.js: -------------------------------------------------------------------------------- 1 | import withProps from '../src/withProps'; 2 | 3 | const originalProps = { 4 | a: 1, 5 | b: 2, 6 | c: 3, 7 | }; 8 | 9 | const additionalProps = { 10 | a: 10, // overwrite original 11 | b: 20, // overwrite original 12 | d: 4, // extends original 13 | }; 14 | 15 | const component = props => ({ props }); 16 | 17 | test('should add additional props to components original props', () => { 18 | const { props } = withProps(additionalProps)(component)(originalProps); 19 | expect(props).toEqual({ 20 | a: 10, 21 | b: 20, 22 | c: 3, 23 | d: 4, 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /jest.babel.transform.js: -------------------------------------------------------------------------------- 1 | // Custom Jest transform implementation that wraps babel-jest and injects our 2 | // babel presets, so we don't have to use .babelrc. 3 | 4 | module.exports = require('babel-jest').createTransformer({ 5 | babelrc: false, 6 | presets: [ 7 | [ 8 | '@babel/preset-env', 9 | { 10 | modules: 'commonjs', 11 | loose: true, 12 | targets: { 13 | node: 'current', 14 | }, 15 | }, 16 | ], 17 | ], 18 | plugins: [ 19 | ['babel-plugin-inferno', { imports: true }], 20 | ['@babel/plugin-proposal-class-properties', { loose: true }], 21 | ], 22 | }); 23 | -------------------------------------------------------------------------------- /tests/defaultProps.test.js: -------------------------------------------------------------------------------- 1 | import defaultProps from '../src/defaultProps'; 2 | 3 | const originalProps = { 4 | a: 1, 5 | b: 2, 6 | c: 3, 7 | }; 8 | 9 | const defaultPropsValues = { 10 | a: 10, // NO overwrite original 11 | b: 20, // NO overwrite original 12 | d: 4, // extends original 13 | }; 14 | 15 | const component = props => ({ props }); 16 | 17 | test('should add additional props to components original props', () => { 18 | const { props } = defaultProps(defaultPropsValues)(component)(originalProps); 19 | expect(props).toEqual({ 20 | a: 1, 21 | b: 2, 22 | c: 3, 23 | d: 4, 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/withHandlers.test.js: -------------------------------------------------------------------------------- 1 | import withHandlers from '../src/withHandlers'; 2 | 3 | const originalProps = { 4 | check: 'yup', 5 | a: 1, 6 | b: 2, 7 | }; 8 | 9 | const withTestHandlers = { 10 | doTest: props => `successful? ${props.check}`, 11 | getSum: props => () => props.a + props.b, 12 | }; 13 | 14 | const component = props => ({ props }); 15 | 16 | test('should add handler creators and enrich them with props', () => { 17 | const { props } = withHandlers(withTestHandlers)(component)(originalProps); 18 | 19 | expect(props.doTest).toEqual('successful? yup'); 20 | expect(props.getSum()).toBe(3); 21 | }); 22 | -------------------------------------------------------------------------------- /docs/withProps.md: -------------------------------------------------------------------------------- 1 | # withProps 2 | ## Description 3 | Like `defaultProps()`, except the passed props take precedence over props provided to the base component. 4 | 5 | ## API 6 | ``` 7 | withProps( 8 | props : Object 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import { 15 | compose, 16 | withProps 17 | } from 'incompose'; 18 | 19 | const LeaderBoard = (props) => ( 20 |
21 |

{props.name} has a score of {props.score}

22 |
23 | ); 24 | 25 | export default compose( 26 | withProps({ 27 | score : 100, 28 | name : 'John', 29 | }), 30 | )(LeaderBoard); 31 | ``` 32 | -------------------------------------------------------------------------------- /src/renameProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file renameProps 3 | * @desc renames the owner prop 4 | * @author Roman Zanettin 5 | * @date 2017-02-06 6 | */ 7 | 8 | /** 9 | * @param {Object} - config ({oldName : 'newName', a : 'z'}) 10 | * @param {Function} - component 11 | * @param {Object} - component props 12 | * @returns {Function} 13 | */ 14 | export default config => Component => props => { 15 | const newProps = Object.keys(props).reduce((acc, key) => { 16 | acc[config[key] || key] = props[key]; 17 | return acc; 18 | }, {}); 19 | 20 | return ; 21 | }; 22 | -------------------------------------------------------------------------------- /src/setObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | let _config = { 6 | fromESObservable: null, 7 | toESObservable: null, 8 | }; 9 | 10 | const configureObservable = c => { 11 | _config = c; 12 | }; 13 | 14 | export const config = { 15 | fromESObservable: observable => 16 | typeof _config.fromESObservable === 'function' 17 | ? _config.fromESObservable(observable) 18 | : observable, 19 | toESObservable: stream => 20 | typeof _config.toESObservable === 'function' 21 | ? _config.toESObservable(stream) 22 | : stream, 23 | }; 24 | 25 | export default configureObservable; 26 | -------------------------------------------------------------------------------- /docs/mapProps.md: -------------------------------------------------------------------------------- 1 | # mapProps 2 | ## Description 3 | Applies a mapper function, which transforms the original props into a new props object. 4 | 5 | ## API 6 | ``` 7 | mapProps( 8 | (props) => Object 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import { 15 | compose, 16 | mapProps 17 | } from 'incompose'; 18 | 19 | const DiscountPriceIndicator = ({ discountPrice }) => ( 20 |
21 |

Discount price: {discountPrice}

22 |
23 | ); 24 | 25 | export default compose( 26 | mapProps(({ price, discount }) => ({ 27 | discountPrice: price - price * (discount / 100) 28 | })), 29 | )(DiscountPriceIndicator); 30 | ``` 31 | -------------------------------------------------------------------------------- /src/renameProp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file renameProp 3 | * @desc renames the owner prop 4 | * @author Roman Zanettin 5 | * @date 2017-02-06 6 | */ 7 | 8 | /** 9 | * @param {string} - old name 10 | * @param {string} - new name 11 | * @param {Function} - component 12 | * @param {Object} - component props 13 | * @returns {Function} 14 | */ 15 | export default (oldName, newName) => Component => props => { 16 | const newProps = props; 17 | 18 | if (props[oldName]) { 19 | newProps[newName] = props[oldName]; 20 | delete newProps[oldName]; 21 | } 22 | 23 | return ; 24 | }; 25 | -------------------------------------------------------------------------------- /dist/wrapDisplayName.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _getDisplayName = _interopRequireDefault(require("./getDisplayName")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11 | 12 | /** 13 | * @author recompose (https://github.com/acdlite/recompose) 14 | */ 15 | var wrapDisplayName = function wrapDisplayName(BaseComponent, hocName) { 16 | return "".concat(hocName, "(").concat((0, _getDisplayName.default)(BaseComponent), ")"); 17 | }; 18 | 19 | var _default = wrapDisplayName; 20 | exports.default = _default; -------------------------------------------------------------------------------- /dist/createSink.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @file createSink 10 | * @author Roman Zanettin 11 | * @date 2017-02-08 12 | */ 13 | var _default = function _default() { 14 | var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : function () { 15 | return null; 16 | }; 17 | return function () { 18 | var props = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; 19 | callback(props); 20 | return null; 21 | }; 22 | }; 23 | 24 | exports.default = _default; -------------------------------------------------------------------------------- /dist/rxjsObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _rxjs = _interopRequireDefault(require("rxjs")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11 | 12 | /** 13 | * @author recompose (https://github.com/acdlite/recompose) 14 | */ 15 | // eslint-disable-line import/no-unresolved 16 | var config = { 17 | fromESObservable: _rxjs.default.Observable.from, 18 | toESObservable: function toESObservable(stream) { 19 | return stream; 20 | } 21 | }; 22 | var _default = config; 23 | exports.default = _default; -------------------------------------------------------------------------------- /src/renderComponent.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import createHelper from './createHelper'; 6 | 7 | const renderComponent = Component => () => { 8 | const RenderComponent = props => ; 9 | if (process.env.NODE_ENV !== 'production') { 10 | /* eslint-disable global-require */ 11 | const wrapDisplayName = require('./wrapDisplayName').default; 12 | /* eslint-enable global-require */ 13 | RenderComponent.displayName = wrapDisplayName(Component, 'renderComponent'); 14 | } 15 | return RenderComponent; 16 | }; 17 | 18 | export default createHelper(renderComponent, 'renderComponent', false); 19 | -------------------------------------------------------------------------------- /src/branch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import compose from './compose'; 6 | import createHelper from './createHelper'; 7 | 8 | const identity = Component => Component; 9 | 10 | const branch = (test, left, right = identity) => BaseComponent => { 11 | let leftFactory; 12 | let rightFactory; 13 | return props => { 14 | if (test(props)) { 15 | leftFactory = leftFactory || compose(left)(BaseComponent); 16 | return leftFactory(props); 17 | } 18 | rightFactory = rightFactory || compose(right)(BaseComponent); 19 | return rightFactory(props); 20 | }; 21 | }; 22 | 23 | export default createHelper(branch, 'branch'); 24 | -------------------------------------------------------------------------------- /src/shouldUpdate.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file shouldUpdate 3 | * @desc use 'onComponentShouldUpdate' lifecycle hook to determine if component should update or not 4 | * @author Roman Zanettin 5 | * @date 2017-01-06 6 | */ 7 | 8 | // import withLifecycle from './withLifecycle'; 9 | 10 | /** 11 | * @param {Function} - onComponentShouldUpdate - should update check function returning a boolean value 12 | * @param {Function} - component 13 | * @returns {Function} 14 | */ 15 | export default onComponentShouldUpdate => Component => { 16 | Component.defaultHooks = { 17 | onComponentShouldUpdate, 18 | }; 19 | 20 | return Component; 21 | }; 22 | -------------------------------------------------------------------------------- /docs/defaultProps.md: -------------------------------------------------------------------------------- 1 | # defaultProps 2 | ## Description 3 | Specifies props to be passed by default to the base component. Similar to `withProps()`, except the props from the owner take precedence over props provided to the HoC. 4 | 5 | ## API 6 | ``` 7 | defaultProps( 8 | props : Object 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import { 15 | compose, 16 | defaultProps 17 | } from 'incompose'; 18 | 19 | const LeaderBoard = (props) => ( 20 |
21 |

{props.name} has a score of {props.score}

22 |
23 | ); 24 | 25 | export default compose( 26 | defaultProps({ 27 | score : 100, 28 | name : 'John', 29 | }), 30 | )(LeaderBoard); 31 | ``` 32 | -------------------------------------------------------------------------------- /dist/kefirObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _kefir = _interopRequireDefault(require("kefir")); 9 | 10 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 11 | 12 | /** 13 | * @author recompose (https://github.com/acdlite/recompose) 14 | */ 15 | // eslint-disable-line import/no-unresolved 16 | var config = { 17 | fromESObservable: _kefir.default.fromESObservable, 18 | toESObservable: function toESObservable(stream) { 19 | return stream.toESObservable(); 20 | } 21 | }; 22 | var _default = config; 23 | exports.default = _default; -------------------------------------------------------------------------------- /docs/renameProps.md: -------------------------------------------------------------------------------- 1 | # renameProps 2 | ## Description 3 | Renames multiple props, using a map of old prop names to new prop names. 4 | 5 | ## API 6 | ``` 7 | renameProps( 8 | nameMap: { [key : string] : string } 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import { 15 | compose, 16 | renameProp 17 | } from 'incompose'; 18 | 19 | const LeaderBoard = (props) => ( 20 |
21 |

{props.name} has a score of {props.score}

22 |
23 | ); 24 | 25 | export default compose( 26 | renameProps({ 27 | count : 'score', // rename prop `count` to `score` 28 | lastName : 'name', // rename prop `lastName` to `name` 29 | }), 30 | )(LeaderBoard); 31 | ``` 32 | -------------------------------------------------------------------------------- /src/flattenProps.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file flattenProps 3 | * @desc renames the owner prop 4 | * @author Roman Zanettin 5 | * @date 2017-02-06 6 | */ 7 | 8 | /** 9 | * @param {string} - prop name to flatten 10 | * @param {Function} - component 11 | * @param {Object} - component props 12 | * @returns {Function} 13 | */ 14 | export default propName => Component => props => { 15 | const newProps = 16 | props[propName] && typeof props[propName] === 'object' 17 | ? { ...props, ...props[propName] } 18 | : { ...props }; 19 | 20 | if (newProps[propName]) { 21 | delete newProps[propName]; 22 | } 23 | 24 | return ; 25 | }; 26 | -------------------------------------------------------------------------------- /dist/compose.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = compose; 7 | 8 | /** 9 | * @author recompose (https://github.com/acdlite/recompose) 10 | */ 11 | function compose() { 12 | for (var _len = arguments.length, funcs = new Array(_len), _key = 0; _key < _len; _key++) { 13 | funcs[_key] = arguments[_key]; 14 | } 15 | 16 | if (funcs.length === 0) { 17 | return function (arg) { 18 | return arg; 19 | }; 20 | } 21 | 22 | if (funcs.length === 1) { 23 | return funcs[0]; 24 | } 25 | 26 | return funcs.reduce(function (a, b) { 27 | return function () { 28 | return a(b.apply(void 0, arguments)); 29 | }; 30 | }); 31 | } -------------------------------------------------------------------------------- /docs/renderComponent.md: -------------------------------------------------------------------------------- 1 | # renderComponent 2 | ## Description 3 | Takes a component and returns a higher-order component version of that component. 4 | 5 | This is useful in combination with another helper that expects a higher-order component, like `branch()`: 6 | 7 | ## API 8 | ``` 9 | renderComponent( 10 | Component : Function 11 | ) : Function 12 | ``` 13 | 14 | ## Example 15 | ```jsx 16 | import { 17 | branch, 18 | compose, 19 | renderComponent, 20 | } from 'incompose'; 21 | 22 | const A = () => ( 23 |

a

24 | ); 25 | 26 | const B = () => ( 27 |

loading...

28 | ); 29 | 30 | export default compose( 31 | branch( 32 | (props) => props.value % 2 === 0, 33 | renderComponent(B), 34 | ) 35 | )(A); 36 | ``` 37 | -------------------------------------------------------------------------------- /src/nest.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file nest 3 | * @author Roman Zanettin 4 | * @date 2017-02-12 5 | */ 6 | 7 | import Inferno from 'inferno'; 8 | 9 | export default (...Components) => props => { 10 | if (!Components || Components.length < 1) { 11 | return null; 12 | } 13 | 14 | const MainComponent = Components[0]; 15 | const components = Components.reverse(); 16 | const propsMap = components.map((Component, index) => { 17 | const PrevComponent = components[index - 1] || null; 18 | const nextProps = props; 19 | 20 | if (PrevComponent !== null) { 21 | nextProps.children = ; 22 | } 23 | 24 | return nextProps; 25 | }); 26 | 27 | return MainComponent(propsMap.reverse()[0]); 28 | }; 29 | -------------------------------------------------------------------------------- /cSpell.json: -------------------------------------------------------------------------------- 1 | // cSpell Settings 2 | { 3 | // Version of the setting file. Always 0.1 4 | "version": "0.1", 5 | // language - current active spelling language 6 | "language": "en", 7 | // words - list of words to be always considered correct 8 | "words": [ 9 | "Incompose", 10 | "flyd", 11 | "lifecycle", 12 | "lodash's", 13 | "referentially", 14 | "rxjsconfig", 15 | "unmount", 16 | "vdom", 17 | "xstream", 18 | "zanettin" 19 | ], 20 | // flagWords - list of words to be always considered incorrect 21 | // This is useful for offensive words and common spelling errors. 22 | // For example "hte" should be "the" 23 | "flagWords": [ 24 | "hte" 25 | ] 26 | } -------------------------------------------------------------------------------- /docs/branch.md: -------------------------------------------------------------------------------- 1 | # branch 2 | ## Description 3 | Accepts a test function and two higher-order components. The test function is passed the props from the owner. If it returns true, the `left` higher-order component is applied to `BaseComponent`; otherwise, the `right` higher-order component is applied. 4 | 5 | ## API 6 | ``` 7 | branch( 8 | test : (props : Object) => boolean, 9 | left : Function, 10 | right : Function 11 | ) : Function 12 | ``` 13 | 14 | ## Example 15 | ```jsx 16 | import { 17 | branch, 18 | compose, 19 | defaultProps, 20 | } from 'incompose'; 21 | 22 | const A = (props) => ( 23 |

counter is {props.counter}

24 | ); 25 | 26 | export default compose( 27 | branch( 28 | (props) => props.value % 2 === 0, 29 | defaultProps({counter : 1}), 30 | defaultProps({counter : 2}), 31 | ) 32 | )(A); 33 | ``` 34 | -------------------------------------------------------------------------------- /src/createEventHandler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import $$observable from 'symbol-observable'; 6 | import { createChangeEmitter } from 'change-emitter'; 7 | import { config as globalConfig } from './setObservableConfig'; 8 | 9 | export const createEventHandlerWithConfig = config => () => { 10 | const emitter = createChangeEmitter(); 11 | const stream = config.fromESObservable({ 12 | subscribe(observer) { 13 | const unsubscribe = emitter.listen(value => observer.next(value)); 14 | return { unsubscribe }; 15 | }, 16 | [$$observable]() { 17 | return this; 18 | }, 19 | }); 20 | return { 21 | handler: emitter.emit, 22 | stream, 23 | }; 24 | }; 25 | 26 | const createEventHandler = createEventHandlerWithConfig(globalConfig); 27 | 28 | export default createEventHandler; 29 | -------------------------------------------------------------------------------- /dist/isReferentiallyTransparentFunctionComponent.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _isClassComponent = require('./isClassComponent.js'); 8 | 9 | var _isClassComponent2 = _interopRequireDefault(_isClassComponent); 10 | 11 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 12 | 13 | /*eslint-env node*/ 14 | var isReferentiallyTransparentFunctionComponent = function isReferentiallyTransparentFunctionComponent(Component) { 15 | return Boolean(typeof Component === 'function' && !(0, _isClassComponent2.default)(Component) && !Component.defaultProps && !Component.contextTypes && (process.env.NODE_ENV === 'production' || !Component.propTypes)); 16 | }; /** 17 | * @author recompose (https://github.com/acdlite/recompose) 18 | */ 19 | 20 | exports.default = isReferentiallyTransparentFunctionComponent; -------------------------------------------------------------------------------- /dist/setObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = exports.config = void 0; 7 | 8 | /** 9 | * @author recompose (https://github.com/acdlite/recompose) 10 | */ 11 | var _config = { 12 | fromESObservable: null, 13 | toESObservable: null 14 | }; 15 | 16 | var configureObservable = function configureObservable(c) { 17 | _config = c; 18 | }; 19 | 20 | var config = { 21 | fromESObservable: function fromESObservable(observable) { 22 | return typeof _config.fromESObservable === 'function' ? _config.fromESObservable(observable) : observable; 23 | }, 24 | toESObservable: function toESObservable(stream) { 25 | return typeof _config.toESObservable === 'function' ? _config.toESObservable(stream) : stream; 26 | } 27 | }; 28 | exports.config = config; 29 | var _default = configureObservable; 30 | exports.default = _default; -------------------------------------------------------------------------------- /docs/nest.md: -------------------------------------------------------------------------------- 1 | # nest 2 | ## Description 3 | Composes components by nesting each one inside the previous. 4 | 5 | ## API 6 | ``` 7 | nest( 8 | ...Components : Array 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import {nest} from 'incompose'; 15 | 16 | const A = (props) => ( 17 |
18 |

I'm A

19 | {props.children} 20 |
21 | ); 22 | 23 | const B = (props) => ( 24 |
25 |

I'm B

26 | {props.children} 27 |
28 | ); 29 | 30 | const C = (props) => ( 31 |
32 |

I'm C

33 | {props.children} 34 |
35 | ); 36 | 37 | const D = (props) => ( 38 |
39 |

I'm D

40 | {props.children} 41 |
42 | ); 43 | 44 | const E = (props) => ( 45 |
46 |
I'm E
47 | {props.children} 48 |
49 | ); 50 | 51 | export default nest(A, B, C, D, E); 52 | ``` 53 | -------------------------------------------------------------------------------- /dist/shouldUpdate.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @file shouldUpdate 10 | * @desc use 'onComponentShouldUpdate' lifecycle hook to determine if component should update or not 11 | * @author Roman Zanettin 12 | * @date 2017-01-06 13 | */ 14 | // import withLifecycle from './withLifecycle'; 15 | 16 | /** 17 | * @param {Function} - onComponentShouldUpdate - should update check function returning a boolean value 18 | * @param {Function} - component 19 | * @returns {Function} 20 | */ 21 | var _default = function _default(onComponentShouldUpdate) { 22 | return function (Component) { 23 | Component.defaultHooks = { 24 | onComponentShouldUpdate: onComponentShouldUpdate 25 | }; 26 | return Component; 27 | }; 28 | }; 29 | 30 | exports.default = _default; -------------------------------------------------------------------------------- /src/createHelper.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | /*eslint-env node*/ 6 | const createHelper = ( 7 | func, 8 | helperName, 9 | setDisplayName = true, 10 | noArgs = false, 11 | ) => { 12 | if (process.env.NODE_ENV !== 'production' && setDisplayName) { 13 | /* eslint-disable global-require */ 14 | const wrapDisplayName = require('./wrapDisplayName').default; 15 | /* eslint-enable global-require */ 16 | 17 | if (noArgs) { 18 | return BaseComponent => { 19 | const Component = func(BaseComponent); 20 | Component.displayName = wrapDisplayName(BaseComponent, helperName); 21 | return Component; 22 | }; 23 | } 24 | 25 | return (...args) => BaseComponent => { 26 | const Component = func(...args)(BaseComponent); 27 | Component.displayName = wrapDisplayName(BaseComponent, helperName); 28 | return Component; 29 | }; 30 | } 31 | 32 | return func; 33 | }; 34 | 35 | export default createHelper; 36 | -------------------------------------------------------------------------------- /src/rxjs4ObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import $$observable from 'symbol-observable'; 6 | import Rx from 'rx'; // eslint-disable-line import/no-unresolved 7 | 8 | const config = { 9 | fromESObservable: observable => 10 | Rx.Observable.create(observer => { 11 | const { unsubscribe } = observable.subscribe({ 12 | next: val => observer.onNext(val), 13 | error: error => observer.onError(error), 14 | complete: () => observer.onCompleted(), 15 | }); 16 | return unsubscribe; 17 | }), 18 | toESObservable: rxObservable => ({ 19 | subscribe: observer => { 20 | const subscription = rxObservable.subscribe( 21 | val => observer.next(val), 22 | error => observer.error(error), 23 | () => observer.complete(), 24 | ); 25 | return { unsubscribe: () => subscription.dispose() }; 26 | }, 27 | [$$observable]() { 28 | return this; 29 | }, 30 | }), 31 | }; 32 | 33 | export default config; 34 | -------------------------------------------------------------------------------- /src/xstreamObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import $$observable from 'symbol-observable'; 6 | import xstream from 'xstream'; // eslint-disable-line import/no-unresolved 7 | 8 | const noop = () => {}; 9 | 10 | const config = { 11 | fromESObservable: observable => 12 | xstream.create({ 13 | subscription: null, 14 | start(listener) { 15 | this.subscription = observable.subscribe(listener); 16 | }, 17 | stop() { 18 | this.subscription.unsubscribe(); 19 | }, 20 | }), 21 | toESObservable: stream => ({ 22 | subscribe: observer => { 23 | const listener = { 24 | next: observer.next || noop, 25 | error: observer.error || noop, 26 | complete: observer.complete || noop, 27 | }; 28 | stream.addListener(listener); 29 | return { 30 | unsubscribe: () => stream.removeListener(listener), 31 | }; 32 | }, 33 | [$$observable]() { 34 | return this; 35 | }, 36 | }), 37 | }; 38 | 39 | export default config; 40 | -------------------------------------------------------------------------------- /src/flydObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import $$observable from 'symbol-observable'; 6 | import flyd from 'flyd'; // eslint-disable-line import/no-unresolved 7 | 8 | const noop = () => {}; 9 | 10 | const config = { 11 | fromESObservable: observable => { 12 | const stream = flyd.stream(); 13 | const { unsubscribe } = observable.subscribe({ 14 | next: value => stream(value), 15 | error: error => stream({ error }), 16 | complete: () => stream.end(true), 17 | }); 18 | 19 | flyd.on(unsubscribe, stream.end); 20 | return stream; 21 | }, 22 | 23 | toESObservable: stream => ({ 24 | subscribe: observer => { 25 | const sub = flyd.on(observer.next || noop, stream); 26 | flyd.on(_ => observer.complete(), sub.end); // eslint-disable-line no-unused-vars 27 | return { 28 | unsubscribe: () => sub.end(true), 29 | }; 30 | }, 31 | [$$observable]() { 32 | return this; 33 | }, 34 | }), 35 | }; 36 | 37 | export default config; 38 | -------------------------------------------------------------------------------- /src/pure.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file pure 3 | * @desc Prevents the component from updating unless a prop has changed. 4 | * Uses shallow equal to test for changes. 5 | * @author Roman Zanettin 6 | * @date 2017-02-15 7 | */ 8 | 9 | import compose from './compose'; 10 | import shouldUpdate from './shouldUpdate'; 11 | 12 | const withUpdatePolicy = shouldUpdate((props, nextProps) => { 13 | // handle invalid props 14 | if ( 15 | !props || 16 | !nextProps || 17 | typeof props !== 'object' || 18 | typeof nextProps !== 'object' 19 | ) { 20 | return true; 21 | } 22 | 23 | const keys = Object.keys(props); 24 | 25 | for (let i = 0; i < keys.length; i += 1) { 26 | if (props[keys[i]] !== nextProps[keys[i]]) { 27 | return true; // just update if we find a shallow diff 28 | } 29 | } 30 | 31 | return false; 32 | }); 33 | 34 | /** 35 | * @param {Function} component 36 | * @returns {Function} 37 | */ 38 | export default Component => compose(withUpdatePolicy)(Component); 39 | -------------------------------------------------------------------------------- /docs/withLifecycle.md: -------------------------------------------------------------------------------- 1 | # withLifecycle 2 | ## Description 3 | Adds lifecycle hooks to the base component. The full API list can be found [here](https://infernojs.org/docs/guides/components). 4 | Please note that Inferno itself offers lifecycle hooks for functional components as described in the docs. 5 | The difference is, that this hook can be used INSIDE the component and not from the parent component. 6 | 7 | ## API 8 | ``` 9 | withLifecycle( 10 | hooks : Object, 11 | ) : Function; 12 | ``` 13 | 14 | ## Example 15 | ```jsx 16 | import { 17 | compose, 18 | withLifecycle 19 | } from 'incompose'; 20 | 21 | const Counter = (props) => ( 22 |
23 |

component with lifecycle

24 |
25 | ); 26 | 27 | export default compose( 28 | withLifecycle({ 29 | componentDidMount : (el) => console.warn('mounted'), 30 | componentWillUnmount : () => console.warn('will unmount'), 31 | componentShouldUpdate : (props, nextProps) => true, // on false, component won't update 32 | }), 33 | )(Counter); 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/flattenProps.md: -------------------------------------------------------------------------------- 1 | # flattenProps 2 | ## Description 3 | Flattens a prop so that its fields are spread out into the props object. 4 | 5 | ## API 6 | ``` 7 | flattenProps( 8 | propsName : string 9 | ) : Function 10 | ``` 11 | 12 | ## Example 13 | ```jsx 14 | import { 15 | compose, 16 | withDefaultProps 17 | } from 'incompose'; 18 | 19 | /** 20 | * original props are: 21 | * props.person = { 22 | * name : 'John', 23 | * lastName : 'Doe', 24 | * age : 33 25 | * } 26 | * 27 | * flattened props are: 28 | * props = { 29 | * name : 'John', 30 | * lastName : 'Doe', 31 | * age : 33 32 | * } 33 | */ 34 | const LeaderBoard = (props) => ( 35 |
36 |

{props.name} {props.lastName}

37 | age : {props.age} 38 |
39 | ); 40 | 41 | export default compose( 42 | flattenProps('person'), // define that props called person should be flattened 43 | )(LeaderBoard); 44 | 45 | 46 | // somewhere in your code - component call jsx 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright 2017 Roman Zanettin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /dist/createEagerFactory.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _createEagerElementUtil = require('./utils/createEagerElementUtil'); 8 | 9 | var _createEagerElementUtil2 = _interopRequireDefault(_createEagerElementUtil); 10 | 11 | var _isReferentiallyTransparentFunctionComponent = require('./isReferentiallyTransparentFunctionComponent'); 12 | 13 | var _isReferentiallyTransparentFunctionComponent2 = _interopRequireDefault(_isReferentiallyTransparentFunctionComponent); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | /** 18 | * @author recompose (https://github.com/acdlite/recompose) 19 | */ 20 | 21 | var createFactory = function createFactory(type) { 22 | var isReferentiallyTransparent = (0, _isReferentiallyTransparentFunctionComponent2.default)(type); 23 | return function (p, c) { 24 | return (0, _createEagerElementUtil2.default)(false, isReferentiallyTransparent, type, p, c); 25 | }; 26 | }; 27 | 28 | exports.default = createFactory; -------------------------------------------------------------------------------- /src/baconObservableConfig.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import $$observable from 'symbol-observable'; 6 | import Bacon from 'baconjs'; // eslint-disable-line import/no-unresolved 7 | 8 | const config = { 9 | fromESObservable: observable => 10 | Bacon.fromBinder(sink => { 11 | const { unsubscribe } = observable.subscribe({ 12 | next: val => sink(new Bacon.Next(val)), 13 | error: err => sink(new Bacon.Error(err)), 14 | complete: () => sink(new Bacon.End()), 15 | }); 16 | return unsubscribe; 17 | }), 18 | toESObservable: stream => ({ 19 | subscribe: observer => { 20 | const unsubscribe = stream.subscribe(event => { 21 | if (event.hasValue()) { 22 | observer.next(event.value()); 23 | } else if (event.isError()) { 24 | observer.error(event.error); 25 | } else if (event.isEnd()) { 26 | observer.complete(); 27 | } 28 | }); 29 | return { unsubscribe }; 30 | }, 31 | [$$observable]() { 32 | return this; 33 | }, 34 | }), 35 | }; 36 | 37 | export default config; 38 | -------------------------------------------------------------------------------- /src/withPropsOnChange.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import { Component } from 'inferno'; 6 | import pick from './utils/pick'; 7 | import shallowEqual from './shallowEqual'; 8 | import createHelper from './createHelper'; 9 | 10 | const withPropsOnChange = (shouldMapOrKeys, propsMapper) => BaseComponent => { 11 | const shouldMap = 12 | typeof shouldMapOrKeys === 'function' 13 | ? shouldMapOrKeys 14 | : (props, nextProps) => 15 | !shallowEqual( 16 | pick(props, shouldMapOrKeys), 17 | pick(nextProps, shouldMapOrKeys), 18 | ); 19 | 20 | return class extends Component { 21 | computedProps = propsMapper(this.props); 22 | 23 | componentWillReceiveProps(nextProps) { 24 | if (shouldMap(this.props, nextProps)) { 25 | this.computedProps = propsMapper(nextProps); 26 | } 27 | } 28 | 29 | render() { 30 | return ( 31 | 32 | ); 33 | } 34 | }; 35 | }; 36 | 37 | export default createHelper(withPropsOnChange, 'withPropsOnChange'); 38 | -------------------------------------------------------------------------------- /docs/createEventHandler.md: -------------------------------------------------------------------------------- 1 | # createEventHandler 2 | ## Description 3 | Returns an object with properties `handler` and `stream`. `stream` is an observable sequence, and `handler` is a function that pushes new values onto the sequence. Useful for creating event handlers like `onClick`. 4 | 5 | ## API 6 | ``` 7 | createEventHandler(): { 8 | handler: (value: T) => void 9 | stream: Observable, 10 | } 11 | ``` 12 | 13 | ## Example 14 | ```jsx 15 | const Counter = componentFromStream(props$ => { 16 | const { handler: increment, stream: increment$ } = createEventHandler() 17 | const { handler: decrement, stream: decrement$ } = createEventHandler() 18 | const count$ = Observable.merge( 19 | increment$.mapTo(1), 20 | decrement$.mapTo(-1) 21 | ) 22 | .startWith(0) 23 | .scan((count, n) => count + n, 0) 24 | 25 | return props$.combineLatest( 26 | count$, 27 | (props, count) => 28 |
29 | Count: {count} 30 | 31 | 32 |
33 | ) 34 | }) 35 | ``` 36 | -------------------------------------------------------------------------------- /src/withState.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import { Component } from 'inferno'; 6 | import createHelper from './createHelper'; 7 | 8 | const withState = ( 9 | stateName, 10 | stateUpdaterName, 11 | initialState, 12 | ) => BaseComponent => { 13 | const StatedComponent = class extends Component { 14 | state = { 15 | stateValue: 16 | typeof initialState === 'function' 17 | ? initialState(this.props) 18 | : initialState, 19 | }; 20 | 21 | updateStateValue = (updateFn, callback) => 22 | this.setState( 23 | ({ stateValue }) => ({ 24 | stateValue: 25 | typeof updateFn === 'function' ? updateFn(stateValue) : updateFn, 26 | }), 27 | callback, 28 | ); 29 | 30 | render() { 31 | return ( 32 | 38 | ); 39 | } 40 | }; 41 | return props => ; 42 | }; 43 | 44 | export default createHelper(withState, 'withState'); 45 | -------------------------------------------------------------------------------- /docs/withHandlers.md: -------------------------------------------------------------------------------- 1 | # withHandlers 2 | ## Description 3 | This helper acts mostly like internal `Inferno.createLink` helper. Please see the example to see them both in action side-by-side. 4 | 5 | ## API 6 | ``` 7 | withHandlers( 8 | handlerCreators : { 9 | [handlerName : string] : (props : Object) => Function 10 | } 11 | ) : Function; 12 | ``` 13 | 14 | ## Example 15 | ```jsx 16 | import { 17 | compose, 18 | withState, 19 | withHandlers, 20 | } from 'incompose'; 21 | 22 | const generateRandomValue = (props, event) => { 23 | props.setValue(Math.floor(Math.random() * 10) + 1); 24 | }; 25 | 26 | const Random = (props) => ( 27 |
28 |

{props.value}

29 | 30 | 31 |
32 | ); 33 | 34 | const withRandomHandlers = withHandlers({ 35 | doGenerateRandomValue : (props) => (event) => generateRandomValue(props), 36 | }); 37 | 38 | export default compose( 39 | withState('value', 'setValue', 1), 40 | withRandomHandlers, 41 | )(Random); 42 | ``` 43 | -------------------------------------------------------------------------------- /src/withReducer.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import { Component } from 'inferno'; 6 | import createHelper from './createHelper'; 7 | 8 | const withReducer = ( 9 | stateName, 10 | dispatchName, 11 | reducer, 12 | initialState, 13 | ) => BaseComponent => { 14 | return class 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: '@@incompose/INIT' }); 26 | } 27 | 28 | dispatch = action => 29 | this.setState(({ stateValue }) => ({ 30 | stateValue: reducer(stateValue, action), 31 | })); 32 | 33 | render() { 34 | return ( 35 | 41 | ); 42 | } 43 | }; 44 | }; 45 | 46 | export default createHelper(withReducer, 'withReducer'); 47 | -------------------------------------------------------------------------------- /src/withLifecycle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | export default lifecycles => Component => { 6 | // avoid breaking changes by mapping class lifecycles to functional lifecycles 7 | const functionalLifecycles = {}; 8 | 9 | if (lifecycles.componentWillMount) { 10 | functionalLifecycles.onComponentWillMount = lifecycles.componentWillMount; 11 | } 12 | if (lifecycles.componentDidMount) { 13 | functionalLifecycles.onComponentDidMount = lifecycles.componentDidMount; 14 | } 15 | if (lifecycles.shouldComponentUpdate) { 16 | functionalLifecycles.onComponentShouldUpdate = 17 | lifecycles.shouldComponentUpdate; 18 | } 19 | if (lifecycles.componentWillUpdate) { 20 | functionalLifecycles.onComponentWillUpdate = lifecycles.componentWillUpdate; 21 | } 22 | if (lifecycles.componentDidUpdate) { 23 | functionalLifecycles.onComponentDidUpdate = lifecycles.componentDidUpdate; 24 | } 25 | if (lifecycles.componentWillUnmount) { 26 | functionalLifecycles.onComponentWillUnmount = 27 | lifecycles.componentWillUnmount; 28 | } 29 | 30 | Component.defaultHooks = { 31 | ...functionalLifecycles, 32 | }; 33 | 34 | return Component; 35 | }; 36 | -------------------------------------------------------------------------------- /dist/branch.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _compose = _interopRequireDefault(require("./compose")); 9 | 10 | var _createHelper = _interopRequireDefault(require("./createHelper")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | /** 15 | * @author recompose (https://github.com/acdlite/recompose) 16 | */ 17 | var identity = function identity(Component) { 18 | return Component; 19 | }; 20 | 21 | var branch = function branch(test, left) { 22 | var right = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : identity; 23 | return function (BaseComponent) { 24 | var leftFactory; 25 | var rightFactory; 26 | return function (props) { 27 | if (test(props)) { 28 | leftFactory = leftFactory || (0, _compose.default)(left)(BaseComponent); 29 | return leftFactory(props); 30 | } 31 | 32 | rightFactory = rightFactory || (0, _compose.default)(right)(BaseComponent); 33 | return rightFactory(props); 34 | }; 35 | }; 36 | }; 37 | 38 | var _default = (0, _createHelper.default)(branch, 'branch'); 39 | 40 | exports.default = _default; -------------------------------------------------------------------------------- /docs/componentFromStream.md: -------------------------------------------------------------------------------- 1 | # componentFromStream 2 | ## Description 3 | Creates a React component by mapping an observable stream of props to a stream of React nodes (vdom). 4 | 5 | You can think of propsToReactNode as a function f such that 6 | 7 | ``` 8 | const vdom$ = f(props$) 9 | ``` 10 | 11 | where props$ is a stream of props and vdom$ is a stream of React nodes. This formulation similar to the popular notion of React views as a function, often communicated as 12 | 13 | ``` 14 | v = f(d) 15 | ``` 16 | 17 | ## API 18 | ``` 19 | componentFromStream( 20 | propsToReactNode: (props$: Observable) => Observable 21 | ): InfernoComponent 22 | ``` 23 | 24 | ## Example 25 | ```jsx 26 | const Counter = componentFromStream(props$ => { 27 | const { handler: increment, stream: increment$ } = createEventHandler() 28 | const { handler: decrement, stream: decrement$ } = createEventHandler() 29 | const count$ = Observable.merge( 30 | increment$.mapTo(1), 31 | decrement$.mapTo(-1) 32 | ) 33 | .startWith(0) 34 | .scan((count, n) => count + n, 0) 35 | 36 | return props$.combineLatest( 37 | count$, 38 | (props, count) => 39 |
40 | Count: {count} 41 | 42 | 43 |
44 | ) 45 | }) 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/withState.md: -------------------------------------------------------------------------------- 1 | # withState 2 | ## Description 3 | Passes two additional props to the base component: a state value, and a function to update that state value. 4 | 5 | ## API 6 | ``` 7 | withState( 8 | propName : string, 9 | setterName : string, 10 | initialValue : any 11 | ) : Function; 12 | ``` 13 | 14 | ## Example 15 | ```jsx 16 | import { 17 | linkEvent 18 | } from 'inferno'; 19 | 20 | import { 21 | compose, 22 | withState 23 | } from 'incompose'; 24 | 25 | const inc = (props) => { 26 | props.setCount(props.count += 1); 27 | }; 28 | 29 | const dec = (props) => { 30 | props.setCount(props.count -= 1); 31 | }; 32 | 33 | const Counter = (props) => ( 34 |
35 |

count : {props.count}

36 | 37 | 38 |
39 | ); 40 | 41 | /** 42 | * with state creates 2 new props on the component props 43 | * props.count - contains the value (1 is set as default value) 44 | * props.setCount - contains the setter function 45 | */ 46 | const withCounterState = withState('count', 'setCount', 1); 47 | 48 | /** 49 | * with compose all the extended functions are composed BEFORE Counter 50 | * gets rendered. Please not that order matters. 51 | */ 52 | export default compose( 53 | withCounterState, 54 | )(Counter); 55 | ``` 56 | -------------------------------------------------------------------------------- /docs/compose.md: -------------------------------------------------------------------------------- 1 | # compose 2 | ## Description 3 | Use to compose multiple higher-order components into a single higher-order component. 4 | This works exactly like the function of the same name in Redux, or lodash's `flowRight()`. 5 | 6 | ## API 7 | ``` 8 | compose( 9 | ...functions : Array 10 | ) : Function 11 | ``` 12 | 13 | ## Example 14 | ```jsx 15 | import { 16 | linkEvent 17 | } from 'inferno'; 18 | 19 | import { 20 | compose, 21 | withState 22 | } from 'incompose'; 23 | 24 | const inc = (props) => { 25 | props.setCount(props.count += 1); 26 | }; 27 | 28 | const dec = (props) => { 29 | props.setCount(props.count -= 1); 30 | }; 31 | 32 | const Counter = (props) => ( 33 |
34 |

count : {props.count}

35 | 36 | 37 |
38 | ); 39 | 40 | /** 41 | * with state creates 2 new props on the component props 42 | * props.count - contains the value (1 is set as default value) 43 | * props.setCount - contains the setter function 44 | */ 45 | const withCounterState = withState('count', 'setCount', 1); 46 | 47 | /** 48 | * with compose all the extended functions are composed BEFORE Counter 49 | * gets rendered. Please not that order matters. 50 | */ 51 | export default compose( 52 | withCounterState, 53 | )(Counter); 54 | ``` 55 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @file named exports 3 | * @author Roman Zanettin 4 | * @date 2017-02-05 5 | */ 6 | 7 | export { default as branch } from './branch'; 8 | export { default as componentFromStream } from './componentFromStream'; 9 | export { default as compose } from './compose'; 10 | export { default as createEventHandler } from './createEventHandler'; 11 | export { default as createSink } from './createSink'; 12 | export { default as defaultProps } from './defaultProps'; 13 | export { default as flattenProps } from './flattenProps'; 14 | export { default as mapProps } from './mapProps'; 15 | export { default as nest } from './nest'; 16 | export { default as pure } from './pure'; 17 | export { default as renderComponent } from './renderComponent'; 18 | export { default as renderNothing } from './renderNothing'; 19 | export { default as renameProp } from './renameProp'; 20 | export { default as renameProps } from './renameProps'; 21 | export { default as setObservableConfig } from './setObservableConfig'; 22 | export { default as shouldUpdate } from './shouldUpdate'; 23 | export { default as withLifecycle } from './withLifecycle'; 24 | export { default as withHandlers } from './withHandlers'; 25 | export { default as withProps } from './withProps'; 26 | export { default as withPropsOnChange } from './withPropsOnChange'; 27 | export { default as withReducer } from './withReducer'; 28 | export { default as withState } from './withState'; 29 | -------------------------------------------------------------------------------- /dist/pure.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _compose = _interopRequireDefault(require("./compose")); 9 | 10 | var _shouldUpdate = _interopRequireDefault(require("./shouldUpdate")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 15 | 16 | var withUpdatePolicy = (0, _shouldUpdate.default)(function (props, nextProps) { 17 | // handle invalid props 18 | if (!props || !nextProps || _typeof(props) !== 'object' || _typeof(nextProps) !== 'object') { 19 | return true; 20 | } 21 | 22 | var keys = Object.keys(props); 23 | 24 | for (var i = 0; i < keys.length; i += 1) { 25 | if (props[keys[i]] !== nextProps[keys[i]]) { 26 | return true; // just update if we find a shallow diff 27 | } 28 | } 29 | 30 | return false; 31 | }); 32 | /** 33 | * @param {Function} component 34 | * @returns {Function} 35 | */ 36 | 37 | var _default = function _default(Component) { 38 | return (0, _compose.default)(withUpdatePolicy)(Component); 39 | }; 40 | 41 | exports.default = _default; -------------------------------------------------------------------------------- /dist/withHandlers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file withHandlers 16 | * @author Roman Zanettin 17 | * @date 2017-02-07 18 | */ 19 | var _default = function _default(handlerCreators) { 20 | return function (Component) { 21 | return function (props) { 22 | var composed = Object.keys(handlerCreators).reduce(function (acc, key) { 23 | acc[key] = handlerCreators[key](props); 24 | return acc; 25 | }, {}); 26 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, props, composed))); 27 | }; 28 | }; 29 | }; 30 | 31 | exports.default = _default; -------------------------------------------------------------------------------- /dist/mapProps.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file mapProps 16 | * @desc maps props on component init 17 | * @author Zoltan Dalmadi 18 | * @date 2018-10-18 19 | */ 20 | 21 | /** 22 | * @param {Object} - mapper function 23 | * @param {Function} - component 24 | * @param {Object} - component props 25 | * @returns {Function} 26 | */ 27 | var _default = function _default(mapper) { 28 | return function (Component) { 29 | return function (props) { 30 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, mapper(props)))); 31 | }; 32 | }; 33 | }; 34 | 35 | exports.default = _default; -------------------------------------------------------------------------------- /docs/shouldUpdate.md: -------------------------------------------------------------------------------- 1 | # shouldUpdate 2 | ## Description 3 | Higher-order component version of `shouldComponentUpdate()`. The test function accepts both the current props and the next props. 4 | If the return value of the defined expression is `false`, the component won't update. 5 | 6 | ## API 7 | ``` 8 | shouldUpdate( 9 | expression : (props, nextProps) : boolean, 10 | ) : Function; 11 | ``` 12 | 13 | ## Example 14 | ```jsx 15 | import { 16 | linkEvent 17 | } from 'inferno'; 18 | 19 | import { 20 | compose, 21 | withState, 22 | shouldUpdate 23 | } from 'incompose'; 24 | 25 | const inc = (props) => { 26 | props.setCount(props.count += 1); 27 | }; 28 | 29 | const dec = (props) => { 30 | props.setCount(props.count -= 1); 31 | }; 32 | 33 | const Counter = (props) => ( 34 |
35 |

count : {props.count}

36 | 37 | 38 |
39 | ); 40 | 41 | const withCounterState = withState('count', 'setCount', 1); 42 | 43 | /** 44 | * should update prevents the component of re-render (shouldUpdate lifecycle hook) 45 | * you can compare current and next props and decide whether the component 46 | * should update or not. In this example, the counter just updates if 47 | * props.count is even. 48 | */ 49 | const withUpdatePolicy = shouldUpdate((props, nextProps) => ( 50 | nextProps.count % 2 === 0 51 | )); 52 | 53 | export default compose( 54 | withCounterState, 55 | withUpdatePolicy, 56 | )(Counter); 57 | ``` 58 | -------------------------------------------------------------------------------- /dist/createHelper.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | /** 9 | * @author recompose (https://github.com/acdlite/recompose) 10 | */ 11 | 12 | /*eslint-env node*/ 13 | var createHelper = function createHelper(func, helperName) { 14 | var setDisplayName = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true; 15 | var noArgs = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; 16 | 17 | if (process.env.NODE_ENV !== 'production' && setDisplayName) { 18 | /* eslint-disable global-require */ 19 | var wrapDisplayName = require('./wrapDisplayName').default; 20 | /* eslint-enable global-require */ 21 | 22 | 23 | if (noArgs) { 24 | return function (BaseComponent) { 25 | var Component = func(BaseComponent); 26 | Component.displayName = wrapDisplayName(BaseComponent, helperName); 27 | return Component; 28 | }; 29 | } 30 | 31 | return function () { 32 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 33 | args[_key] = arguments[_key]; 34 | } 35 | 36 | return function (BaseComponent) { 37 | var Component = func.apply(void 0, args)(BaseComponent); 38 | Component.displayName = wrapDisplayName(BaseComponent, helperName); 39 | return Component; 40 | }; 41 | }; 42 | } 43 | 44 | return func; 45 | }; 46 | 47 | var _default = createHelper; 48 | exports.default = _default; -------------------------------------------------------------------------------- /dist/defaultProps.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file defaultProps 16 | * @desc sets default values for owner props 17 | * @author Roman Zanettin 18 | * @date 2017-01-06 19 | */ 20 | 21 | /** 22 | * @param {Object} - default props config 23 | * @param {Function} - component 24 | * @param {Object} - component props 25 | * @returns {Function} 26 | */ 27 | var _default = function _default(config) { 28 | return function (Component) { 29 | return function (props) { 30 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, config, props))); 31 | }; 32 | }; 33 | }; 34 | 35 | exports.default = _default; -------------------------------------------------------------------------------- /dist/withProps.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file withProps 16 | * @desc appends props on component init (does overwrite existing props) 17 | * @author Roman Zanettin 18 | * @date 2017-01-06 19 | */ 20 | 21 | /** 22 | * @param {Object} - default props config 23 | * @param {Function} - component 24 | * @param {Object} - component props 25 | * @returns {Function} 26 | */ 27 | var _default = function _default(config) { 28 | return function (Component) { 29 | return function (props) { 30 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, props, config))); 31 | }; 32 | }; 33 | }; 34 | 35 | exports.default = _default; -------------------------------------------------------------------------------- /dist/createEventHandler.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = exports.createEventHandlerWithConfig = void 0; 7 | 8 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 9 | 10 | var _changeEmitter = require("change-emitter"); 11 | 12 | var _setObservableConfig = require("./setObservableConfig"); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15 | 16 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 17 | 18 | var createEventHandlerWithConfig = function createEventHandlerWithConfig(config) { 19 | return function () { 20 | var emitter = (0, _changeEmitter.createChangeEmitter)(); 21 | var stream = config.fromESObservable(_defineProperty({ 22 | subscribe: function subscribe(observer) { 23 | var unsubscribe = emitter.listen(function (value) { 24 | return observer.next(value); 25 | }); 26 | return { 27 | unsubscribe: unsubscribe 28 | }; 29 | } 30 | }, _symbolObservable.default, function () { 31 | return this; 32 | })); 33 | return { 34 | handler: emitter.emit, 35 | stream: stream 36 | }; 37 | }; 38 | }; 39 | 40 | exports.createEventHandlerWithConfig = createEventHandlerWithConfig; 41 | var createEventHandler = createEventHandlerWithConfig(_setObservableConfig.config); 42 | var _default = createEventHandler; 43 | exports.default = _default; -------------------------------------------------------------------------------- /dist/renameProps.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file renameProps 16 | * @desc renames the owner prop 17 | * @author Roman Zanettin 18 | * @date 2017-02-06 19 | */ 20 | 21 | /** 22 | * @param {Object} - config ({oldName : 'newName', a : 'z'}) 23 | * @param {Function} - component 24 | * @param {Object} - component props 25 | * @returns {Function} 26 | */ 27 | var _default = function _default(config) { 28 | return function (Component) { 29 | return function (props) { 30 | var newProps = Object.keys(props).reduce(function (acc, key) { 31 | acc[config[key] || key] = props[key]; 32 | return acc; 33 | }, {}); 34 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, newProps))); 35 | }; 36 | }; 37 | }; 38 | 39 | exports.default = _default; -------------------------------------------------------------------------------- /dist/renameProp.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | /** 15 | * @file renameProp 16 | * @desc renames the owner prop 17 | * @author Roman Zanettin 18 | * @date 2017-02-06 19 | */ 20 | 21 | /** 22 | * @param {string} - old name 23 | * @param {string} - new name 24 | * @param {Function} - component 25 | * @param {Object} - component props 26 | * @returns {Function} 27 | */ 28 | var _default = function _default(oldName, newName) { 29 | return function (Component) { 30 | return function (props) { 31 | var newProps = props; 32 | 33 | if (props[oldName]) { 34 | newProps[newName] = props[oldName]; 35 | delete newProps[oldName]; 36 | } 37 | 38 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, newProps))); 39 | }; 40 | }; 41 | }; 42 | 43 | exports.default = _default; -------------------------------------------------------------------------------- /dist/xstreamObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 9 | 10 | var _xstream = _interopRequireDefault(require("xstream")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | // eslint-disable-line import/no-unresolved 17 | var noop = function noop() {}; 18 | 19 | var config = { 20 | fromESObservable: function fromESObservable(observable) { 21 | return _xstream.default.create({ 22 | subscription: null, 23 | start: function start(listener) { 24 | this.subscription = observable.subscribe(listener); 25 | }, 26 | stop: function stop() { 27 | this.subscription.unsubscribe(); 28 | } 29 | }); 30 | }, 31 | toESObservable: function toESObservable(stream) { 32 | return _defineProperty({ 33 | subscribe: function subscribe(observer) { 34 | var listener = { 35 | next: observer.next || noop, 36 | error: observer.error || noop, 37 | complete: observer.complete || noop 38 | }; 39 | stream.addListener(listener); 40 | return { 41 | unsubscribe: function unsubscribe() { 42 | return stream.removeListener(listener); 43 | } 44 | }; 45 | } 46 | }, _symbolObservable.default, function () { 47 | return this; 48 | }); 49 | } 50 | }; 51 | var _default = config; 52 | exports.default = _default; -------------------------------------------------------------------------------- /dist/renderComponent.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | var _createHelper = _interopRequireDefault(require("./createHelper")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 15 | 16 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 17 | 18 | var renderComponent = function renderComponent(Component) { 19 | return function () { 20 | var RenderComponent = function RenderComponent(props) { 21 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, props))); 22 | }; 23 | 24 | if (process.env.NODE_ENV !== 'production') { 25 | /* eslint-disable global-require */ 26 | var wrapDisplayName = require('./wrapDisplayName').default; 27 | /* eslint-enable global-require */ 28 | 29 | 30 | RenderComponent.displayName = wrapDisplayName(Component, 'renderComponent'); 31 | } 32 | 33 | return RenderComponent; 34 | }; 35 | }; 36 | 37 | var _default = (0, _createHelper.default)(renderComponent, 'renderComponent', false); 38 | 39 | exports.default = _default; -------------------------------------------------------------------------------- /dist/utils/createEagerElementUtil.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | 7 | var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; /** 8 | * @author recompose (https://github.com/acdlite/recompose) 9 | */ 10 | 11 | var _inferno = require('inferno'); 12 | 13 | var _inferno2 = _interopRequireDefault(_inferno); 14 | 15 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 16 | 17 | var createEagerElementUtil = function createEagerElementUtil(hasKey, isReferentiallyTransparent, type, props, children) { 18 | if (!hasKey && isReferentiallyTransparent) { 19 | if (children) { 20 | return type(_extends({}, props, { children: children })); 21 | } 22 | return type(props); 23 | } 24 | 25 | var Component = type; 26 | 27 | if (children) { 28 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _extends({}, props, { 29 | children: children 30 | }))); 31 | } 32 | 33 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _extends({}, props))); 34 | }; 35 | 36 | exports.default = createEagerElementUtil; -------------------------------------------------------------------------------- /src/componentFromStream.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author recompose (https://github.com/acdlite/recompose) 3 | */ 4 | 5 | import { Component } from 'inferno'; 6 | import { createChangeEmitter } from 'change-emitter'; 7 | import $$observable from 'symbol-observable'; 8 | import { config as globalConfig } from './setObservableConfig'; 9 | 10 | export const componentFromStreamWithConfig = config => propsToVdom => 11 | class ComponentFromStream extends Component { 12 | state = { vdom: null }; 13 | 14 | propsEmitter = createChangeEmitter(); 15 | 16 | // Stream of props 17 | props$ = config.fromESObservable({ 18 | subscribe: observer => { 19 | const unsubscribe = this.propsEmitter.listen(props => { 20 | if (props) { 21 | observer.next(props); 22 | } else { 23 | observer.complete(); 24 | } 25 | }); 26 | return { unsubscribe }; 27 | }, 28 | [$$observable]() { 29 | return this; 30 | }, 31 | }); 32 | 33 | // Stream of vdom 34 | vdom$ = config.toESObservable(propsToVdom(this.props$)); 35 | 36 | componentWillMount() { 37 | // Subscribe to child prop changes so we know when to re-render 38 | this.subscription = this.vdom$.subscribe({ 39 | next: vdom => { 40 | this.setState({ vdom }); 41 | }, 42 | }); 43 | this.propsEmitter.emit(this.props); 44 | } 45 | 46 | componentWillReceiveProps(nextProps) { 47 | // Receive new props from the owner 48 | this.propsEmitter.emit(nextProps); 49 | } 50 | 51 | shouldComponentUpdate(nextProps, nextState) { 52 | return nextState.vdom !== this.state.vdom; 53 | } 54 | 55 | componentWillUnmount() { 56 | // Call without arguments to complete stream 57 | this.propsEmitter.emit(); 58 | 59 | // Clean-up subscription before un-mounting 60 | this.subscription.unsubscribe(); 61 | } 62 | 63 | render() { 64 | return this.state.vdom; 65 | } 66 | }; 67 | 68 | const componentFromStream = propsToVdom => 69 | componentFromStreamWithConfig(globalConfig)(propsToVdom); 70 | 71 | export default componentFromStream; 72 | -------------------------------------------------------------------------------- /dist/rxjs4ObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 9 | 10 | var _rx = _interopRequireDefault(require("rx")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | // eslint-disable-line import/no-unresolved 17 | var config = { 18 | fromESObservable: function fromESObservable(observable) { 19 | return _rx.default.Observable.create(function (observer) { 20 | var _observable$subscribe = observable.subscribe({ 21 | next: function next(val) { 22 | return observer.onNext(val); 23 | }, 24 | error: function error(_error) { 25 | return observer.onError(_error); 26 | }, 27 | complete: function complete() { 28 | return observer.onCompleted(); 29 | } 30 | }), 31 | unsubscribe = _observable$subscribe.unsubscribe; 32 | 33 | return unsubscribe; 34 | }); 35 | }, 36 | toESObservable: function toESObservable(rxObservable) { 37 | return _defineProperty({ 38 | subscribe: function subscribe(observer) { 39 | var subscription = rxObservable.subscribe(function (val) { 40 | return observer.next(val); 41 | }, function (error) { 42 | return observer.error(error); 43 | }, function () { 44 | return observer.complete(); 45 | }); 46 | return { 47 | unsubscribe: function unsubscribe() { 48 | return subscription.dispose(); 49 | } 50 | }; 51 | } 52 | }, _symbolObservable.default, function () { 53 | return this; 54 | }); 55 | } 56 | }; 57 | var _default = config; 58 | exports.default = _default; -------------------------------------------------------------------------------- /docs/withPropsOnChange.md: -------------------------------------------------------------------------------- 1 | # withPropsOnChange 2 | ## Description 3 | Like `withProps()`, except the new props are only created when one of the owner props specified by `shouldMapOrKeys` changes. This helps ensure that expensive computations inside `createProps()` are only executed when necessary. 4 | 5 | Instead of an array of prop keys, the first parameter can also be a function that returns a boolean, given the current props and the next props. This allows you to customize when `createProps()` should be called. 6 | 7 | ## API 8 | ``` 9 | withPropsOnChange( 10 | shouldMapOrKeys : Array| (props : Object, nextProps : Object) => boolean, 11 | createProps : (ownerProps : Object) => Object 12 | ) : Function 13 | ``` 14 | 15 | ## Example 16 | ```jsx 17 | import { 18 | compose, 19 | withPropsOnChange, 20 | withState 21 | } from 'incompose'; 22 | 23 | const inc = (props) => { 24 | props.setCount(props.count += 1); 25 | }; 26 | 27 | const dec = (props) => { 28 | props.setCount(props.count -= 1); 29 | }; 30 | 31 | const performHeavyCalculation = (props) => { 32 | // ... do some heavy lifting 33 | console.warn('do some heavy lifting...'); 34 | return 1; 35 | } 36 | 37 | const Counter = (props) => ( 38 |
39 |

count : {props.count}

40 | 41 | 42 |
43 | ); 44 | 45 | const withCounterState = withState('count', 'setCount', 1); 46 | 47 | /** 48 | * if next counter value can be divided by 2 without any rest 49 | * the function on the `specialProp` key will be re-executed 50 | * and the new value set. Otherwise nothing will change and 51 | * your heavy calculation won't be executed. 52 | */ 53 | const withExtendedProps = withPropsOnChange( 54 | (props, nextProps) => nextProps.count % 2 === 0, 55 | (props) => ({ 56 | specialProp : performHeavyCalculation(props.count), 57 | }) 58 | ) 59 | 60 | export default compose( 61 | withCounterState, 62 | withExtendedProps, 63 | )(Counter); 64 | ``` 65 | -------------------------------------------------------------------------------- /dist/flydObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 9 | 10 | var _flyd = _interopRequireDefault(require("flyd")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | // eslint-disable-line import/no-unresolved 17 | var noop = function noop() {}; 18 | 19 | var config = { 20 | fromESObservable: function fromESObservable(observable) { 21 | var stream = _flyd.default.stream(); 22 | 23 | var _observable$subscribe = observable.subscribe({ 24 | next: function next(value) { 25 | return stream(value); 26 | }, 27 | error: function error(_error) { 28 | return stream({ 29 | error: _error 30 | }); 31 | }, 32 | complete: function complete() { 33 | return stream.end(true); 34 | } 35 | }), 36 | unsubscribe = _observable$subscribe.unsubscribe; 37 | 38 | _flyd.default.on(unsubscribe, stream.end); 39 | 40 | return stream; 41 | }, 42 | toESObservable: function toESObservable(stream) { 43 | return _defineProperty({ 44 | subscribe: function subscribe(observer) { 45 | var sub = _flyd.default.on(observer.next || noop, stream); 46 | 47 | _flyd.default.on(function (_) { 48 | return observer.complete(); 49 | }, sub.end); // eslint-disable-line no-unused-vars 50 | 51 | 52 | return { 53 | unsubscribe: function unsubscribe() { 54 | return sub.end(true); 55 | } 56 | }; 57 | } 58 | }, _symbolObservable.default, function () { 59 | return this; 60 | }); 61 | } 62 | }; 63 | var _default = config; 64 | exports.default = _default; -------------------------------------------------------------------------------- /dist/baconObservableConfig.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 9 | 10 | var _baconjs = _interopRequireDefault(require("baconjs")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | // eslint-disable-line import/no-unresolved 17 | var config = { 18 | fromESObservable: function fromESObservable(observable) { 19 | return _baconjs.default.fromBinder(function (sink) { 20 | var _observable$subscribe = observable.subscribe({ 21 | next: function next(val) { 22 | return sink(new _baconjs.default.Next(val)); 23 | }, 24 | error: function error(err) { 25 | return sink(new _baconjs.default.Error(err)); 26 | }, 27 | complete: function complete() { 28 | return sink(new _baconjs.default.End()); 29 | } 30 | }), 31 | unsubscribe = _observable$subscribe.unsubscribe; 32 | 33 | return unsubscribe; 34 | }); 35 | }, 36 | toESObservable: function toESObservable(stream) { 37 | return _defineProperty({ 38 | subscribe: function subscribe(observer) { 39 | var unsubscribe = stream.subscribe(function (event) { 40 | if (event.hasValue()) { 41 | observer.next(event.value()); 42 | } else if (event.isError()) { 43 | observer.error(event.error); 44 | } else if (event.isEnd()) { 45 | observer.complete(); 46 | } 47 | }); 48 | return { 49 | unsubscribe: unsubscribe 50 | }; 51 | } 52 | }, _symbolObservable.default, function () { 53 | return this; 54 | }); 55 | } 56 | }; 57 | var _default = config; 58 | exports.default = _default; -------------------------------------------------------------------------------- /docs/withReducer.md: -------------------------------------------------------------------------------- 1 | # withReducer 2 | ## Description 3 | Similar to `withState()`, but state updates are applied using a reducer function. A reducer is a function that receives a state and an action, and returns a new state. 4 | 5 | Passes two additional props to the base component: a state value, and a dispatch method. The dispatch method sends an action to the reducer, and the new state is applied. 6 | 7 | ## API 8 | ``` 9 | withReducer( 10 | stateName : string, 11 | dispatchName : string, 12 | reducer : (state : S, action : A) => S, 13 | initialState : S 14 | ) : Function 15 | ``` 16 | 17 | ## Example 18 | ```jsx 19 | import { 20 | compose, 21 | withReducer 22 | } from 'incompose'; 23 | 24 | const INC = 'action/inc'; 25 | const DEC = 'action/dec'; 26 | const MIN = 'action/min'; 27 | const MAX = 'action/max'; 28 | 29 | const Component = (props) => ( 30 |
31 |

reducer example

32 |

{props.counter.count}

33 | 34 | 35 | 36 | 37 |
38 | ); 39 | 40 | const reducer = (state, action) => { 41 | 42 | const newState = state; 43 | 44 | switch(action) { 45 | 46 | case INC: { 47 | newState.count += 1; 48 | return newState; 49 | } 50 | 51 | case DEC: { 52 | newState.count -= 1; 53 | return newState; 54 | } 55 | 56 | case MIN: { 57 | newState.count = state.min; 58 | return newState; 59 | } 60 | 61 | case MAX: { 62 | newState.count = state.max; 63 | return newState; 64 | } 65 | 66 | default: { 67 | return newState; 68 | } 69 | 70 | } 71 | }; 72 | 73 | export default compose( 74 | withReducer( 75 | 'counter', 76 | 'counterDispatch', 77 | reducer, 78 | { 79 | count : 50, 80 | min : 1, 81 | max : 100, 82 | } 83 | ), 84 | )(Component); 85 | ``` 86 | -------------------------------------------------------------------------------- /dist/flattenProps.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 11 | 12 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 13 | 14 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 15 | 16 | /** 17 | * @file flattenProps 18 | * @desc renames the owner prop 19 | * @author Roman Zanettin 20 | * @date 2017-02-06 21 | */ 22 | 23 | /** 24 | * @param {string} - prop name to flatten 25 | * @param {Function} - component 26 | * @param {Object} - component props 27 | * @returns {Function} 28 | */ 29 | var _default = function _default(propName) { 30 | return function (Component) { 31 | return function (props) { 32 | var newProps = props[propName] && _typeof(props[propName]) === 'object' ? _objectSpread({}, props, props[propName]) : _objectSpread({}, props); 33 | 34 | if (newProps[propName]) { 35 | delete newProps[propName]; 36 | } 37 | 38 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, Component, _objectSpread({}, newProps))); 39 | }; 40 | }; 41 | }; 42 | 43 | exports.default = _default; -------------------------------------------------------------------------------- /dist/withLifecycle.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 9 | 10 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 11 | 12 | /** 13 | * @author recompose (https://github.com/acdlite/recompose) 14 | */ 15 | var _default = function _default(lifecycles) { 16 | return function (Component) { 17 | // avoid breaking changes by mapping class lifecycles to functional lifecycles 18 | var functionalLifecycles = {}; 19 | 20 | if (lifecycles.componentWillMount) { 21 | functionalLifecycles.onComponentWillMount = lifecycles.componentWillMount; 22 | } 23 | 24 | if (lifecycles.componentDidMount) { 25 | functionalLifecycles.onComponentDidMount = lifecycles.componentDidMount; 26 | } 27 | 28 | if (lifecycles.shouldComponentUpdate) { 29 | functionalLifecycles.onComponentShouldUpdate = lifecycles.shouldComponentUpdate; 30 | } 31 | 32 | if (lifecycles.componentWillUpdate) { 33 | functionalLifecycles.onComponentWillUpdate = lifecycles.componentWillUpdate; 34 | } 35 | 36 | if (lifecycles.componentDidUpdate) { 37 | functionalLifecycles.onComponentDidUpdate = lifecycles.componentDidUpdate; 38 | } 39 | 40 | if (lifecycles.componentWillUnmount) { 41 | functionalLifecycles.onComponentWillUnmount = lifecycles.componentWillUnmount; 42 | } 43 | 44 | Component.defaultHooks = _objectSpread({}, functionalLifecycles); 45 | return Component; 46 | }; 47 | }; 48 | 49 | exports.default = _default; -------------------------------------------------------------------------------- /dist/nest.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = _interopRequireWildcard(require("inferno")); 9 | 10 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } } 11 | 12 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 13 | 14 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 15 | 16 | var _default = function _default() { 17 | for (var _len = arguments.length, Components = new Array(_len), _key = 0; _key < _len; _key++) { 18 | Components[_key] = arguments[_key]; 19 | } 20 | 21 | return function (props) { 22 | if (!Components || Components.length < 1) { 23 | return null; 24 | } 25 | 26 | var MainComponent = Components[0]; 27 | var components = Components.reverse(); 28 | var propsMap = components.map(function (Component, index) { 29 | var PrevComponent = components[index - 1] || null; 30 | var nextProps = props; 31 | 32 | if (PrevComponent !== null) { 33 | nextProps.children = (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, PrevComponent, _objectSpread({}, nextProps))); 34 | } 35 | 36 | return nextProps; 37 | }); 38 | return MainComponent(propsMap.reverse()[0]); 39 | }; 40 | }; 41 | 42 | exports.default = _default; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "incompose", 3 | "version": "5.0.1", 4 | "description": "An inferno utility belt for function components and higher-order components", 5 | "browserslist": "> 0.25%, not dead", 6 | "repository": { 7 | "type": "git", 8 | "url": "git://github.com/zanettin/incompose.git" 9 | }, 10 | "main": "dist/index.js", 11 | "keywords": [ 12 | "inferno", 13 | "recompose", 14 | "functional", 15 | "component", 16 | "higher", 17 | "order", 18 | "component", 19 | "hoc" 20 | ], 21 | "author": { 22 | "name": "Roman Zanettin", 23 | "email": "roman.zanettin@gmail.com", 24 | "url": "http://github.com/zanettin" 25 | }, 26 | "license": "MIT", 27 | "scripts": { 28 | "test": "NODE_ENV=test jest --no-cache", 29 | "build": "NODE_ENV=production babel src --out-dir dist", 30 | "prepublish": "npm run build", 31 | "lint": "eslint src/**", 32 | "cspell": "cspell src/**/*.js tests/**/*.js docs/**/*.md --config ./cSpell.json", 33 | "ci": "npm run test && npm run lint && npm run cspell", 34 | "prettier": "./node_modules/.bin/prettier --write './!(dist|.vscode)/**/*.js'" 35 | }, 36 | "dependencies": { 37 | "change-emitter": "^0.1.6", 38 | "symbol-observable": "^1.2.0" 39 | }, 40 | "devDependencies": { 41 | "@babel/cli": "^7.4.4", 42 | "@babel/core": "^7.4.5", 43 | "@babel/plugin-proposal-class-properties": "^7.4.4", 44 | "@babel/plugin-proposal-object-rest-spread": "^7.4.4", 45 | "@babel/preset-env": "^7.4.5", 46 | "babel-core": "^7.0.0-bridge.0", 47 | "babel-eslint": "^10.0.2", 48 | "babel-jest": "^24.8.0", 49 | "babel-plugin-inferno": "^6.0.5", 50 | "babel-plugin-syntax-jsx": "^6.18.0", 51 | "cspell": "^4.0.23", 52 | "eslint": "^6.0.1", 53 | "eslint-plugin-import": "^2.18.0", 54 | "eslint-plugin-inferno": "^7.11.0", 55 | "inferno": "7.1.13", 56 | "inferno-create-class": "7.1.13", 57 | "jest": "^24.8.0", 58 | "jsdom": "^15.1.1", 59 | "prettier": "^1.18.2" 60 | }, 61 | "contributors": [ 62 | { 63 | "name": "Carsten Lamm", 64 | "email": "CarstenLamm+incompose@gmail.com", 65 | "url": "https://github.com/FQ400" 66 | } 67 | ], 68 | "peerDependencies": { 69 | "inferno": "5.0.0", 70 | "inferno-create-class": "5.0.0" 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /docs/setObservableConfig.md: -------------------------------------------------------------------------------- 1 | # setObservableConfig 2 | ## Description 3 | Observables in Incompose are plain objects that conform to the ES Observable proposal. Usually, you'll want to use them alongside an observable library like RxJS so that you have access to its suite of operators. By default, this requires you to convert the observables provided by Incompose before applying any transforms: 4 | 5 | ``` 6 | mapPropsStream(props$ => { 7 | const rxjsProps$ = Rx.Observable.from(props$) 8 | // ...now you can use map, filter, scan, etc. 9 | return transformedProps$ 10 | }) 11 | ``` 12 | 13 | This quickly becomes tedious. Rather than performing this transform for each stream individually, `setObservableConfig()` sets a global observable transform that is applied automatically. 14 | 15 | ``` 16 | import Rx from 'rxjs' 17 | import { setObservableConfig } from 'incompose' 18 | 19 | setObservableConfig({ 20 | // Converts a plain ES observable to an RxJS 5 observable 21 | fromESObservable: Rx.Observable.from 22 | }) 23 | ``` 24 | 25 | In addition to `fromESObservable`, the config object also accepts `toESObservable`, which converts a stream back into an ES observable. Because RxJS 5 observables already conform to the ES observable spec, `toESObservable` is not necessary in the above example. However, it is required for libraries like RxJS 4 or xstream, whose streams do not conform to the ES observable spec. 26 | 27 | Fortunately, you likely don't need to worry about how to configure Incompose for your favorite stream library, because Incompose provides drop-in configuration for you. 28 | 29 | Note: The following configuration modules are not included in the main export. You must import them individually, as shown in the examples. 30 | 31 | ## API 32 | ``` 33 | setObservableConfig({ 34 | fromESObservable: ?(observable: Observable) => Stream, 35 | toESObservable: ?(stream: Stream) => Observable 36 | }) 37 | ``` 38 | 39 | ## Example 40 | 41 | ### RxJS 42 | ```jsx 43 | import rxjsconfig from 'incompose/dist/rxjsObservableConfig' 44 | setObservableConfig(rxjsconfig) 45 | ``` 46 | 47 | ### RxJS 4 (legacy) 48 | ```jsx 49 | import rxjs4config from 'incompose/dist/rxjs4ObservableConfig' 50 | setObservableConfig(rxjs4config) 51 | ``` 52 | 53 | ### most 54 | ```jsx 55 | import mostConfig from 'incompose/dist/mostObservableConfig' 56 | setObservableConfig(mostConfig) 57 | ``` 58 | 59 | ### xstream 60 | ```jsx 61 | import xstreamConfig from 'incompose/dist/xstreamObservableConfig' 62 | setObservableConfig(xstreamConfig) 63 | ``` 64 | 65 | ### Bacon 66 | ```jsx 67 | import baconConfig from 'incompose/dist/baconObservableConfig' 68 | setObservableConfig(baconConfig) 69 | ``` 70 | 71 | ### Kefir 72 | ```jsx 73 | import kefirConfig from 'incompose/dist/kefirObservableConfig' 74 | setObservableConfig(kefirConfig) 75 | ``` 76 | 77 | ### Flyd 78 | ```jsx 79 | import flydConfig from 'incompose/dist/flydObservableConfig' 80 | setObservableConfig(flydConfig) 81 | ``` -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/). 6 | 7 | ## [5.0.1] - 2019-07-06 8 | ### Update 9 | - `shouldUpdate` and `withLifecycle` use inferno hooks under the hood 10 | ### Fixed 11 | - fixed issue #26 composition issues - thx to ioi0! 12 | 13 | ## [5.0.0] - 2019-06-27 14 | ### Update 15 | - upgraded all npm packages 16 | - inferno v7 support 17 | 18 | ### Fixed 19 | - withState is composable again - thx to ioi0! 20 | 21 | ## [4.0.0] - 2018-11-18 22 | ### Update 23 | - upgraded all npm packages 24 | - babel v7 support 25 | - inferno v6 support 26 | 27 | ## [3.0.2] - 2018-10-19 28 | ### Fixed 29 | - added named import for `mapProps` 30 | 31 | ## [3.0.1] - 2018-10-19 32 | ### Added 33 | - `mapProps` - thx to ZoltanDalmadi 34 | 35 | ## [3.0.0] - 2018-03-18 36 | ### Update 37 | - incompose is now ready for inferno `^5.0` - thx to IgnusG! 38 | 39 | ## [2.0.0] - 2018-02-11 40 | ### Update 41 | - incompose is now ready for inferno `^4.0` 42 | - updated all dependencies 43 | - removed `inferno-compat` as dependency 44 | - added `inferno-create-class` as dependency 45 | - use node `9.5.0` internally 46 | 47 | ## [1.1.0] - 2017-08-07 48 | ### Added 49 | - componentFromStream 50 | - createEventHandler 51 | - setObservableConfig 52 | - observable configs for bacon, flyd, kefir, most, rxjs4, rxjs, xstream 53 | 54 | ### Update 55 | - updated npm dependencies 56 | 57 | ## [1.0.0] - 2017-07-29 58 | ### Update 59 | - updated npm dependencies 60 | - updated docs 61 | - moved to first stable version 62 | 63 | ## [0.0.15] - 2017-05-2 64 | ### Update 65 | - updated npm dependencies and fixes - thx to @FQ400! 66 | - updated docs 67 | 68 | ## [0.0.14] - 2017-04-12 69 | ### Fixed 70 | - fixed `isClassComponent` - thx to @FQ400! 71 | - spelling fixes - thx to @FQ400! 72 | 73 | ## [0.0.13] - 2017-04-11 74 | ### Update 75 | - updated npm dependencies and fixes - thx to @FQ400! 76 | 77 | ## [0.0.12] - 2017-04-06 78 | ### Update 79 | - updated npm dependencies 80 | 81 | ## [0.0.11] - 2017-02-23 82 | ### Fixed 83 | - issue #2 (inferno-devtools crashes because of withLifecycle) 84 | 85 | ### Breaking changes 86 | - lifecycle hooks have to be named like class lifecycle hooks and no longer like the functional component lifecycle hooks. 87 | from: `onComponentDidMount` to: `componentDidMount`. 88 | 89 | ## [0.0.10] - 2017-02-17 90 | ### Fixed 91 | - update dependencies 92 | 93 | ## [0.0.9] - 2017-02-15 94 | ### Fixed 95 | - update dependencies 96 | 97 | ## [0.0.8] - 2017-02-15 98 | ### Added 99 | - pure 100 | - branch 101 | - renderComponent 102 | 103 | ## [0.0.7] - 2017-02-12 104 | ### Added 105 | - nest 106 | - withReducer 107 | 108 | ## [0.0.6] - 2017-02-10 109 | ### Added 110 | - Documentation 111 | - createSink 112 | 113 | ### Fixed 114 | - isClassComponent check 115 | 116 | ## [0.0.5] - 2017-02-07 117 | ### Added 118 | - Changelog.md 119 | - renderNothing 120 | - withHandlers 121 | 122 | ### Fixed 123 | - added named imports for renameProp, renameProps, flattenProps 124 | 125 | ## [0.0.4] - 2017-02-06 126 | ### Added 127 | - renameProp 128 | - renameProps 129 | - flattenProps 130 | 131 | ## [0.0.3] - 2017-02-04 132 | ### Added 133 | - compose 134 | - defaultProps 135 | - withLifecycle 136 | - withProps 137 | - withState -------------------------------------------------------------------------------- /src/shallowEqual.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright (c) 2013-present, Facebook, Inc. 3 | * All rights reserved. 4 | * 5 | * This source code is licensed under the BSD-style license found next. 6 | * 7 | * BSD License 8 | * 9 | * For fbjs software 10 | * 11 | * Copyright (c) 2013-present, Facebook, Inc. 12 | * All rights reserved. 13 | * 14 | * Redistribution and use in source and binary forms, with or without modification, 15 | * are permitted provided that the following conditions are met: 16 | * 17 | * * Redistributions of source code must retain the above copyright notice, this 18 | * list of conditions and the following disclaimer. 19 | * 20 | * * Redistributions in binary form must reproduce the above copyright notice, 21 | * this list of conditions and the following disclaimer in the documentation 22 | * and/or other materials provided with the distribution. 23 | * 24 | * * Neither the name Facebook nor the names of its contributors may be used to 25 | * endorse or promote products derived from this software without specific 26 | * prior written permission. 27 | * 28 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 29 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 30 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 31 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 32 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 33 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 35 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 36 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 37 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 38 | */ 39 | 40 | const hasOwnProperty = Object.prototype.hasOwnProperty; 41 | 42 | /** 43 | * inlined Object.is polyfill to avoid requiring consumers ship their own 44 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 45 | */ 46 | function is(x, y) { 47 | // SameValue algorithm 48 | if (x === y) { 49 | // Steps 1-5, 7-10 50 | // Steps 6.b-6.e: +0 != -0 51 | // Added the nonzero y check to make Flow happy, but it is redundant 52 | return x !== 0 || y !== 0 || 1 / x === 1 / y; 53 | } else { 54 | // Step 6.a: NaN == NaN 55 | return x !== x && y !== y; 56 | } 57 | } 58 | 59 | /** 60 | * Performs equality by iterating through keys on an object and returning false 61 | * when any key has values which are not strictly equal between the arguments. 62 | * Returns true when the values of all keys are strictly equal. 63 | */ 64 | function shallowEqual(objA, objB) { 65 | if (is(objA, objB)) { 66 | return true; 67 | } 68 | 69 | if ( 70 | typeof objA !== 'object' || 71 | objA === null || 72 | typeof objB !== 'object' || 73 | objB === null 74 | ) { 75 | return false; 76 | } 77 | 78 | const keysA = Object.keys(objA); 79 | const keysB = Object.keys(objB); 80 | 81 | if (keysA.length !== keysB.length) { 82 | return false; 83 | } 84 | 85 | // Test for A's keys different from B. 86 | for (let i = 0; i < keysA.length; i++) { 87 | if ( 88 | !hasOwnProperty.call(objB, keysA[i]) || 89 | !is(objA[keysA[i]], objB[keysA[i]]) 90 | ) { 91 | return false; 92 | } 93 | } 94 | 95 | return true; 96 | } 97 | 98 | export default shallowEqual; 99 | -------------------------------------------------------------------------------- /dist/shallowEqual.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 9 | 10 | /** 11 | * Copyright (c) 2013-present, Facebook, Inc. 12 | * All rights reserved. 13 | * 14 | * This source code is licensed under the BSD-style license found next. 15 | * 16 | * BSD License 17 | * 18 | * For fbjs software 19 | * 20 | * Copyright (c) 2013-present, Facebook, Inc. 21 | * All rights reserved. 22 | * 23 | * Redistribution and use in source and binary forms, with or without modification, 24 | * are permitted provided that the following conditions are met: 25 | * 26 | * * Redistributions of source code must retain the above copyright notice, this 27 | * list of conditions and the following disclaimer. 28 | * 29 | * * Redistributions in binary form must reproduce the above copyright notice, 30 | * this list of conditions and the following disclaimer in the documentation 31 | * and/or other materials provided with the distribution. 32 | * 33 | * * Neither the name Facebook nor the names of its contributors may be used to 34 | * endorse or promote products derived from this software without specific 35 | * prior written permission. 36 | * 37 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 38 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 39 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 40 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 41 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 42 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 44 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 45 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 46 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 47 | */ 48 | var hasOwnProperty = Object.prototype.hasOwnProperty; 49 | /** 50 | * inlined Object.is polyfill to avoid requiring consumers ship their own 51 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is 52 | */ 53 | 54 | function is(x, y) { 55 | // SameValue algorithm 56 | if (x === y) { 57 | // Steps 1-5, 7-10 58 | // Steps 6.b-6.e: +0 != -0 59 | // Added the nonzero y check to make Flow happy, but it is redundant 60 | return x !== 0 || y !== 0 || 1 / x === 1 / y; 61 | } else { 62 | // Step 6.a: NaN == NaN 63 | return x !== x && y !== y; 64 | } 65 | } 66 | /** 67 | * Performs equality by iterating through keys on an object and returning false 68 | * when any key has values which are not strictly equal between the arguments. 69 | * Returns true when the values of all keys are strictly equal. 70 | */ 71 | 72 | 73 | function shallowEqual(objA, objB) { 74 | if (is(objA, objB)) { 75 | return true; 76 | } 77 | 78 | if (_typeof(objA) !== 'object' || objA === null || _typeof(objB) !== 'object' || objB === null) { 79 | return false; 80 | } 81 | 82 | var keysA = Object.keys(objA); 83 | var keysB = Object.keys(objB); 84 | 85 | if (keysA.length !== keysB.length) { 86 | return false; 87 | } // Test for A's keys different from B. 88 | 89 | 90 | for (var i = 0; i < keysA.length; i++) { 91 | if (!hasOwnProperty.call(objB, keysA[i]) || !is(objA[keysA[i]], objB[keysA[i]])) { 92 | return false; 93 | } 94 | } 95 | 96 | return true; 97 | } 98 | 99 | var _default = shallowEqual; 100 | exports.default = _default; -------------------------------------------------------------------------------- /dist/withPropsOnChange.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | var _pick = _interopRequireDefault(require("./utils/pick")); 11 | 12 | var _shallowEqual = _interopRequireDefault(require("./shallowEqual")); 13 | 14 | var _createHelper = _interopRequireDefault(require("./createHelper")); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 19 | 20 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 21 | 22 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 23 | 24 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 25 | 26 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 27 | 28 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 29 | 30 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 31 | 32 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 33 | 34 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 35 | 36 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 37 | 38 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 39 | 40 | var withPropsOnChange = function withPropsOnChange(shouldMapOrKeys, propsMapper) { 41 | return function (BaseComponent) { 42 | var _temp; 43 | 44 | var shouldMap = typeof shouldMapOrKeys === 'function' ? shouldMapOrKeys : function (props, nextProps) { 45 | return !(0, _shallowEqual.default)((0, _pick.default)(props, shouldMapOrKeys), (0, _pick.default)(nextProps, shouldMapOrKeys)); 46 | }; 47 | return _temp = 48 | /*#__PURE__*/ 49 | function (_Component) { 50 | _inherits(_temp, _Component); 51 | 52 | function _temp() { 53 | var _getPrototypeOf2; 54 | 55 | var _this; 56 | 57 | _classCallCheck(this, _temp); 58 | 59 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 60 | args[_key] = arguments[_key]; 61 | } 62 | 63 | _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(_temp)).call.apply(_getPrototypeOf2, [this].concat(args))); 64 | 65 | _defineProperty(_assertThisInitialized(_this), "computedProps", propsMapper(_this.props)); 66 | 67 | return _this; 68 | } 69 | 70 | _createClass(_temp, [{ 71 | key: "componentWillReceiveProps", 72 | value: function componentWillReceiveProps(nextProps) { 73 | if (shouldMap(this.props, nextProps)) { 74 | this.computedProps = propsMapper(nextProps); 75 | } 76 | } 77 | }, { 78 | key: "render", 79 | value: function render() { 80 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, BaseComponent, _objectSpread({}, Object.assign(this.props, this.computedProps)))); 81 | } 82 | }]); 83 | 84 | return _temp; 85 | }(_inferno.Component), _temp; 86 | }; 87 | }; 88 | 89 | var _default = (0, _createHelper.default)(withPropsOnChange, 'withPropsOnChange'); 90 | 91 | exports.default = _default; -------------------------------------------------------------------------------- /dist/withState.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | var _createHelper = _interopRequireDefault(require("./createHelper")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 15 | 16 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 17 | 18 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 19 | 20 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 21 | 22 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 23 | 24 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 25 | 26 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 27 | 28 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 29 | 30 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 31 | 32 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 33 | 34 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 35 | 36 | var withState = function withState(stateName, stateUpdaterName, initialState) { 37 | return function (BaseComponent) { 38 | var _temp; 39 | 40 | var StatedComponent = (_temp = 41 | /*#__PURE__*/ 42 | function (_Component) { 43 | _inherits(StatedComponent, _Component); 44 | 45 | function StatedComponent() { 46 | var _getPrototypeOf2; 47 | 48 | var _this; 49 | 50 | _classCallCheck(this, StatedComponent); 51 | 52 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 53 | args[_key] = arguments[_key]; 54 | } 55 | 56 | _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(StatedComponent)).call.apply(_getPrototypeOf2, [this].concat(args))); 57 | 58 | _defineProperty(_assertThisInitialized(_this), "state", { 59 | stateValue: typeof initialState === 'function' ? initialState(_this.props) : initialState 60 | }); 61 | 62 | _defineProperty(_assertThisInitialized(_this), "updateStateValue", function (updateFn, callback) { 63 | return _this.setState(function (_ref) { 64 | var stateValue = _ref.stateValue; 65 | return { 66 | stateValue: typeof updateFn === 'function' ? updateFn(stateValue) : updateFn 67 | }; 68 | }, callback); 69 | }); 70 | 71 | return _this; 72 | } 73 | 74 | _createClass(StatedComponent, [{ 75 | key: "render", 76 | value: function render() { 77 | var _Object$assign; 78 | 79 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, BaseComponent, _objectSpread({}, Object.assign(this.props, (_Object$assign = {}, _defineProperty(_Object$assign, stateName, this.state.stateValue), _defineProperty(_Object$assign, stateUpdaterName, this.updateStateValue), _Object$assign))))); 80 | } 81 | }]); 82 | 83 | return StatedComponent; 84 | }(_inferno.Component), _temp); 85 | return function (props) { 86 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, StatedComponent, _objectSpread({}, props))); 87 | }; 88 | }; 89 | }; 90 | 91 | var _default = (0, _createHelper.default)(withState, 'withState'); 92 | 93 | exports.default = _default; -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | Object.defineProperty(exports, "branch", { 7 | enumerable: true, 8 | get: function get() { 9 | return _branch.default; 10 | } 11 | }); 12 | Object.defineProperty(exports, "componentFromStream", { 13 | enumerable: true, 14 | get: function get() { 15 | return _componentFromStream.default; 16 | } 17 | }); 18 | Object.defineProperty(exports, "compose", { 19 | enumerable: true, 20 | get: function get() { 21 | return _compose.default; 22 | } 23 | }); 24 | Object.defineProperty(exports, "createEventHandler", { 25 | enumerable: true, 26 | get: function get() { 27 | return _createEventHandler.default; 28 | } 29 | }); 30 | Object.defineProperty(exports, "createSink", { 31 | enumerable: true, 32 | get: function get() { 33 | return _createSink.default; 34 | } 35 | }); 36 | Object.defineProperty(exports, "defaultProps", { 37 | enumerable: true, 38 | get: function get() { 39 | return _defaultProps.default; 40 | } 41 | }); 42 | Object.defineProperty(exports, "flattenProps", { 43 | enumerable: true, 44 | get: function get() { 45 | return _flattenProps.default; 46 | } 47 | }); 48 | Object.defineProperty(exports, "mapProps", { 49 | enumerable: true, 50 | get: function get() { 51 | return _mapProps.default; 52 | } 53 | }); 54 | Object.defineProperty(exports, "nest", { 55 | enumerable: true, 56 | get: function get() { 57 | return _nest.default; 58 | } 59 | }); 60 | Object.defineProperty(exports, "pure", { 61 | enumerable: true, 62 | get: function get() { 63 | return _pure.default; 64 | } 65 | }); 66 | Object.defineProperty(exports, "renderComponent", { 67 | enumerable: true, 68 | get: function get() { 69 | return _renderComponent.default; 70 | } 71 | }); 72 | Object.defineProperty(exports, "renderNothing", { 73 | enumerable: true, 74 | get: function get() { 75 | return _renderNothing.default; 76 | } 77 | }); 78 | Object.defineProperty(exports, "renameProp", { 79 | enumerable: true, 80 | get: function get() { 81 | return _renameProp.default; 82 | } 83 | }); 84 | Object.defineProperty(exports, "renameProps", { 85 | enumerable: true, 86 | get: function get() { 87 | return _renameProps.default; 88 | } 89 | }); 90 | Object.defineProperty(exports, "setObservableConfig", { 91 | enumerable: true, 92 | get: function get() { 93 | return _setObservableConfig.default; 94 | } 95 | }); 96 | Object.defineProperty(exports, "shouldUpdate", { 97 | enumerable: true, 98 | get: function get() { 99 | return _shouldUpdate.default; 100 | } 101 | }); 102 | Object.defineProperty(exports, "withLifecycle", { 103 | enumerable: true, 104 | get: function get() { 105 | return _withLifecycle.default; 106 | } 107 | }); 108 | Object.defineProperty(exports, "withHandlers", { 109 | enumerable: true, 110 | get: function get() { 111 | return _withHandlers.default; 112 | } 113 | }); 114 | Object.defineProperty(exports, "withProps", { 115 | enumerable: true, 116 | get: function get() { 117 | return _withProps.default; 118 | } 119 | }); 120 | Object.defineProperty(exports, "withPropsOnChange", { 121 | enumerable: true, 122 | get: function get() { 123 | return _withPropsOnChange.default; 124 | } 125 | }); 126 | Object.defineProperty(exports, "withReducer", { 127 | enumerable: true, 128 | get: function get() { 129 | return _withReducer.default; 130 | } 131 | }); 132 | Object.defineProperty(exports, "withState", { 133 | enumerable: true, 134 | get: function get() { 135 | return _withState.default; 136 | } 137 | }); 138 | 139 | var _branch = _interopRequireDefault(require("./branch")); 140 | 141 | var _componentFromStream = _interopRequireDefault(require("./componentFromStream")); 142 | 143 | var _compose = _interopRequireDefault(require("./compose")); 144 | 145 | var _createEventHandler = _interopRequireDefault(require("./createEventHandler")); 146 | 147 | var _createSink = _interopRequireDefault(require("./createSink")); 148 | 149 | var _defaultProps = _interopRequireDefault(require("./defaultProps")); 150 | 151 | var _flattenProps = _interopRequireDefault(require("./flattenProps")); 152 | 153 | var _mapProps = _interopRequireDefault(require("./mapProps")); 154 | 155 | var _nest = _interopRequireDefault(require("./nest")); 156 | 157 | var _pure = _interopRequireDefault(require("./pure")); 158 | 159 | var _renderComponent = _interopRequireDefault(require("./renderComponent")); 160 | 161 | var _renderNothing = _interopRequireDefault(require("./renderNothing")); 162 | 163 | var _renameProp = _interopRequireDefault(require("./renameProp")); 164 | 165 | var _renameProps = _interopRequireDefault(require("./renameProps")); 166 | 167 | var _setObservableConfig = _interopRequireDefault(require("./setObservableConfig")); 168 | 169 | var _shouldUpdate = _interopRequireDefault(require("./shouldUpdate")); 170 | 171 | var _withLifecycle = _interopRequireDefault(require("./withLifecycle")); 172 | 173 | var _withHandlers = _interopRequireDefault(require("./withHandlers")); 174 | 175 | var _withProps = _interopRequireDefault(require("./withProps")); 176 | 177 | var _withPropsOnChange = _interopRequireDefault(require("./withPropsOnChange")); 178 | 179 | var _withReducer = _interopRequireDefault(require("./withReducer")); 180 | 181 | var _withState = _interopRequireDefault(require("./withState")); 182 | 183 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } -------------------------------------------------------------------------------- /dist/withReducer.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | var _createHelper = _interopRequireDefault(require("./createHelper")); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 15 | 16 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; } 17 | 18 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 19 | 20 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 21 | 22 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 23 | 24 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 25 | 26 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 27 | 28 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 29 | 30 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 31 | 32 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 33 | 34 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 35 | 36 | var withReducer = function withReducer(stateName, dispatchName, reducer, initialState) { 37 | return function (BaseComponent) { 38 | var _temp; 39 | 40 | return _temp = 41 | /*#__PURE__*/ 42 | function (_Component) { 43 | _inherits(_temp, _Component); 44 | 45 | function _temp() { 46 | var _getPrototypeOf2; 47 | 48 | var _this; 49 | 50 | _classCallCheck(this, _temp); 51 | 52 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 53 | args[_key] = arguments[_key]; 54 | } 55 | 56 | _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(_temp)).call.apply(_getPrototypeOf2, [this].concat(args))); 57 | 58 | _defineProperty(_assertThisInitialized(_this), "state", { 59 | stateValue: _this.initializeStateValue() 60 | }); 61 | 62 | _defineProperty(_assertThisInitialized(_this), "dispatch", function (action) { 63 | return _this.setState(function (_ref) { 64 | var stateValue = _ref.stateValue; 65 | return { 66 | stateValue: reducer(stateValue, action) 67 | }; 68 | }); 69 | }); 70 | 71 | return _this; 72 | } 73 | 74 | _createClass(_temp, [{ 75 | key: "initializeStateValue", 76 | value: function initializeStateValue() { 77 | if (initialState !== undefined) { 78 | return typeof initialState === 'function' ? initialState(this.props) : initialState; 79 | } 80 | 81 | return reducer(undefined, { 82 | type: '@@incompose/INIT' 83 | }); 84 | } 85 | }, { 86 | key: "render", 87 | value: function render() { 88 | var _Object$assign; 89 | 90 | return (0, _inferno.normalizeProps)((0, _inferno.createComponentVNode)(2, BaseComponent, _objectSpread({}, Object.assign(this.props, (_Object$assign = {}, _defineProperty(_Object$assign, stateName, this.state.stateValue), _defineProperty(_Object$assign, dispatchName, this.dispatch), _Object$assign))))); 91 | } 92 | }]); 93 | 94 | return _temp; 95 | }(_inferno.Component), _temp; 96 | }; 97 | }; 98 | 99 | var _default = (0, _createHelper.default)(withReducer, 'withReducer'); 100 | 101 | exports.default = _default; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Inferno JS Logo](https://cdn-images-1.medium.com/max/1600/1*NZoKqwcj_x9W1Zh-eWWeCw.png "Inferno JS") 2 | 3 | # Incompose 4 | Incompose is a [Inferno.js](https://infernojs.org/) clone of the famous [recompose](https://github.com/acdlite/recompose) lib for React. 5 | 6 | [![Build Status](https://semaphoreci.com/api/v1/open-source/incompose/branches/master/shields_badge.svg)](https://semaphoreci.com/open-source/incompose) 7 | [![npm version](https://badge.fury.io/js/incompose.svg)](https://www.npmjs.com/package/incompose) 8 | [![npm downloads](https://img.shields.io/npm/dm/incompose.svg?style=flat-square)](https://www.npmjs.com/package/incompose) 9 | [![Code Climate](https://codeclimate.com/github/zanettin/incompose/badges/gpa.svg)](https://codeclimate.com/github/zanettin/incompose) 10 | [![Test Coverage](https://codeclimate.com/github/zanettin/incompose/badges/coverage.svg)](https://codeclimate.com/github/zanettin/incompose/coverage) 11 | [![MIT](https://img.shields.io/npm/l/express.svg)](LICENSE.md) 12 | 13 | ## Installation 14 | ``` 15 | npm install incompose 16 | ``` 17 | 18 | ## Incompose / Inferno version map 19 | Incompose works with specific version of inferno. Please make sure you use the correct version. 20 | 21 | | Inferno verion | Incompose version | 22 | | -- | -- | 23 | | `v7.x` | `>= v.5.0.0` | 24 | | `v6.x` | `>= v.4.0.0` | 25 | | `v5.x` | `>= v.3.0.0` | 26 | | `v4.x` | `v.2.0.0` | 27 | | `< v4.0` | `< v.2` | 28 | 29 | ## Support 30 | Following HoCs are available. If you miss any helper/HoC please send me a note on twitter [@roman_zanettin](https://twitter.com/roman_zanettin) or create an issue / open a PR. Thanks. 31 | 32 | | Function | since | 33 | | --- | :---: | 34 | |[branch](docs/branch.md)|![0.0.8](https://img.shields.io/badge/version-0.0.8-green.svg)| 35 | |[componentFromStream](docs/componentFromStream.md)|![1.1.0](https://img.shields.io/badge/version-1.1.0-green.svg)| 36 | |[compose](docs/compose.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 37 | |[createEventHandler](docs/createEventHandler.md)|![1.1.0](https://img.shields.io/badge/version-1.1.0-green.svg)| 38 | |[createSink](docs/createSink.md)|![0.0.6](https://img.shields.io/badge/version-0.0.6-green.svg)| 39 | |[defaultProps](docs/defaultProps.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 40 | |[flattenProps](docs/flattenProps.md)|![0.0.4](https://img.shields.io/badge/version-0.0.4-green.svg)| 41 | |[mapProps](docs/mapProps.md)|![3.0.1](https://img.shields.io/badge/version-3.0.1-green.svg)| 42 | |[nest](docs/nest.md)|![0.0.7](https://img.shields.io/badge/version-0.0.7-green.svg)| 43 | |[pure](docs/pure.md)|![0.0.8](https://img.shields.io/badge/version-0.0.8-green.svg)| 44 | |[renderComponent](docs/renderComponent.md)|![0.0.8](https://img.shields.io/badge/version-0.0.8-green.svg)| 45 | |[renderNothing](docs/renderNothing.md)|![0.0.5](https://img.shields.io/badge/version-0.0.5-green.svg)| 46 | |[renameProp](docs/renameProp.md)|![0.0.4](https://img.shields.io/badge/version-0.0.4-green.svg)| 47 | |[renameProps](docs/renameProps.md)|![0.0.4](https://img.shields.io/badge/version-0.0.4-green.svg)| 48 | |[setObservableConfig](docs/setObservableConfig.md)|![1.1.0](https://img.shields.io/badge/version-1.1.0-green.svg)| 49 | |[shouldUpdate](docs/shouldUpdate.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 50 | |[withHandlers](docs/withHandlers.md)|![0.0.5](https://img.shields.io/badge/version-0.0.5-green.svg)| 51 | |[withLifecycle](docs/withLifecycle.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 52 | |[withProps](docs/withProps.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 53 | |[withPropsOnChange](docs/withPropsOnChange.md)|![0.0.6](https://img.shields.io/badge/version-0.0.6-green.svg)| 54 | |[withReducer](docs/withReducer.md)|![0.0.7](https://img.shields.io/badge/version-0.0.7-green.svg)| 55 | |[withState](docs/withState.md)|![0.0.3](https://img.shields.io/badge/version-0.0.3-green.svg)| 56 | 57 | 58 | ## Usage 59 | Please find the API and example code in the docs folder. 60 | 61 | ### Import 62 | Incompose provides named and default imports: 63 | ```javascript 64 | import {withState} from 'incompose'; 65 | import withState from 'incompose/dist/withState'; 66 | ``` 67 | 68 | ### Example 69 | ```javascript 70 | import { 71 | linkEvent 72 | } from 'inferno'; 73 | 74 | import { 75 | compose, 76 | withState, 77 | shouldUpdate 78 | } from 'incompose'; 79 | 80 | const inc = (props) => { 81 | props.setCount(props.count += 1); 82 | }; 83 | 84 | const dec = (props) => { 85 | props.setCount(props.count -= 1); 86 | }; 87 | 88 | const Counter = (props) => ( 89 |
90 |

count : {props.count}

91 | 92 | 93 |
94 | ); 95 | 96 | /** 97 | * with state creates 2 new props on the component props 98 | * props.count - contains the value (1 is set as default value) 99 | * props.setCount - contains the setter function 100 | */ 101 | const withCounterState = withState('count', 'setCount', 1); 102 | 103 | /** 104 | * should update prevents the component of re-render (shouldUpdate lifecycle hook) 105 | * you can compare current and next props and decide whether the component 106 | * should update or not. In this example, the counter just updates if 107 | * props.count is even. 108 | */ 109 | const withUpdatePolicy = shouldUpdate((props, nextProps) => ( 110 | nextProps.count % 2 === 0 111 | )); 112 | 113 | /** 114 | * with compose all the extended functions are composed BEFORE Counter 115 | * gets rendered. Please not that order matters. 116 | */ 117 | export default compose( 118 | withCounterState, 119 | withUpdatePolicy, 120 | )(Counter); 121 | ``` 122 | 123 | ## Thanks 124 | Special thanks to all the contributors and Andrew Clark ([@acdlite](https://twitter.com/acdlite)) for creating this amazing lib for React! 125 | 126 | ## Changelog 127 | Changelog is available [here](CHANGELOG.md). 128 | -------------------------------------------------------------------------------- /dist/componentFromStream.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = exports.componentFromStreamWithConfig = void 0; 7 | 8 | var _inferno = require("inferno"); 9 | 10 | var _changeEmitter = require("change-emitter"); 11 | 12 | var _symbolObservable = _interopRequireDefault(require("symbol-observable")); 13 | 14 | var _setObservableConfig = require("./setObservableConfig"); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 19 | 20 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 21 | 22 | function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } 23 | 24 | function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 25 | 26 | function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); } 27 | 28 | function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); } 29 | 30 | function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; } 31 | 32 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); } 33 | 34 | function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); } 35 | 36 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 37 | 38 | var componentFromStreamWithConfig = function componentFromStreamWithConfig(config) { 39 | return function (propsToVdom) { 40 | var _temp; 41 | 42 | return _temp = 43 | /*#__PURE__*/ 44 | function (_Component) { 45 | _inherits(ComponentFromStream, _Component); 46 | 47 | function ComponentFromStream() { 48 | var _getPrototypeOf2; 49 | 50 | var _this; 51 | 52 | _classCallCheck(this, ComponentFromStream); 53 | 54 | for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { 55 | args[_key] = arguments[_key]; 56 | } 57 | 58 | _this = _possibleConstructorReturn(this, (_getPrototypeOf2 = _getPrototypeOf(ComponentFromStream)).call.apply(_getPrototypeOf2, [this].concat(args))); 59 | 60 | _defineProperty(_assertThisInitialized(_this), "state", { 61 | vdom: null 62 | }); 63 | 64 | _defineProperty(_assertThisInitialized(_this), "propsEmitter", (0, _changeEmitter.createChangeEmitter)()); 65 | 66 | _defineProperty(_assertThisInitialized(_this), "props$", config.fromESObservable(_defineProperty({ 67 | subscribe: function subscribe(observer) { 68 | var unsubscribe = _this.propsEmitter.listen(function (props) { 69 | if (props) { 70 | observer.next(props); 71 | } else { 72 | observer.complete(); 73 | } 74 | }); 75 | 76 | return { 77 | unsubscribe: unsubscribe 78 | }; 79 | } 80 | }, _symbolObservable.default, function () { 81 | return this; 82 | }))); 83 | 84 | _defineProperty(_assertThisInitialized(_this), "vdom$", config.toESObservable(propsToVdom(_this.props$))); 85 | 86 | return _this; 87 | } 88 | 89 | _createClass(ComponentFromStream, [{ 90 | key: "componentWillMount", 91 | value: function componentWillMount() { 92 | var _this2 = this; 93 | 94 | // Subscribe to child prop changes so we know when to re-render 95 | this.subscription = this.vdom$.subscribe({ 96 | next: function next(vdom) { 97 | _this2.setState({ 98 | vdom: vdom 99 | }); 100 | } 101 | }); 102 | this.propsEmitter.emit(this.props); 103 | } 104 | }, { 105 | key: "componentWillReceiveProps", 106 | value: function componentWillReceiveProps(nextProps) { 107 | // Receive new props from the owner 108 | this.propsEmitter.emit(nextProps); 109 | } 110 | }, { 111 | key: "shouldComponentUpdate", 112 | value: function shouldComponentUpdate(nextProps, nextState) { 113 | return nextState.vdom !== this.state.vdom; 114 | } 115 | }, { 116 | key: "componentWillUnmount", 117 | value: function componentWillUnmount() { 118 | // Call without arguments to complete stream 119 | this.propsEmitter.emit(); // Clean-up subscription before un-mounting 120 | 121 | this.subscription.unsubscribe(); 122 | } 123 | }, { 124 | key: "render", 125 | value: function render() { 126 | return this.state.vdom; 127 | } 128 | }]); 129 | 130 | return ComponentFromStream; 131 | }(_inferno.Component), _temp; 132 | }; 133 | }; 134 | 135 | exports.componentFromStreamWithConfig = componentFromStreamWithConfig; 136 | 137 | var componentFromStream = function componentFromStream(propsToVdom) { 138 | return componentFromStreamWithConfig(_setObservableConfig.config)(propsToVdom); 139 | }; 140 | 141 | var _default = componentFromStream; 142 | exports.default = _default; --------------------------------------------------------------------------------