cycle-react
Advanced tools
Comparing version 2.0.0 to 3.0.0-beta1
# Changelog | ||
## 3.0.0 | ||
Breaking change: applyToDOM and makeDOMDriver are both removed. Use `ReactDOM.render` instead. | ||
Breaking change: The peer dependency of React has been added back. | ||
Deprecated: Deprecated `bindThis` with the function as view. | ||
Add feature: Support lifecycle events by `interactions.get`. [#18] | ||
``` | ||
// Get the lifecycle event collection for componentDidMount | ||
interactions.get('React_componentDidMount'); | ||
``` | ||
## 2.0.0 | ||
@@ -4,0 +19,0 @@ |
# Cycle-React API | ||
- [`applyToDOM`](#applyToDOM) | ||
- [`component`](#component) | ||
- [`makeDOMDriver`](#makeDOMDriver) | ||
- [`React`](#React) | ||
- [`Rx`](#Rx) | ||
### <a id="applyToDOM"></a> `applyToDOM(container, computer)` | ||
Takes a `computer` function which outputs an Observable of React | ||
elements, and renders that into the DOM element indicated by `container`, | ||
which can be either a CSS selector or an actual element. At the same time, | ||
provides the `interactions` input to the `computer` function, which is a | ||
collection of all events happening on the user-defined event handlers. | ||
You must query this collection with | ||
`interactions.get(eventName)` in order to get an Observable of | ||
interactions of type `eventName`. And create the event handlers with | ||
`interactions.listener(eventName)`. | ||
Example: | ||
``` | ||
interactions.get('MyButtonClick').map(ev => ...); | ||
<button onClick={interactions.listener('MyButtonClick')} /> | ||
``` | ||
#### Arguments: | ||
- `container :: String|HTMLElement` the DOM selector for the element (or the element itself) to contain the rendering of the VTrees. | ||
- `computer :: Function` a function that takes `interactions` as input and outputs an Observable of React elements. | ||
- - - | ||
### <a id="component"></a> `component(displayName, definitionFn, [options])` | ||
@@ -37,11 +11,16 @@ | ||
elements, and returns a native React component which can be used normally | ||
by `React.createElement` and "Cycle.applyToDOM". | ||
by `React.createElement`. | ||
The given `definitionFn` function takes two parameters as input, in this order: | ||
`interactions` and `properties`. The former works just like it does in the | ||
`definitionFn` function given to `applyToDOM`, and the later contains | ||
Observables representing properties of the custom element, given from the | ||
parent context. `properties.get('foo')` will return the Observable `foo$`. | ||
`interactions` and `properties`. `interactions` is a collection of all events | ||
happening on the user-defined event handlers. You must query this collection with | ||
`interactions.get(eventName)` in order to get an Observable of | ||
interactions of type `eventName`. And create the event handlers with | ||
`interactions.listener(eventName)`. | ||
The `definitionFn` must output an object containing the property `vtree$` | ||
The second parameter, `properties`, contains Observables representing properties | ||
of the custom element, given from the parent context. | ||
`properties.get('foo')` will return the Observable `foo$`. | ||
The `definitionFn` must output an object containing the property `view` | ||
as an Observable. If the output object contains other Observables, then | ||
@@ -58,4 +37,3 @@ they are treated as custom events of the custom element. | ||
propTypes: null, | ||
disableHotLoader: false, | ||
bindThis: false | ||
disableHotLoader: false | ||
}); | ||
@@ -98,19 +76,2 @@ | ||
### <a id="makeDOMDriver"></a> `makeDOMDriver(container)` | ||
A factory for the Cycle.js DOM driver function. See docs/cycle-js-driver.md | ||
for details. | ||
#### Arguments: | ||
- `container :: String|HTMLElement` the DOM selector for the element (or the element itself) to contain the rendering of the VTrees. | ||
#### Return: | ||
*(Function)* the DOM driver function. The function expects an Observable of definitionFn as input, and outputs the response object for this | ||
driver, containing functions `get()` and `dispose()` that can be used for | ||
debugging and testing. | ||
- - - | ||
### <a id="React"></a> `React` | ||
@@ -117,0 +78,0 @@ |
@@ -10,3 +10,3 @@ # Interactions API | ||
```js | ||
Cycle.applyToDOM('.js-container', function computer(interactions) { | ||
Cycle.component('MyElement', function computer(interactions) { | ||
// get(eventName: string): Observable<any> | ||
@@ -13,0 +13,0 @@ return interactions.get('OnMyInput') |
@@ -6,3 +6,2 @@ ### Documentations | ||
- [Working with React](/docs/working-with-react.md) | ||
- [Using Cycle.js driver](/docs/cycle-js-driver.md) | ||
@@ -9,0 +8,0 @@ ### Where to ask for help? |
@@ -41,2 +41,38 @@ # Working with React | ||
## Lifecycle events | ||
You can query your component's | ||
[lifecycle events](https://facebook.github.io/react/docs/component-specs.html) | ||
through the `interactions` collection. The key for the lifecycle event is the | ||
event name with the `React_` prefix. | ||
Note: Although Cycle-React provides all lifecycle events available, the only | ||
two reasonable events are `componentDidMount` and `componentDidUpdate`. | ||
You should not manipulate the DOM element directly except from these two events. | ||
Example: | ||
```js | ||
let MyElement = Cycle.component('MyElement', function (interactions, props, self) { | ||
// Get the lifecycle event collection for componentDidMount | ||
let componentDidMountObservable = interactions.get('React_componentDidMount'); | ||
return componentDidMountObservable.map(() => { | ||
// Find the DOM node from "self" | ||
let node = ReactDOM.findDOMNode(self); | ||
// ... | ||
return <div>The element</div>; | ||
}); | ||
}); | ||
``` | ||
Keys for lifecycle events: | ||
- React_componentWillMount | ||
- React_componentDidMount | ||
- React_componentWillReceiveProps | ||
- React_componentWillUpdate | ||
- React_componentDidUpdate | ||
- React_componentWillUnmount | ||
## Mixins | ||
@@ -64,4 +100,5 @@ | ||
`opts.bindThis` will pass the third parameter `self` to `definitionFn`. | ||
`self` represents `this` of your created React class. | ||
The third parameter of `definitionFn` is `self`, which represents `this` of | ||
your created React class. | ||
Normally, you don't want to use this. However, it might be required for | ||
@@ -75,40 +112,9 @@ working with some React components. | ||
let options = { | ||
mixins: [Navigation], | ||
bindThis: true | ||
mixins: [Navigation] | ||
}; | ||
let MyElement = Cycle.component('MyElement', function (_1, _2, self) { | ||
return Rx.Observable.just(<div onClick={() => self.goBack()}>Go back</div>) | ||
return Rx.Observable.just(<div onClick={() => self.goBack()}>Go back</div>); | ||
}, options); | ||
``` | ||
## Refs | ||
If you've ever tried to set `ref` to the element with Cycle-React, you've | ||
probably encountered this following error: | ||
``` | ||
Invariant Violation: addComponentAsRefTo(...): Only a ReactOwner can have refs. | ||
This usually means that you're trying to add a ref to a component that doesn't | ||
have an owner (that is, was not created inside of another component's `render` | ||
method). | ||
``` | ||
This is because Cycle-React evaluates the vtree(ReactElement) inside the Rx | ||
subscription instead of `Component.prototype.render`. In order to fix this, | ||
you can return the lazy value of ReactElement with the option | ||
`{bindThis: true}` set. | ||
Example: | ||
```js | ||
let options = { | ||
// The bindThis option must be set | ||
bindThis: true | ||
}; | ||
let MyElement = Cycle.component('MyElement', (_1, _2, self) => { | ||
// Return lambda instead of plain vtree | ||
return Rx.Observable.just(() => <input ref="myInput" />); | ||
}, options); | ||
``` | ||
## react-hot-loader | ||
@@ -115,0 +121,0 @@ |
33
index.js
'use strict'; | ||
var applyToDOM = require('./src/render-dom'); | ||
var createReactClass = require('./src/create-react-class'); | ||
var makeDOMDriver = require('./src/cycle-driver'); | ||
var createAdapter = require('./src/rx/adapter'); | ||
var React = require('react'); | ||
@@ -16,3 +15,2 @@ var Rx = require('rx'); | ||
* @param {Object} [self] - "this" object for the React component. | ||
* "bindThis" option must be set for enabling this parameter. | ||
* @returns {} | ||
@@ -29,13 +27,2 @@ */ | ||
*/ | ||
/** | ||
* Takes a `computer` function which outputs an Observable of React | ||
* elements, and renders that into the DOM element indicated by `container`. | ||
* | ||
* @function applyToDOM | ||
* @param {(String|HTMLElement)} container the DOM selector for the element | ||
* (or the element itself) to contain the rendering of the VTrees. | ||
* @param {DefinitionFn} computer a function that takes `interactions` as input | ||
* and outputs an Observable of React elements. | ||
*/ | ||
applyToDOM: applyToDOM, | ||
@@ -45,3 +32,3 @@ /** | ||
* elements, and returns a native React component which can be used normally | ||
* by `React.createElement` and "Cycle.applyToDOM". | ||
* by `React.createElement`. | ||
* | ||
@@ -56,19 +43,5 @@ * @function component | ||
*/ | ||
component: createReactClass(React), | ||
component: createReactClass(React, createAdapter()), | ||
/** | ||
* A factory for the Cycle.js DOM driver function. See docs/cycle-js-driver.md | ||
* for details. | ||
* | ||
* @param {(String|HTMLElement)} container the DOM selector for the element | ||
* (or the element itself) to contain the rendering of the VTrees. | ||
* @return {Function} the DOM driver function. The function expects an | ||
* Observable of definitionFn as input, and outputs the response object for this | ||
* driver, containing functions `get()` and `dispose()` that can be used for | ||
* debugging and testing. | ||
* @function makeDOMDriver | ||
*/ | ||
makeDOMDriver: makeDOMDriver, | ||
/** | ||
* A shortcut to the root object of React. | ||
@@ -75,0 +48,0 @@ * @name React |
'use strict'; | ||
//var applyToDOM = require('./src/render-dom'); | ||
var createReactClass = require('./src/create-react-class'); | ||
//var makeDOMDriver = require('./src/cycle-driver'); | ||
var React = require('react-native'); | ||
@@ -16,3 +14,2 @@ var Rx = require('rx'); | ||
* @param {Object} [self] - "this" object for the React component. | ||
* "bindThis" option must be set for enabling this parameter. | ||
* @returns {} | ||
@@ -29,13 +26,2 @@ */ | ||
*/ | ||
/** | ||
* Takes a `computer` function which outputs an Observable of React | ||
* elements, and renders that into the DOM element indicated by `container`. | ||
* | ||
* @function applyToDOM | ||
* @param {(String|HTMLElement)} container the DOM selector for the element | ||
* (or the element itself) to contain the rendering of the VTrees. | ||
* @param {DefinitionFn} computer a function that takes `interactions` as input | ||
* and outputs an Observable of React elements. | ||
*/ | ||
//applyToDOM: applyToDOM, | ||
@@ -45,3 +31,3 @@ /** | ||
* elements, and returns a native React component which can be used normally | ||
* by `React.createElement` and "Cycle.applyToDOM". | ||
* by `React.createElement`. | ||
* | ||
@@ -59,16 +45,2 @@ * @function component | ||
/** | ||
* A factory for the Cycle.js DOM driver function. See docs/cycle-js-driver.md | ||
* for details. | ||
* | ||
* @param {(String|HTMLElement)} container the DOM selector for the element | ||
* (or the element itself) to contain the rendering of the VTrees. | ||
* @return {Function} the DOM driver function. The function expects an | ||
* Observable of definitionFn as input, and outputs the response object for this | ||
* driver, containing functions `get()` and `dispose()` that can be used for | ||
* debugging and testing. | ||
* @function makeDOMDriver | ||
*/ | ||
//makeDOMDriver: makeDOMDriver, | ||
/** | ||
* A shortcut to the root object of React. | ||
@@ -75,0 +47,0 @@ * @name React |
{ | ||
"name": "cycle-react", | ||
"version": "2.0.0", | ||
"version": "3.0.0-beta1", | ||
"author": { | ||
@@ -26,18 +26,21 @@ "name": "pH200", | ||
"dependencies": { | ||
"rx": "2.5.3" | ||
"rx": "4.0.7" | ||
}, | ||
"peerDependencies": { | ||
"react": ">0.14.0" | ||
}, | ||
"devDependencies": { | ||
"babel": "^5.6.4", | ||
"babel-eslint": "^3.1.21", | ||
"babelify": "^6.1.2", | ||
"browserify": "^10.2.4", | ||
"babel": "^5.8.23", | ||
"babel-eslint": "^4.1.3", | ||
"babelify": "^6.4.0", | ||
"browserify": "^11.2.0", | ||
"cheerio": "~0.19.0", | ||
"cuid": "^1.2.5", | ||
"eslint": "^0.24.0", | ||
"express": "^4.13.0", | ||
"immutable": "^3.7.4", | ||
"mocha": "^2.2.5", | ||
"react": "^0.13.3", | ||
"testem": "~0.8.3", | ||
"uglify-js": "^2.4.23" | ||
"cuid": "^1.3.8", | ||
"eslint": "^1.7.3", | ||
"express": "^4.13.3", | ||
"immutable": "^3.7.5", | ||
"mocha": "^2.3.3", | ||
"react": "~0.14.0", | ||
"testem": "~0.9.8", | ||
"uglify-js": "^2.5.0" | ||
}, | ||
@@ -44,0 +47,0 @@ "engines": { |
@@ -10,5 +10,5 @@ # Cycle-React | ||
applications in functional style and represents their UIs as Observables. | ||
In addition, Cycle-React is immutable and uses | ||
[PureRenderMixin](https://facebook.github.io/react/docs/pure-render-mixin.html) | ||
internally by default. | ||
In addition, Cycle-React is immutable and | ||
[optimizes](https://facebook.github.io/react/docs/pure-render-mixin.html) | ||
the component updates internally by default. | ||
@@ -27,6 +27,7 @@ Additionally, Cycle-React is also a React-style implementation of a beautiful | ||
```js | ||
let Cycle = require('cycle-react'); | ||
let React = require('react'); | ||
const Cycle = require('cycle-react'); | ||
const React = require('react'); | ||
const ReactDOM = require('react-dom'); | ||
function computer(interactions) { | ||
const Hello = Cycle.component('Hello', function computer(interactions) { | ||
return interactions.get('OnNameChanged') | ||
@@ -43,11 +44,14 @@ .map(ev => ev.target.value) | ||
); | ||
} | ||
}); | ||
Cycle.applyToDOM('.js-container', computer); | ||
ReactDOM.render( | ||
<Hello />, | ||
document.querySelector('.js-container') | ||
); | ||
``` | ||
The input of the `computer` is `interactions`, a collection containing all | ||
user interaction events happening on the user-defined event handlers on the DOM, | ||
which you can query using `interactions.get(eventName)`. And the event handler | ||
can be defined by `interactions.listener(eventName)`. | ||
The input of the function `computer` is `interactions`, a collection containing | ||
all user interaction events happening on the user-defined event handlers on the | ||
DOM, which you can query using `interactions.get(eventName)`. And the event | ||
handler can be defined by `interactions.listener(eventName)`. | ||
@@ -57,6 +61,7 @@ The output of the `computer` is `Observable<ReactElement>` | ||
Function `applyToDOM` subscribes that Observable of elements and renders the | ||
elements to DOM, by using `React.createClass` and `React.render` internally. | ||
Function `component` subscribes that Observable of elements and create a new | ||
React component class, which can be used normally by `React.createElement` and | ||
`ReactDOM.render`. | ||
Notice that although `React.createClass` is mentioned here, you don't have to | ||
Notice that although `class` is mentioned here, you don't have to | ||
use it. That's why Cycle-React was made. We took functions over classes | ||
@@ -72,8 +77,9 @@ and mutable states. | ||
```js | ||
let Cycle = require('cycle-react'); | ||
let React = require('react'); | ||
let Rx = Cycle.Rx; | ||
const Cycle = require('cycle-react'); | ||
const React = require('react'); | ||
const ReactDOM = require('react-dom'); | ||
const Rx = Cycle.Rx; | ||
// "component" returns a native React component which can be used normally | ||
// by "React.createElement" and "Cycle.applyToDOM". | ||
// by "React.createElement". | ||
let Counter = Cycle.component('Counter', function (interactions, props) { | ||
@@ -91,7 +97,6 @@ return props.get('counter').map(counter => | ||
Cycle.applyToDOM('.js-container', Timer); | ||
// or | ||
// React.render( | ||
// React.createElement(Timer), | ||
// document.querySelector('.js-container')); | ||
ReactDOM.render( | ||
<Timer />, | ||
document.querySelector('.js-container') | ||
); | ||
``` | ||
@@ -121,13 +126,2 @@ | ||
## Cycle.js Driver | ||
Cycle.js (not Cycle-React) has the | ||
[driver architecture](http://cycle.js.org/drivers.html) to externalize the | ||
side-effects. Cycle Web, for example, is a driver externalizes DOM environment. | ||
And Cycle-React provides a DOM driver (powered by React, of course) | ||
for Cycle.js, too. | ||
Details can be found at | ||
["Using Cycle-React's DOM driver for Cycle.js"](/docs/cycle-js-driver.md). | ||
## FAQ | ||
@@ -134,0 +128,0 @@ |
@@ -1,38 +0,42 @@ | ||
'use strict'; | ||
var Rx = require('rx'); | ||
var digestDefinitionFnOutput = require('./util').digestDefinitionFnOutput; | ||
var makeInteractions = require('./interactions').makeInteractions; | ||
var makePropsObservable = require('./props').makePropsObservable; | ||
var makeInteractions = require('./interactions'); | ||
function makeDispatchFunction(eventName, self) { | ||
return function dispatchCustomEvent(evData) { | ||
if (self.props) { | ||
var eventHandler = self.props[eventName]; | ||
if (eventHandler) { | ||
eventHandler(evData); | ||
function createReactClass(React, Adapter) { | ||
var makePropsObservable = Adapter.makePropsObservable; | ||
var createEventSubject = Adapter.createEventSubject; | ||
var CompositeDisposable = Adapter.CompositeDisposable; | ||
var createDisposable = Adapter.createDisposable; | ||
var doOnNext = Adapter.doOnNext; | ||
var subscribe = Adapter.subscribe; | ||
var subscribeAll = Adapter.subscribeAll; | ||
function makeDispatchFunction(eventName, self) { | ||
return function dispatchCustomEvent(evData) { | ||
if (self.props) { | ||
var eventHandler = self.props[eventName]; | ||
if (eventHandler) { | ||
eventHandler(evData); | ||
} | ||
} | ||
}; | ||
} | ||
function composingEventObservables(events, self) { | ||
var eventNames = Object.keys(events); | ||
var eventObservables = []; | ||
for (var i = 0; i < eventNames.length; i++) { | ||
var eventName = eventNames[i]; | ||
var eventObs = events[eventName]; | ||
eventObservables.push( | ||
doOnNext(eventObs, makeDispatchFunction(eventName, self)) | ||
); | ||
} | ||
}; | ||
} | ||
function composingEventObservables(events, self) { | ||
var eventNames = Object.keys(events); | ||
var eventObservables = []; | ||
for (var i = 0; i < eventNames.length; i++) { | ||
var eventName = eventNames[i]; | ||
var eventObs = events[eventName]; | ||
eventObservables.push( | ||
eventObs.doOnNext(makeDispatchFunction(eventName, self)) | ||
); | ||
return eventObservables; | ||
} | ||
return eventObservables; | ||
} | ||
function createReactClass(React) { | ||
return function component( | ||
displayName, | ||
definitionFn, | ||
componentOptions, | ||
observer, | ||
eventObserver) { | ||
componentOptions | ||
) { | ||
if (typeof displayName !== 'string') { | ||
@@ -47,4 +51,2 @@ throw new Error('Invalid displayName'); | ||
var rootTagName = options.rootTagName || 'div'; | ||
// The option for passing "this" to definitionFn | ||
var bindThis = !!options.bindThis; | ||
@@ -59,10 +61,9 @@ var reactClassProto = { | ||
var self = this; | ||
this.disposable = new Rx.CompositeDisposable(); | ||
this.disposable = new CompositeDisposable(); | ||
var propsSubject$ = makePropsObservable(this.props); | ||
this.propsSubject$ = propsSubject$; | ||
var interactions = makeInteractions(); | ||
var interactions = makeInteractions(createEventSubject); | ||
this.interactions = interactions; | ||
var cycleComponent = digestDefinitionFnOutput( | ||
bindThis ? | ||
definitionFn(interactions, this.propsSubject$, this) : | ||
definitionFn(interactions, this.propsSubject$) | ||
definitionFn(interactions, this.propsSubject$, this) | ||
); | ||
@@ -73,7 +74,6 @@ this.cycleComponent = cycleComponent; | ||
var vtree$ = cycleComponent.vtree$; | ||
var vtreeDoSet$ = vtree$.doOnNext(function onNextVTree(vtree) { | ||
var subscription = subscribe(vtree$, function onNextVTree(vtree) { | ||
self.setState({vtree: vtree}); | ||
}); | ||
var subscription = observer ? | ||
vtreeDoSet$.subscribe(observer) : vtreeDoSet$.subscribe(); | ||
this.disposable.add(this.propsSubject$); | ||
@@ -89,3 +89,3 @@ this.disposable.add(subscription); | ||
if (typeof dispose === 'function') { | ||
this.disposable.add(Rx.Disposable.create(dispose)); | ||
this.disposable.add(createDisposable(dispose)); | ||
} else if (typeof dispose.dispose === 'function') { | ||
@@ -106,10 +106,3 @@ this.disposable.add(dispose); | ||
if (eventObservables.length > 0) { | ||
var eventSubscription; | ||
if (eventObserver) { | ||
eventSubscription = | ||
Rx.Observable.merge(eventObservables).subscribe(eventObserver); | ||
} else { | ||
eventSubscription = | ||
Rx.Observable.merge(eventObservables).subscribe(); | ||
} | ||
var eventSubscription = subscribeAll(eventObservables); | ||
this.disposable.add(eventSubscription); | ||
@@ -126,7 +119,4 @@ } | ||
this._subscribeCycleComponent(); | ||
this.interactions.listener('React_componentWillMount')(); | ||
}, | ||
componentWillUnmount: function componentWillUnmount() { | ||
// componentWillUnmount is not being called for server | ||
this._unsubscribeCycleComponent(); | ||
}, | ||
componentDidMount: function componentDidMount() { | ||
@@ -138,14 +128,32 @@ this._subscribeCycleEvents(); | ||
this.hasMounted = true; | ||
this.interactions.listener('React_componentDidMount')(); | ||
}, | ||
componentWillReceiveProps: function componentWillReceiveProps(nextProps) { | ||
this.propsSubject$.onNext(nextProps); | ||
this.interactions.listener('React_componentWillReceiveProps')(nextProps); | ||
}, | ||
componentWillUpdate: function componentWillUpdate(nextProps) { | ||
this.interactions.listener('React_componentWillUpdate')(nextProps); | ||
}, | ||
componentDidUpdate: function componentDidUpdate(nextProps) { | ||
this.interactions.listener('React_componentDidUpdate')(nextProps); | ||
}, | ||
componentWillUnmount: function componentWillUnmount() { | ||
// componentWillUnmount is not being called for server | ||
this._unsubscribeCycleComponent(); | ||
this.interactions.listener('React_componentWillUnmount')(); | ||
}, | ||
render: function render() { | ||
if (this.state && this.state.vtree) { | ||
if (bindThis && typeof this.state.vtree === 'function') { | ||
// `this` is bound automatically by React.createClass so the element | ||
// will have the owner set by this component | ||
return this.state.vtree(); | ||
// TODO: Remove this block in the future releases | ||
if (typeof this.state.vtree === 'function' && | ||
typeof console !== 'undefined') | ||
{ | ||
console.warn( | ||
'Support for using the function as view is ' + | ||
'deprecated and will be soon removed.' | ||
); | ||
return React.cloneElement(this.state.vtree()); | ||
} | ||
return this.state.vtree; | ||
return React.cloneElement(this.state.vtree); | ||
} | ||
@@ -152,0 +160,0 @@ return React.createElement(rootTagName); |
/* globals process */ | ||
'use strict'; | ||
var createEventSubject = require('./event-subject'); | ||
function makeInteractions(createEventSubject) { | ||
/* eslint-disable camelcase */ | ||
var subjects = { | ||
React_componentWillMount: createEventSubject(), | ||
React_componentDidMount: createEventSubject(), | ||
React_componentWillReceiveProps: createEventSubject(), | ||
React_componentWillUpdate: createEventSubject(), | ||
React_componentDidUpdate: createEventSubject(), | ||
React_componentWillUnmount: createEventSubject() | ||
}; | ||
function makeInteractions() { | ||
var subjects = {}; | ||
function get(name) { | ||
@@ -51,4 +56,2 @@ if (name === null || name === (void 0)) { | ||
module.exports = { | ||
makeInteractions: makeInteractions | ||
}; | ||
module.exports = makeInteractions; |
@@ -5,3 +5,5 @@ 'use strict'; | ||
let Cycle = require('../../'); | ||
let applyToDOM = require('./lib/apply-to-dom'); | ||
let {Rx, React} = Cycle; | ||
let ReactDOM = require('react-dom'); | ||
@@ -32,3 +34,3 @@ function createRenderTarget() { | ||
let vtree$ = Rx.Observable.just(<MyElement />); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -62,3 +64,3 @@ let myElement = document.querySelector('.myelementclass'); | ||
} | ||
Cycle.applyToDOM(createRenderTarget(), definitionFn); | ||
applyToDOM(createRenderTarget(), definitionFn); | ||
number$.request(8); | ||
@@ -91,3 +93,3 @@ // Make assertions | ||
); | ||
let domUI = Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
let domUI = applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -118,3 +120,3 @@ let myElement = document.querySelector('.inner-element'); | ||
); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -146,3 +148,3 @@ let myElement1 = document.querySelector('.myelement1class'); | ||
let vtree$ = Rx.Observable.just(<Outer />); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -177,3 +179,3 @@ let innerElement = document.querySelector('.innerClass'); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), Root); | ||
applyToDOM(createRenderTarget(), Root); | ||
// Make assertions | ||
@@ -233,3 +235,3 @@ let myElement = document.querySelector('.myelementclass'); | ||
Cycle.applyToDOM(createRenderTarget(), computer); | ||
applyToDOM(createRenderTarget(), computer); | ||
@@ -260,3 +262,3 @@ // Simulate clicks | ||
); | ||
let domUI = Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
let domUI = applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -302,3 +304,3 @@ let wrapper = document.querySelector('.wrapper'); | ||
Cycle.applyToDOM(createRenderTarget(), computer); | ||
applyToDOM(createRenderTarget(), computer); | ||
@@ -346,3 +348,3 @@ document.querySelector('.button').click(); | ||
Cycle.applyToDOM(createRenderTarget(), computer); | ||
applyToDOM(createRenderTarget(), computer); | ||
@@ -387,3 +389,3 @@ document.querySelector('.button').click(); | ||
customElementSwitch$.request(1); | ||
Cycle.applyToDOM(createRenderTarget(), Root); | ||
applyToDOM(createRenderTarget(), Root); | ||
// Make assertions | ||
@@ -426,3 +428,3 @@ let myElement = document.querySelector('.myelementclass'); | ||
customElementSwitch$.request(1); | ||
Cycle.applyToDOM(createRenderTarget(), Root); | ||
applyToDOM(createRenderTarget(), Root); | ||
// Make assertions | ||
@@ -453,3 +455,3 @@ number$.request(1); | ||
let vtree$ = Rx.Observable.just(<MyElement />); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -467,3 +469,3 @@ vtreeController$.request(1); | ||
it('should accept vtree as function and "ref" if "bindThis" was set', function (done) { | ||
it('should accept vtree as function and "ref"', function (done) { | ||
let vtreeController$ = Rx.Observable.range(0, 2).controlled(); | ||
@@ -473,3 +475,3 @@ // Make simple custom element | ||
vtreeController$.subscribe(() => { | ||
let editField = React.findDOMNode(self.refs.theRef); | ||
let editField = ReactDOM.findDOMNode(self.refs.theRef); | ||
assert.notStrictEqual(editField, null); | ||
@@ -483,4 +485,4 @@ assert.strictEqual(editField.tagName, 'H3'); | ||
); | ||
}, {bindThis: true}); | ||
Cycle.applyToDOM(createRenderTarget(), MyElement); | ||
}); | ||
applyToDOM(createRenderTarget(), MyElement); | ||
// Make assertions | ||
@@ -506,3 +508,3 @@ vtreeController$.request(1); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -549,3 +551,3 @@ customElementSwitch$.request(1); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -590,3 +592,3 @@ customElementSwitch$.request(1); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -626,3 +628,3 @@ customElementSwitch$.request(1); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -659,3 +661,3 @@ customElementSwitch$.request(1); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -674,2 +676,53 @@ customElementSwitch$.request(1); | ||
}); | ||
it('should trigger the React_componentWillMount interaction', function (done) { | ||
// Make simple custom element | ||
let MyElement = Cycle.component('MyElement', function (interactions) { | ||
interactions.get('React_componentWillMount') | ||
.subscribe(done); | ||
return Rx.Observable.just(<h3 className="myelementclass" />); | ||
}); | ||
// Use the custom element | ||
let vtree$ = Rx.Observable.just(<MyElement />); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
}); | ||
it('should trigger the React_componentDidMount interaction', function (done) { | ||
// Make simple custom element | ||
let MyElement = Cycle.component('MyElement', function (interactions, props, self) { | ||
interactions | ||
.get('React_componentDidMount') | ||
.do(() => { | ||
let node = ReactDOM.findDOMNode(self); | ||
assert.ok(node); | ||
assert.strictEqual(node.tagName, 'H3'); | ||
}) | ||
.subscribe(done); | ||
return Rx.Observable.just(<h3 className="myelementclass" />); | ||
}); | ||
// Use the custom element | ||
let vtree$ = Rx.Observable.just(<MyElement />); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
}); | ||
it('should trigger the React_componentDidUpdate interaction', function () { | ||
let log = 0; | ||
let number$ = Rx.Observable.range(1, 2).controlled(); | ||
// Make simple custom element | ||
let MyElement = Cycle.component('MyElement', function (interactions) { | ||
interactions.get('React_componentDidUpdate') | ||
.subscribe(() => log++); | ||
return number$.map(n => <h3 className="myelementclass">{n}</h3>); | ||
}); | ||
// Use the custom element | ||
let vtree$ = Rx.Observable.just(<MyElement />); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
number$.request(1); | ||
assert.strictEqual(log, 1); | ||
// Update the element | ||
number$.request(1); | ||
assert.strictEqual(log, 2); | ||
}); | ||
}); |
@@ -5,2 +5,1 @@ 'use strict'; | ||
require('./render.js'); | ||
require('./driver.js'); |
@@ -5,2 +5,3 @@ 'use strict'; | ||
let Cycle = require('../../'); | ||
let applyToDOM = require('./lib/apply-to-dom'); | ||
let Fixture89 = require('./fixtures/issue-89'); | ||
@@ -16,3 +17,3 @@ let {Rx, React} = Cycle; | ||
describe('Cycle.applyToDOM', function () { | ||
describe('applyToDOM', function () { | ||
beforeEach(function () { | ||
@@ -27,33 +28,5 @@ let testDivs = Array.prototype.slice.call(document.querySelectorAll('.cycletest')); | ||
it('should accept a DOM element as input', function () { | ||
let element = createRenderTarget(); | ||
assert.doesNotThrow(function () { | ||
Cycle.applyToDOM(element, () => Rx.Observable.empty()); | ||
}); | ||
}); | ||
it('should accept a string selector to an existing element as input', function () { | ||
let id = 'testShouldAcceptSelectorToExisting'; | ||
let element = createRenderTarget(); | ||
element.id = id; | ||
assert.doesNotThrow(function () { | ||
Cycle.applyToDOM('#' + id, () => Rx.Observable.empty()); | ||
}); | ||
}); | ||
it('should not accept a selector to an unknown element as input', function () { | ||
assert.throws(function () { | ||
Cycle.applyToDOM('#nonsenseIdToNothing', () => Rx.Observable.empty()); | ||
}, /Cannot render into unknown element/); | ||
}); | ||
it('should not accept a number as input', function () { | ||
assert.throws(function () { | ||
Cycle.applyToDOM(123); | ||
}, /Given container is not a DOM element neither a selector string/); | ||
}); | ||
it('should throw if definitionFn returns bad output', function () { | ||
assert.throws(function () { | ||
Cycle.applyToDOM(createRenderTarget(), () => ({})); | ||
applyToDOM(createRenderTarget(), () => ({})); | ||
}, /definitionFn given to/); | ||
@@ -70,3 +43,3 @@ }); | ||
); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
let selectEl = document.querySelector('.my-class'); | ||
@@ -82,3 +55,3 @@ assert.notStrictEqual(selectEl, null); | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), MyElement); | ||
applyToDOM(createRenderTarget(), MyElement); | ||
let myelement = document.querySelector('.myelementclass'); | ||
@@ -105,3 +78,3 @@ assert.notStrictEqual(myelement, null); | ||
} | ||
Cycle.applyToDOM(createRenderTarget(), computer); | ||
applyToDOM(createRenderTarget(), computer); | ||
// Make assertions | ||
@@ -131,3 +104,3 @@ let myElement = document.querySelector('.myelementclass'); | ||
} | ||
Cycle.applyToDOM(createRenderTarget(), computer); | ||
applyToDOM(createRenderTarget(), computer); | ||
let span = document.querySelector('.wrapperDiv > *:first-child'); | ||
@@ -145,3 +118,3 @@ assert.notStrictEqual(span, null); | ||
let vtree$ = Rx.Observable.just(<MyElement className="ERR" />); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
// Make assertions | ||
@@ -158,3 +131,3 @@ let myElement = document.querySelector('.myelementclass'); | ||
let vtree$ = Fixture89.viewWithContainerFn(number$, MyElement); | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
@@ -179,3 +152,3 @@ number$.request(1); | ||
assert.doesNotThrow(() => { | ||
Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
applyToDOM(createRenderTarget(), () => vtree$); | ||
number$.request(1); | ||
@@ -182,0 +155,0 @@ }); |
@@ -8,6 +8,2 @@ 'use strict'; | ||
describe('API', function () { | ||
it('should have `applyToDOM`', function () { | ||
assert.strictEqual(typeof Cycle.applyToDOM, 'function'); | ||
}); | ||
it('should have `component`', function () { | ||
@@ -14,0 +10,0 @@ assert.strictEqual(typeof Cycle.component, 'function'); |
@@ -72,17 +72,2 @@ 'use strict'; | ||
it('should not bind `this` for definitionFn by default', function () { | ||
let plan = 0; | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
(_1, _2, self) => { | ||
assert.equal(self, null); | ||
plan++; | ||
return Rx.Observable.empty(); | ||
} | ||
); | ||
let element = new MyElement(); | ||
element.componentWillMount(); | ||
assert.strictEqual(plan, 1); | ||
}); | ||
it('should be able to bind `this` for definitionFn', function () { | ||
@@ -98,3 +83,2 @@ let plan = 0; | ||
{ | ||
bindThis: true, | ||
mixins: [{foo: 'bar'}] | ||
@@ -101,0 +85,0 @@ } |
'use strict'; | ||
/* global describe, it */ | ||
let assert = require('assert'); | ||
let createEventSubject = require('../../src/event-subject'); | ||
let createEventSubject = require('../../src/rx/event-subject'); | ||
@@ -6,0 +6,0 @@ describe('createEventSubject', function () { |
@@ -6,7 +6,8 @@ 'use strict'; | ||
let EventEmitter = require('events').EventEmitter; | ||
let {makeInteractions} = require('../../src/interactions'); | ||
let createEventSubject = require('../../src/rx/event-subject'); | ||
let makeInteractions = require('../../src/interactions'); | ||
describe('interactions', function () { | ||
it('should provide collection of interactions', function (done) { | ||
let interactions = makeInteractions(); | ||
let interactions = makeInteractions(createEventSubject); | ||
interactions.get('foo').subscribe(function (value) { | ||
@@ -21,3 +22,3 @@ assert.strictEqual(value, 'bar'); | ||
it('should return the same interaction observable from the same key', function () { | ||
let interactions = makeInteractions(); | ||
let interactions = makeInteractions(createEventSubject); | ||
assert.strictEqual( | ||
@@ -30,3 +31,3 @@ interactions.get('foo'), | ||
it('should return the object of listeners by bindListeners', function (done) { | ||
let interactions = makeInteractions(); | ||
let interactions = makeInteractions(createEventSubject); | ||
let interactionTypes = { | ||
@@ -53,3 +54,3 @@ foo: 'onFoo', | ||
it('should throw error when the key is null', function () { | ||
let interactions = makeInteractions(); | ||
let interactions = makeInteractions(createEventSubject); | ||
assert.throws(() => interactions.get(), /Invalid name/i); | ||
@@ -60,3 +61,3 @@ assert.throws(() => interactions.get(null), /Invalid name/i); | ||
it('should warn when `listener` is used before `get`', function (done) { | ||
let interactions = makeInteractions(); | ||
let interactions = makeInteractions(createEventSubject); | ||
let tempConsoleWarn = console.warn; | ||
@@ -63,0 +64,0 @@ console.warn = function warn(message) { |
@@ -5,30 +5,4 @@ 'use strict'; | ||
let Rx = require('rx'); | ||
let { | ||
makeEmptyPropsObservable, | ||
makePropsObservable | ||
} = require('../../src/props'); | ||
let makePropsObservable = require('../../src/rx/props'); | ||
describe('makeEmptyPropsObservable', function () { | ||
it('should be an empty observable', function (done) { | ||
let props = makeEmptyPropsObservable(); | ||
props.subscribe(() => { | ||
throw new Error('Should not have element'); | ||
}, () => {}, done); | ||
}); | ||
it('should has `get()` returning empty observable', function (done) { | ||
let props = makeEmptyPropsObservable(); | ||
props.get().subscribe(() => { | ||
throw new Error('Should not have element'); | ||
}, () => {}, done); | ||
}); | ||
it('should has `getAll()` returning empty observable', function (done) { | ||
let props = makeEmptyPropsObservable(); | ||
props.getAll().subscribe(() => { | ||
throw new Error('Should not have element'); | ||
}, () => {}, done); | ||
}); | ||
}); | ||
describe('makePropsObservable', function () { | ||
@@ -35,0 +9,0 @@ it('should be an observable for all properties', function (done) { |
@@ -5,2 +5,3 @@ 'use strict'; | ||
let cheerio = require('cheerio'); | ||
let ReactDOMServer = require('react-dom/server'); | ||
let Cycle = require('../../'); | ||
@@ -14,3 +15,3 @@ let {Rx, React} = Cycle; | ||
)); | ||
let html = React.renderToStaticMarkup(React.createElement(Root)); | ||
let html = ReactDOMServer.renderToStaticMarkup(React.createElement(Root)); | ||
assert.strictEqual(html, '<div class="test-element">Foobar</div>'); | ||
@@ -31,3 +32,3 @@ }); | ||
}); | ||
let html = React.renderToStaticMarkup(React.createElement(MyElement)); | ||
let html = ReactDOMServer.renderToStaticMarkup(React.createElement(MyElement)); | ||
assert.strictEqual(html, '<div class="test-element">Foobar</div>'); | ||
@@ -44,3 +45,3 @@ assert.notStrictEqual(log, 123); | ||
)); | ||
let html = React.renderToStaticMarkup(React.createElement(Root)); | ||
let html = ReactDOMServer.renderToStaticMarkup(React.createElement(Root)); | ||
assert.strictEqual(html, '<div class="test-element"><h3 class="myelementclass"></h3></div>'); | ||
@@ -60,5 +61,5 @@ }); | ||
)); | ||
let html = React.renderToStaticMarkup(React.createElement(Root)); | ||
let html = ReactDOMServer.renderToStaticMarkup(React.createElement(Root)); | ||
assert.strictEqual(html, '<div class="test-element"><h3 class="myelementclass">YES</h3></div>'); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 1 instance in 1 package
9
3229951
2
41
62030
3
167
+ Addedjs-tokens@4.0.0(transitive)
+ Addedloose-envify@1.4.0(transitive)
+ Addedreact@18.3.1(transitive)
+ Addedrx@4.0.7(transitive)
- Removedrx@2.5.3(transitive)
Updatedrx@4.0.7