cycle-react
Advanced tools
Comparing version 0.26.0 to 0.27.0
# Changelog | ||
## 0.27.0 | ||
Breaking change: Rename "createReactClass" to "component" | ||
For migrating to 0.27, simply replace the string "createReactClass" | ||
to "component". | ||
Fix: Remove unnecessary update on `props` change | ||
Add feature: New option "noDOMDispatchEvent" for skipping DOM dispatchEvent | ||
Use "noDOMDispatchEvent" if you want to handle events by using event handlers | ||
completely instead of using `interactions.get` API. | ||
## 0.26.0 | ||
@@ -4,0 +18,0 @@ |
@@ -8,3 +8,3 @@ | ||
- [`createReactClass`](#createReactClass) | ||
- [`component`](#component) | ||
@@ -56,14 +56,8 @@ - [`makeDOMDriver`](#makeDOMDriver) | ||
### <a id="createReactClass"></a> `createReactClass(tagName, definitionFn, [options])` | ||
### <a id="component"></a> `component(displayName, definitionFn, [options])` | ||
Takes a `definitionFn` function which outputs an Observable of React | ||
elements, and returns a converted React class which can be used normally | ||
elements, and returns a native React component which can be used normally | ||
by `React.createElement` and "Cycle.applyToDOM". | ||
**IMPORTANT** A React class should be used as a function object instead of | ||
class in cycle-react apps. If you found yourself writing `this.`, | ||
you're doing it wrong. | ||
"React class" shares the same terminology as Cycle's "custom element". | ||
The given `definitionFn` function takes two parameters as input, in this order: | ||
@@ -83,3 +77,3 @@ `interactions` and `properties`. The former works just like it does in the | ||
createReactClass('displayName', definitionFn, { | ||
component('displayName', definitionFn, { | ||
rootTagName: 'div', | ||
@@ -97,3 +91,3 @@ mixins: [], | ||
// The element for the first render would be <h1 /> | ||
createReactClass('displayName', () => Rx.Observable.just(<h1 />), { | ||
component('displayName', () => Rx.Observable.just(<h1 />), { | ||
rootTagName: 'div' | ||
@@ -104,3 +98,3 @@ }); | ||
// and the second element would be <h1 /> (after 1000ms) | ||
createReactClass('displayName', | ||
component('displayName', | ||
() => Rx.Observable.timer(1000).map(() => <h1 />), { | ||
@@ -113,3 +107,3 @@ rootTagName: 'div' | ||
// rootTagName has no effect in this case | ||
createReactClass('displayName', | ||
component('displayName', | ||
() => Rx.Observable.timer(1000) | ||
@@ -123,6 +117,6 @@ .map(() => <h1 />) | ||
- `tagName :: String` a name for identifying the React class. | ||
- `displayName :: String` a name for identifying the React component. | ||
- `definitionFn :: Function` the implementation for the custom element. This function takes two arguments: `interactions`, and `properties`, and | ||
should output an object of Observables. | ||
- `[options] :: Object` the options for createReactClass. | ||
- `[options] :: Object` the options for component. | ||
@@ -129,0 +123,0 @@ - - - |
@@ -8,21 +8,20 @@ # Using Cycle-React's DOM driver for Cycle.js | ||
let CycleReact = require('cycle-react'); | ||
let React = require('react'); | ||
let Rx = require('rx'); | ||
function main(drivers) { | ||
// The component definition | ||
function component(interactions) { | ||
return interactions.get('.myinput', 'input') | ||
.map(ev => ev.target.value) | ||
.startWith('') | ||
.map(name => | ||
<div> | ||
<label>Name:</label> | ||
<input className="myinput" type="text"></input> | ||
<hr /> | ||
<h1>Hello {name}</h1> | ||
</div> | ||
); | ||
} | ||
// The component's definition | ||
let TimerText = React.createClass({ | ||
render() { | ||
return <div>Seconds Elapsed: {this.props.seconds}</div>; | ||
} | ||
}); | ||
let MainPage = function mainPageComponent() { | ||
return Rx.Observable.interval(1000) | ||
.map(i => <TimerText seconds={i} />); | ||
}; | ||
return { | ||
// The definition function is required to be wrapped by Observable | ||
DOM: Rx.Observable.just(component) | ||
DOM: Rx.Observable.just(MainPage) | ||
}; | ||
@@ -49,5 +48,5 @@ } | ||
Plus, Cycle-React's `createReactClass` was not only designed to be returning the | ||
native React class, but also it can be used without the `Cycle.run`. So it's | ||
weird if we changed the `createReactClass` by using drivers without making it | ||
Plus, Cycle-React's `component` was not only designed to be returning the | ||
native React component, but also it can be used without the `Cycle.run`. So it's | ||
weird if we changed the `component` by using drivers without making it | ||
running with `Cycle.run`. |
@@ -40,4 +40,4 @@ # Interactions API | ||
To subscribe a event from Cycle-React's custom element, | ||
append "on" before the event name with a postfix "$". | ||
To subscribe an event from Cycle-React's custom element, | ||
append "on" before the event name. | ||
@@ -47,3 +47,3 @@ Example: | ||
```js | ||
var MyElement = createReactClass('MyElement', function computer() { | ||
var MyElement = Cycle.component('MyElement', function definition() { | ||
return { | ||
@@ -53,3 +53,3 @@ view: Rx.Observable.just(<h3 className="myelement">My Element</h3>), | ||
// The event observable | ||
tickEvent$: Rx.Observable.interval(500) | ||
tickEvent: Rx.Observable.interval(500) | ||
} | ||
@@ -59,4 +59,4 @@ } | ||
// Cycle-React would also try to | ||
// emit onTickEvent$ if ontickEvent$ was not found | ||
<MyElement ontickEvent$={interactions.subject('ontick').onEvent} /> | ||
// emit onTickEvent if ontickEvent was not found | ||
<MyElement ontickEvent={interactions.subject('ontick').onEvent} /> | ||
// You can still use interactions.get for custom elements | ||
@@ -63,0 +63,0 @@ interactions.get('.myelement', 'tickEvent').map(...); |
@@ -19,3 +19,3 @@ # Working with React | ||
In addition, properties that end with `$` except `vtree$` from your custom | ||
In addition, the properties inside of `events` object from your custom | ||
element will be converted to event handlers of the rendered element. | ||
@@ -26,3 +26,3 @@ | ||
```js | ||
let MyElement = createReactClass('MyElement', function computer() { | ||
let MyElement = Cycle.component('MyElement', function definition() { | ||
return { | ||
@@ -32,3 +32,3 @@ view: Rx.Observable.just(<h3 className="myelement">My Element</h3>), | ||
// The event observable | ||
tickEvent$: Rx.Observable.interval(500) | ||
tickEvent: Rx.Observable.interval(500) | ||
} | ||
@@ -38,4 +38,4 @@ } | ||
// Cycle-React would also try to | ||
// emit onTickEvent$ if ontickEvent$ was not found | ||
<MyElement ontickEvent$={myEventHandler} /> | ||
// emit onTickEvent if ontickEvent was not found | ||
<MyElement ontickEvent={myEventHandler} /> | ||
// You can still use interactions.get for custom elements | ||
@@ -60,3 +60,3 @@ interactions.get('.myelement', 'tickEvent').map(...); | ||
}; | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
// ... | ||
@@ -81,3 +81,3 @@ }, options); | ||
}; | ||
let MyElement = Cycle.createReactClass('MyElement', function (_1, _2, self) { | ||
let MyElement = Cycle.component('MyElement', function (_1, _2, self) { | ||
return Rx.Observable.just(<div onClick={() => self.goBack()}>Go back</div>) | ||
@@ -89,3 +89,3 @@ }, options); | ||
If you've ever tried to set `ref` to the element with Cycle-React, you're | ||
If you've ever tried to set `ref` to the element with Cycle-React, you've | ||
probably encountered this following error: | ||
@@ -101,3 +101,3 @@ | ||
This is because Cycle-React evaluates the vtree(ReactElement) inside the Rx | ||
subscription instead of `ReactClass.prototype.render`. In order to fix this, | ||
subscription instead of `Component.prototype.render`. In order to fix this, | ||
you can return the lazy value of ReactElement with the option | ||
@@ -113,3 +113,3 @@ `{bindThis: true}` set. | ||
}; | ||
let MyElement = Cycle.createReactClass('MyElement', (_1, _2, self) => { | ||
let MyElement = Cycle.component('MyElement', (_1, _2, self) => { | ||
// Return lambda instead of plain vtree | ||
@@ -127,3 +127,3 @@ return Rx.Observable.just(() => <input ref="myInput" />); | ||
(webpack hot module enabled). No extra configuration needed. | ||
This overriding behavior only affects the ReactClass created by Cycle-React | ||
This overriding behavior only affects the component created by Cycle-React | ||
and has no effect if webpack-hot-module was disabled. |
{ | ||
"name": "cycle-react", | ||
"version": "0.26.0", | ||
"version": "0.27.0", | ||
"author": { | ||
@@ -26,3 +26,2 @@ "name": "pH200", | ||
"dependencies": { | ||
"global": "^4.3.0", | ||
"rx": "2.5.2", | ||
@@ -29,0 +28,0 @@ "virtual-hyperscript": "^4.6.0" |
@@ -27,3 +27,3 @@ # Cycle-React | ||
let Cycle = require('cycle-react'); | ||
let React = Cycle.React; | ||
let React = require('react'); | ||
@@ -61,4 +61,5 @@ function computer(interactions) { | ||
The description of the concept behind `applyToDOM` and `Cycle` can be found at | ||
[Cycle.js](https://github.com/staltz/cycle/tree/v0.22.0) README. | ||
You can learn more about the concept behind `applyToDOM` and `Cycle` from | ||
André's amazing presentation: | ||
["What if the user was a function?"](https://youtu.be/1zj7M1LnJV4) | ||
@@ -69,17 +70,15 @@ ## Custom element example | ||
let Cycle = require('cycle-react'); | ||
let React = Cycle.React; | ||
let React = require('react'); | ||
let Rx = Cycle.Rx; | ||
// "createReactClass" returns a native react class which can be used normally | ||
// "component" returns a native React component which can be used normally | ||
// by "React.createElement" and "Cycle.applyToDOM". | ||
let CounterText = Cycle.createReactClass('CounterText', | ||
function (interactions, props) { | ||
return props.get('counter') | ||
.map(counter => <h3>Seconds Elapsed: {counter}</h3>); | ||
} | ||
); | ||
let Counter = Cycle.component('Counter', function (interactions, props) { | ||
return props.get('counter') | ||
.map(counter => <h3>Seconds Elapsed: {counter}</h3>); | ||
}); | ||
let Timer = Cycle.createReactClass('Timer', function () { | ||
let Timer = Cycle.component('Timer', function () { | ||
return Rx.Observable.interval(1000).map(i => | ||
<CounterText counter={i} /> | ||
<Counter counter={i} /> | ||
); | ||
@@ -95,23 +94,7 @@ }); | ||
You can use `h` and without JSX just like you did in Cycle.js. | ||
This was made possible by | ||
[react-hyperscript](https://github.com/mlmorg/react-hyperscript). | ||
[The example](/examples/timer/timer.js). | ||
## But you said no classes | ||
`createReactClass` transforms your `computer()` function into a ReactClass. So, | ||
you get a ReactClass but without writing a class definition. The point is that | ||
ReactClass **is** a function indeed and it should always be used as a | ||
function object, because you don't `new`, `extends` or `this` to access | ||
properties. In fact, we don't want you to do that. | ||
Apps written in Cycle-React are `this`-less. You won't find a single `this` | ||
in the examples. | ||
## Learn more | ||
Cycle-React shares the same API as Cycle.js, except of doing custom elements. | ||
A more comprehensive README can be found at | ||
https://github.com/staltz/cycle | ||
Cycle-React is a React-style implementation of Cycle.js, so we have the same | ||
concept of handling user interactions. More information of this concept can be | ||
found at: https://github.com/staltz/cycle | ||
@@ -139,3 +122,3 @@ ## Cycle.js Driver | ||
Yes. You can even use Cycle-React with your current React apps. Because | ||
`createReactClass` creates the native ReactClass for you. | ||
`component` creates the native React component for you. | ||
@@ -142,0 +125,0 @@ Examples for integrating Cycle-React with other libraries are work in progress. |
@@ -6,19 +6,21 @@ 'use strict'; | ||
var makeInteractions = require('./interactions').makeInteractions; | ||
var createCustomEvent = require('./CustomEvent'); | ||
var createCustomEventWithOption = require('./create-custom-event'); | ||
function makeDispatchFunction(elementGetter, eventName, handler) { | ||
function makeDispatchFunction(elementGetter, eventName, handler, noDispatch) { | ||
return function dispatchCustomEvent(evData) { | ||
//console.log('%cdispatchCustomEvent ' + eventName, | ||
// 'background-color: #CCCCFF; color: black'); | ||
var event = createCustomEvent(eventName, { | ||
var element = elementGetter(); | ||
var event = createCustomEventWithOption(eventName, { | ||
detail: evData, | ||
bubbles: true, | ||
cancelable: true | ||
}); | ||
var element = elementGetter(); | ||
}, element, noDispatch); | ||
if (element) { | ||
if (handler) { | ||
// invoke the event handler from props | ||
handler(event); | ||
} | ||
element.dispatchEvent(event); | ||
if (!noDispatch) { | ||
// dispatch DOM event by default | ||
element.dispatchEvent(event); | ||
} | ||
} else { | ||
@@ -33,3 +35,3 @@ console.warn( | ||
function composingEventObservables(events, handlerGetter, elementGetter) { | ||
function composingEventObservables(events, handlerGetter, elementGetter, noDispatch) { | ||
var eventNames = Object.keys(events); | ||
@@ -45,3 +47,4 @@ var eventObservables = []; | ||
eventName, | ||
handlerGetter(eventName) | ||
handlerGetter(eventName), | ||
noDispatch | ||
) | ||
@@ -96,3 +99,3 @@ ) | ||
function createReactClass( | ||
function component( | ||
displayName, | ||
@@ -114,2 +117,4 @@ definitionFn, | ||
var bindThis = !!options.bindThis; | ||
// The option for skipping DOM dispatchEvent | ||
var noDOMDispatchEvent = !!options.noDOMDispatchEvent; | ||
@@ -129,3 +134,5 @@ var reactClassProto = { | ||
this.rootElemSubject$ = new Rx.ReplaySubject(1); | ||
var interactions = makeInteractions(this.rootElemSubject$); | ||
var interactions = makeInteractions( | ||
this.rootElemSubject$.distinctUntilChanged() | ||
); | ||
var cycleComponent = digestDefinitionFnOutput( | ||
@@ -175,3 +182,4 @@ bindThis ? | ||
return React.findDOMNode(self); | ||
} | ||
}, | ||
noDOMDispatchEvent | ||
); | ||
@@ -198,5 +206,4 @@ if (eventObservables.length > 0) { | ||
shouldComponentUpdate: function shouldComponentUpdate(nextProps, nextState) { | ||
// https://facebook.github.io/react/docs/pure-render-mixin.html | ||
// This works perfectly because the state is always set by the new vtree. | ||
return this.props !== nextProps || this.state !== nextState; | ||
// Only care about the state since the props have been observed. | ||
return this.state !== nextState; | ||
}, | ||
@@ -213,2 +220,4 @@ componentWillMount: function componentWillMount() { | ||
componentDidUpdate: function componentDidUpdate() { | ||
// This action should be fast since React will cache the result of findDOMNode | ||
// facebook/react/src/renderers/dom/client/ReactMount.js#getNodeFromInstance | ||
var node = React.findDOMNode(this); | ||
@@ -223,4 +232,4 @@ this.rootElemSubject$.onNext(node); | ||
if (bindThis && typeof this.state.vtree === 'function') { | ||
// invoke literal is sufficient even though `addComponentAsRefTo` | ||
// might has something to do with `this` | ||
// `this` is bound automatically by React.createClass so the element | ||
// will have the owner set by this component | ||
return this.state.vtree(); | ||
@@ -259,2 +268,2 @@ } | ||
module.exports = createReactClass; | ||
module.exports = component; |
@@ -0,11 +1,13 @@ | ||
/* jshint browser:true */ | ||
'use strict'; | ||
var document = require('global/document'); | ||
var window = require('global/window'); | ||
var createCustomEvent; | ||
if (window && window.CustomEvent && typeof window.CustomEvent === 'function') { | ||
if (typeof window !== 'undefined' && | ||
window.CustomEvent && | ||
typeof window.CustomEvent === 'function') | ||
{ | ||
createCustomEvent = function createCustomEventDefault(type, eventInitDict) { | ||
return new window.CustomEvent(type, eventInitDict); | ||
}; | ||
} else if (document && document.createEvent) { | ||
} else if (typeof document !== 'undefined' && document.createEvent) { | ||
// http://www.w3.org/TR/dom/#customevent | ||
@@ -12,0 +14,0 @@ createCustomEvent = function createCustomEventShim(type, eventInitDict) { |
'use strict'; | ||
var applyToDOM = require('./render-dom'); | ||
var renderAsHTML = require('./render-html'); | ||
var createReactClass = require('./create-react-class'); | ||
var component = require('./create-react-class'); | ||
var makeDOMDriver = require('./cycle-driver'); | ||
@@ -46,11 +46,5 @@ var React = require('react'); | ||
* Takes a `definitionFn` function which outputs an Observable of React | ||
* elements, and returns a converted React class which can be used normally | ||
* elements, and returns a native React component which can be used normally | ||
* by `React.createElement` and "Cycle.applyToDOM". | ||
* | ||
* **IMPORTANT** A React class should be used as a function object instead of | ||
* class in cycle-react apps. If you found yourself writing `this.`, | ||
* you're doing it wrong. | ||
* | ||
* "React class" shares the same terminology as Cycle's "custom element". | ||
* | ||
* The given `definitionFn` function takes two parameters as input, in this order: | ||
@@ -70,3 +64,3 @@ * `interactions` and `properties`. The former works just like it does in the | ||
* | ||
* createReactClass('displayName', definitionFn, { | ||
* component('displayName', definitionFn, { | ||
* rootTagName: 'div', | ||
@@ -84,3 +78,3 @@ * mixins: [], | ||
* // The element for the first render would be <h1 /> | ||
* createReactClass('displayName', () => Rx.Observable.just(<h1 />), { | ||
* component('displayName', () => Rx.Observable.just(<h1 />), { | ||
* rootTagName: 'div' | ||
@@ -91,3 +85,3 @@ * }); | ||
* // and the second element would be <h1 /> (after 1000ms) | ||
* createReactClass('displayName', | ||
* component('displayName', | ||
* () => Rx.Observable.timer(1000).map(() => <h1 />), { | ||
@@ -100,3 +94,3 @@ * rootTagName: 'div' | ||
* // rootTagName has no effect in this case | ||
* createReactClass('displayName', | ||
* component('displayName', | ||
* () => Rx.Observable.timer(1000) | ||
@@ -108,10 +102,10 @@ * .map(() => <h1 />) | ||
* | ||
* @param {String} tagName a name for identifying the React class. | ||
* @param {String} displayName a name for identifying the React component. | ||
* @param {Function} definitionFn the implementation for the custom element. | ||
* This function takes two arguments: `interactions`, and `properties`, and | ||
* should output an object of Observables. | ||
* @param {Object} [options] the options for createReactClass. | ||
* @function createReactClass | ||
* @param {Object} [options] the options for component. | ||
* @function component | ||
*/ | ||
createReactClass: createReactClass, | ||
component: component, | ||
@@ -118,0 +112,0 @@ /** |
/* jshint browser:true */ | ||
'use strict'; | ||
var React = require('react'); | ||
var createReactClass = require('./create-react-class'); | ||
var component = require('./create-react-class'); | ||
@@ -35,3 +35,3 @@ function isElement(obj) { | ||
var RxReactRoot = createReactClass('RxReactRoot', definitionFn); | ||
var RxReactRoot = component('RxReactRoot', definitionFn); | ||
React.render(React.createElement(RxReactRoot), domContainer); | ||
@@ -38,0 +38,0 @@ |
@@ -22,3 +22,3 @@ 'use strict'; | ||
{ | ||
computer = function createReactClassFromObservable() { | ||
computer = function componentFromObservable() { | ||
return definitionFn; | ||
@@ -25,0 +25,0 @@ }; |
@@ -20,3 +20,3 @@ 'use strict'; | ||
throw new Error( | ||
'definitionFn given to render or createReactClass must return an ' + | ||
'definitionFn given to render or component must return an ' + | ||
'Observable of React elements, or an object containing such ' + | ||
@@ -23,0 +23,0 @@ 'Observable named as `view`'); |
@@ -26,3 +26,3 @@ 'use strict'; | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return Rx.Observable.just(h('h3.myelementclass')); | ||
@@ -43,3 +43,3 @@ }); | ||
let number$ = Rx.Observable.range(1, 10).controlled(); | ||
let MyElement = Cycle.createReactClass('MyElement', function (interactions, props) { | ||
let MyElement = Cycle.component('MyElement', function (interactions, props) { | ||
return Rx.Observable.combineLatest( | ||
@@ -79,3 +79,3 @@ props.get('color'), | ||
// Make custom element | ||
let MyElement = Cycle.createReactClass('myElement', function (interactions, props) { | ||
let MyElement = Cycle.component('myElement', function (interactions, props) { | ||
return props.get('*').map(propsObj => { | ||
@@ -110,7 +110,7 @@ assert.strictEqual(typeof propsObj, 'object'); | ||
// Make the first custom element | ||
let MyElement1 = Cycle.createReactClass('MyElement1', function () { | ||
let MyElement1 = Cycle.component('MyElement1', function () { | ||
return Rx.Observable.just(h('h1.myelement1class')); | ||
}); | ||
// Make the second custom element | ||
let MyElement2 = Cycle.createReactClass('MyElement2', function () { | ||
let MyElement2 = Cycle.component('MyElement2', function () { | ||
return Rx.Observable.just(h('h2.myelement2class')); | ||
@@ -138,7 +138,7 @@ }); | ||
// Make the inner custom element | ||
let Inner = Cycle.createReactClass('Inner', function () { | ||
let Inner = Cycle.component('Inner', function () { | ||
return Rx.Observable.just(h('h3.innerClass')); | ||
}); | ||
// Make the outer custom element | ||
let Outer = Cycle.createReactClass('Outer', function () { | ||
let Outer = Cycle.component('Outer', function () { | ||
return Rx.Observable.just( | ||
@@ -163,3 +163,3 @@ h('div.outerClass', [ | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return { | ||
@@ -173,3 +173,3 @@ view: Rx.Observable.just(h('h3.myelementclass', 'foobar')), | ||
// Use the custom element | ||
let Root = Cycle.createReactClass('Root', function (interactions) { | ||
let Root = Cycle.component('Root', function (interactions) { | ||
let vtree$ = Rx.Observable.just(h('div.toplevel', [ | ||
@@ -196,3 +196,3 @@ h(MyElement, {key: 1}) | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return { | ||
@@ -206,3 +206,3 @@ view: Rx.Observable.just(h('h3.myelementclass', 'foobar')), | ||
// Use the custom element | ||
let Root = Cycle.createReactClass('Root', function (interactions) { | ||
let Root = Cycle.component('Root', function (interactions) { | ||
let onmyevent$ = interactions.getEventSubject('onmyevent'); | ||
@@ -232,3 +232,3 @@ let vtree$ = Rx.Observable.just(h('div.toplevel', [ | ||
// Make custom element | ||
let Slider = Cycle.createReactClass('Slider', function (interactions, props) { | ||
let Slider = Cycle.component('Slider', function (interactions, props) { | ||
let remove$ = interactions.get('.internalslider', 'click') | ||
@@ -285,3 +285,3 @@ .map(() => true); | ||
// Make simple custom element | ||
let SimpleWrapper = Cycle.createReactClass('SimpleWrapper', function (interactions, props) { | ||
let SimpleWrapper = Cycle.component('SimpleWrapper', function (interactions, props) { | ||
return props.get('children').map(children => { | ||
@@ -306,3 +306,3 @@ return h('div.wrapper', children); | ||
it('should recognize changes on a mutable collection given as props', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', function (interactions, props) { | ||
let MyElement = Cycle.component('MyElement', function (interactions, props) { | ||
return props.get('list', () => false).map(list => | ||
@@ -343,3 +343,3 @@ h('div', [ | ||
it('should distinct property changes for props.get', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', function (interactions, props) { | ||
let MyElement = Cycle.component('MyElement', function (interactions, props) { | ||
return props.get('list').map(list => | ||
@@ -383,3 +383,3 @@ h('div', [ | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
// Here the vtree changes from <h3> to <button>, the myevent should | ||
@@ -400,3 +400,3 @@ // be emitted on <button> and not from the original <h3>. | ||
// Use the custom element | ||
let Root = Cycle.createReactClass('Root', function (interactions) { | ||
let Root = Cycle.component('Root', function (interactions) { | ||
let onmyevent$ = interactions.getEventSubject('onmyevent'); | ||
@@ -431,3 +431,3 @@ let vtree$ = Rx.Observable.just( | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return vtreeController$.map(control => { | ||
@@ -455,6 +455,6 @@ if (control === 0) { | ||
it('should accept vtree as function if bindThis was provided', function (done) { | ||
it('should accept vtree as function if bindThis was set', function (done) { | ||
let vtreeController$ = Rx.Observable.range(0, 2).controlled(); | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function (_1, _2, self) { | ||
let MyElement = Cycle.component('MyElement', function (_1, _2, self) { | ||
vtreeController$.subscribe(() => { | ||
@@ -473,2 +473,41 @@ let editField = Cycle.React.findDOMNode(self.refs.theRef); | ||
it('should not dispatch event if noDOMDispatchEvent was set', function (done) { | ||
let number$ = Rx.Observable.of(123, 456).controlled(); | ||
// Make simple custom element | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return { | ||
view: Rx.Observable.just(h('h3.myelementclass', 'foobar')), | ||
events: { | ||
myevent: number$ | ||
} | ||
}; | ||
}, {noDOMDispatchEvent: true}); | ||
// Use the custom element | ||
let Root = Cycle.component('Root', function (interactions) { | ||
let vtree$ = Rx.Observable.just(h(MyElement, { | ||
onmyevent(ev) { | ||
// Assert events | ||
assert.strictEqual(ev.type, 'myevent'); | ||
assert.strictEqual(ev.preventDefault, (void 0)); | ||
assert.ok(ev.detail === 123 || ev.detail === 456); | ||
assert.strictEqual(ev.target.tagName, 'H3'); | ||
assert.strictEqual(ev.target.innerHTML, 'foobar'); | ||
if (ev.detail === 456) { | ||
done(); | ||
} | ||
} | ||
})); | ||
interactions.get('.myelementclass', 'myevent').subscribe(x => { | ||
// Throw error for DOM event | ||
done(new Error('Should not dispatch DOM event')); | ||
}); | ||
return vtree$; | ||
}); | ||
Cycle.applyToDOM(createRenderTarget(), Root); | ||
number$.request(2); | ||
}); | ||
it('should dispose vtree$ after destruction', function () { | ||
@@ -479,3 +518,3 @@ let log = []; | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return number$ | ||
@@ -515,3 +554,3 @@ .do(i => log.push(i)) | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return { | ||
@@ -563,3 +602,3 @@ view: Rx.Observable.just(h('h3.myelementclass')), | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
let subscription = number$.subscribe(i => log.push(i)); | ||
@@ -596,3 +635,3 @@ return { | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
let subscription = number$.subscribe(i => log.push(i)); | ||
@@ -632,3 +671,3 @@ return { | ||
// Make simple custom element | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
let subscription = number$.subscribe(i => log.push(i)); | ||
@@ -635,0 +674,0 @@ return Rx.Observable.using( |
@@ -40,3 +40,3 @@ 'use strict'; | ||
responses.get('DOM', ':root').first().subscribe(function (root) { | ||
responses.DOM.get(':root').first().subscribe(function (root) { | ||
let myElement = document.querySelector('.myelementclass'); | ||
@@ -63,3 +63,3 @@ assert.notStrictEqual(myElement, null); | ||
responses.get('DOM', ':root').first().subscribe(function (root) { | ||
responses.DOM.get(':root').first().subscribe(function (root) { | ||
let myElement = document.querySelector('.myelementclass'); | ||
@@ -80,3 +80,3 @@ assert.notStrictEqual(myElement, null); | ||
// Assert event | ||
drivers.get('DOM', '.myelementclass', 'click') | ||
drivers.DOM.get('.myelementclass', 'click') | ||
.take(1) | ||
@@ -96,3 +96,3 @@ .subscribe(ev => { | ||
responses.get('DOM', ':root').first().subscribe(function (root) { | ||
responses.DOM.get(':root').first().subscribe(function (root) { | ||
let myElement = document.querySelector('.myelementclass'); | ||
@@ -116,3 +116,3 @@ assert.notStrictEqual(myElement, null); | ||
responses.get('DOM', ':root').subscribe(function (root) { | ||
responses.DOM.get(':root').subscribe(function (root) { | ||
throw new Error('Should not render'); | ||
@@ -119,0 +119,0 @@ }); |
@@ -20,30 +20,2 @@ 'use strict'; | ||
function makeGet(rawResponses) { | ||
return function get(driverName, ...params) { | ||
if (!rawResponses.hasOwnProperty(driverName)) { | ||
throw new Error(`get(${driverName}, ...) failed, no driver function ` + | ||
`named ${driverName} was found for this Cycle execution.`); | ||
} | ||
let driverResponse = rawResponses[driverName]; | ||
if (typeof driverResponse.subscribe === 'function') { | ||
return driverResponse; // is an Observable | ||
} else if (typeof driverResponse === 'object' && | ||
typeof driverResponse.get === 'function') | ||
{ | ||
return rawResponses[driverName].get.apply(null, params); | ||
} else if (typeof driverResponse === 'object' && | ||
params.length > 0 && | ||
typeof params[0] === 'string' && | ||
driverResponse.hasOwnProperty(params[0])) | ||
{ | ||
return rawResponses[driverName][params[0]]; | ||
} else { | ||
throw new Error(`get(${driverName}, ...) failed because driver was ` + | ||
`not able to process parameters. Report this bug to the driver ` + | ||
`function author.`); | ||
} | ||
}; | ||
} | ||
function makeDispose(requestProxies, rawResponses) { | ||
@@ -65,6 +37,7 @@ return function dispose() { | ||
function makeAppInput(requestProxies, rawResponses) { | ||
return { | ||
get: makeGet(rawResponses), | ||
dispose: makeDispose(requestProxies, rawResponses) | ||
}; | ||
Object.defineProperty(rawResponses, 'dispose', { | ||
enumerable: false, | ||
value: makeDispose(requestProxies, rawResponses) | ||
}); | ||
return rawResponses; | ||
} | ||
@@ -71,0 +44,0 @@ |
@@ -74,3 +74,3 @@ 'use strict'; | ||
it('should accept a ReactClass as definitionFn', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return Rx.Observable.just(h('h3.myelementclass')); | ||
@@ -133,3 +133,3 @@ }); | ||
it('should not set props.className to the root element', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', Fixture89.myelement); | ||
let MyElement = Cycle.component('MyElement', Fixture89.myelement); | ||
let vtree$ = Rx.Observable.just(h(MyElement, {className: 'ERR'})); | ||
@@ -145,3 +145,3 @@ Cycle.applyToDOM(createRenderTarget(), () => vtree$); | ||
it('should accept a view wrapping a custom element (#89)', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', Fixture89.myelement); | ||
let MyElement = Cycle.component('MyElement', Fixture89.myelement); | ||
let number$ = Fixture89.makeModelNumber$(); | ||
@@ -165,3 +165,3 @@ let vtree$ = Fixture89.viewWithContainerFn(number$, MyElement); | ||
it('should accept a view with custom element as the root of vtree$', function () { | ||
let MyElement = Cycle.createReactClass('MyElement', Fixture89.myelement); | ||
let MyElement = Cycle.component('MyElement', Fixture89.myelement); | ||
let number$ = Fixture89.makeModelNumber$(); | ||
@@ -168,0 +168,0 @@ let vtree$ = Fixture89.viewWithoutContainerFn(number$, MyElement); |
@@ -16,4 +16,4 @@ 'use strict'; | ||
it('should have `createReactClass`', function () { | ||
assert.strictEqual(typeof Cycle.createReactClass, 'function'); | ||
it('should have `component`', function () { | ||
assert.strictEqual(typeof Cycle.component, 'function'); | ||
}); | ||
@@ -20,0 +20,0 @@ |
@@ -7,5 +7,5 @@ 'use strict'; | ||
describe('createReactClass', function () { | ||
describe('component', function () { | ||
it('should have a default rootTagName', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -19,3 +19,3 @@ () => Rx.Observable.empty() | ||
it('should overwrite rootTagName', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -30,3 +30,3 @@ () => Rx.Observable.empty(), | ||
it('should not overwrite rootTagName by null options', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -41,3 +41,3 @@ () => Rx.Observable.empty(), | ||
it('should have default mixins', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -56,3 +56,3 @@ () => Rx.Observable.empty() | ||
}; | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -69,3 +69,3 @@ () => Rx.Observable.empty(), | ||
}; | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -80,3 +80,3 @@ () => Rx.Observable.empty(), | ||
let plan = 0; | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -96,3 +96,3 @@ (_1, _2, self) => { | ||
let plan = 0; | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -115,3 +115,3 @@ (_1, _2, self) => { | ||
it('should override forceUpdate for react-hot-loader', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -131,3 +131,3 @@ () => Rx.Observable.empty(), | ||
it('should not override forceUpdate by default', function () { | ||
let MyElement = Cycle.createReactClass( | ||
let MyElement = Cycle.component( | ||
'MyElement', | ||
@@ -134,0 +134,0 @@ () => Rx.Observable.empty() |
@@ -23,3 +23,3 @@ 'use strict'; | ||
var log = 0; | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return { | ||
@@ -44,3 +44,3 @@ view: Rx.Observable.just(h('div.test-element', ['Foobar'])), | ||
it('should render a simple nested custom element as HTML', function (done) { | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return Rx.Observable.just(h('h3.myelementclass')); | ||
@@ -62,6 +62,6 @@ }); | ||
it('should render double nested custom elements as HTML', function (done) { | ||
let MyElement = Cycle.createReactClass('MyElement', function () { | ||
let MyElement = Cycle.component('MyElement', function () { | ||
return Rx.Observable.just(h('h3.myelementclass')); | ||
}); | ||
let NiceElement = Cycle.createReactClass('NiceElement', function () { | ||
let NiceElement = Cycle.component('NiceElement', function () { | ||
return Rx.Observable.just(h('div.a-nice-element', null, [ | ||
@@ -87,3 +87,3 @@ 'foobar', h(MyElement) | ||
it('should render a nested custom element with props as HTML', function (done) { | ||
let MyElement = Cycle.createReactClass('MyElement', function (_, props) { | ||
let MyElement = Cycle.component('MyElement', function (_, props) { | ||
return props.get('foobar') | ||
@@ -90,0 +90,0 @@ .map(foobar => h('h3.myelementclass', null, String(foobar).toUpperCase())) |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
3248709
3
47
62553
145
- Removedglobal@^4.3.0
- Removeddom-walk@0.1.2(transitive)
- Removedglobal@4.4.0(transitive)
- Removedmin-document@2.19.0(transitive)
- Removedprocess@0.11.10(transitive)