Skip to content

Commit

Permalink
depend on cycle/react 1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
staltz committed Jul 14, 2018
1 parent 5116471 commit 8d58c8f
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 29 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -18,7 +18,7 @@
"typings": "lib/cjs/index.d.ts",
"types": "lib/cjs/index.d.ts",
"dependencies": {
"@cycle/react": "^1.0.2",
"@cycle/react": "^1.3.2",
"react": "16.4.x",
"react-native": ">=0.55.0",
"xstream": "11.x.x"
Expand Down
15 changes: 8 additions & 7 deletions readme.md
Expand Up @@ -13,12 +13,13 @@ import {run} from '@cycle/run';
import {makeReactNativeDriver, TouchableOpacity, View, Text} from '@cycle/react-native';

function main(sources) {
const inc$ = sources.react.select('inc').events('click');
const inc = Symbol();
const inc$ = sources.react.select(inc).events('click');

const count$ = inc$.fold(count => count + 1, 0);

const elem$ = count$.map(i =>
TouchableOpacity('inc', [
TouchableOpacity(inc, [
View([
Text(`Counter: ${i}`),
])
Expand Down Expand Up @@ -56,17 +57,17 @@ Import hyperscript helpers such as `View`, `Text`, `TouchableOpacity`, etc to cr
The basic usage is `View(props, children)`, but some variations and shortcuts are allowed:

- `View()` becomes `<View/>`
- `View(propsObject)` becomes `<View {...props}></View>`
- `View(props)` becomes `<View {...props}></View>`
- `Text('text content')` becomes `<Text>text content</Text>`
- `View([child1, child2])`
- `Text(propsObject, 'text content')`
- `View(propsObject, [child1, child2])`
- `Text(props, 'text content')`
- `View(props, [child1, child2])`
- etc

There are also shortcuts for (MVI) intent selectors:

- `Touchable('inc')` becomes `h(Touchable, {selector: 'inc'})`
- `Touchable('inc', propsObject)` becomes `h(Touchable, {selector: 'inc', ...props})`
- `Touchable(someSymbol)` becomes `h(Touchable, {sel: someSymbol})`
- `Touchable(sym, props)` becomes `h(Touchable, {sel: sym, ...props})`
- `Text('myselector', 'text content')`
- `Touchable('inc', [child])`
- `Touchable('inc', propsObject, [child])`
Expand Down
31 changes: 16 additions & 15 deletions src/index.ts
Expand Up @@ -86,23 +86,22 @@ export function makeReactNativeDriver(appKey: string) {
}

function parseSelector(param: any) {
if (typeof param === 'string' && param.length > 0) {
return param;
} else {
return null;
}
if (typeof param === 'symbol') return param;
if (typeof param === 'string' && param.length > 0) return param;
return null;
}

export type Children = Array<ReactElement<any>> | string;

export type HelperSig<P> = {
(sel: string): ReactElement<P>;
(sel: symbol): ReactElement<P>;
(child: string): ReactElement<P>;
(props: P): ReactElement<P>;
(children: Children): ReactElement<P>;
(sel: string, props: P): ReactElement<P>;
(sel: string | symbol, props: P): ReactElement<P>;
(props: P, children: Children): ReactElement<P>;
(sel: string, children: Children): ReactElement<P>;
(sel: string, props: P, children: Children): ReactElement<P>;
(sel: string | symbol, children: Children): ReactElement<P>;
(sel: string | symbol, props: P, children: Children): ReactElement<P>;
};

export function makeHelper<P>(type: ComponentType<P>): HelperSig<P> {
Expand All @@ -111,16 +110,18 @@ export function makeHelper<P>(type: ComponentType<P>): HelperSig<P> {
const hasB = typeof b !== 'undefined';
const hasBChildren = Array.isArray(b) || typeof b === 'string';
const hasC = typeof c !== 'undefined';
const selector = parseSelector(a);
if (selector) {
const sel = parseSelector(a);
if (sel) {
if (hasB && hasC) {
return h(type, {...b, selector}, c);
return h(type, {...b, sel}, c);
} else if (hasB && hasBChildren) {
return h(type, {selector} as any, b as Array<ReactElement<any>>);
return h(type, {sel} as any, b as Array<ReactElement<any>>);
} else if (hasB) {
return h(type, {...b, selector});
return h(type, {...b, sel});
} else if (typeof sel === 'symbol') {
return h(type, {sel} as any);
} else {
return h(type, selector as any /* child, not a selector */);
return h(type, sel as any /* child, not a sel */);
}
} else if (hasC) {
return h(type, b, c);
Expand Down
27 changes: 23 additions & 4 deletions test/helpers.ts
Expand Up @@ -59,6 +59,29 @@ describe('helpers', function() {
run(main, {react: testDriver});
});

it('View w/ symbol selector', done => {
function main(sources: {react: ReactSource}) {
const foo = Symbol();
const vdom$ = xs.of(View(foo));
return {react: vdom$};
}

function testDriver(sink: Stream<React.ReactElement<any>>) {
const source = new ReactSource();
const Root = makeCycleReactComponent(() => ({source, sink}));
const r = renderer.create(React.createElement(Root as any));
const root = r.root;
setTimeout(() => {
const view = root.findByType(_View);
assert.strictEqual(!!view, true);
done();
}, 50);
return source;
}

run(main, {react: testDriver});
});

it('View w/ selector and props', done => {
function main(sources: {react: ReactSource}) {
const vdom$ = xs.of(View('foo', {accessible: true}));
Expand All @@ -72,7 +95,6 @@ describe('helpers', function() {
const root = r.root;
setTimeout(() => {
const view = root.findByType(_View);
assert.strictEqual(view.props.selector, 'foo');
assert.strictEqual(view.props.accessible, true);
done();
}, 50);
Expand All @@ -96,7 +118,6 @@ describe('helpers', function() {
setTimeout(() => {
const view = root.findByType(_View);
const text = view.props.children;
assert.strictEqual(view.props.selector, 'foo');
assert.strictEqual(text.props.children, 'hello world');
done();
}, 50);
Expand All @@ -122,7 +143,6 @@ describe('helpers', function() {
setTimeout(() => {
const view = root.findByType(_View);
const text = view.props.children;
assert.strictEqual(view.props.selector, 'foo');
assert.strictEqual(view.props.accessible, true);
assert.strictEqual(text.props.children, 'hello world');
done();
Expand Down Expand Up @@ -171,7 +191,6 @@ describe('helpers', function() {
setTimeout(() => {
const view = root.findByType(_View);
const text = view.props.children;
assert.strictEqual(text.props.selector, 'foo');
assert.strictEqual(text.props.children, 'hello world');
done();
}, 50);
Expand Down
5 changes: 3 additions & 2 deletions test/index.ts
Expand Up @@ -23,10 +23,11 @@ class Touchable extends React.PureComponent<any, any> {
describe('React Native driver', function() {
it('converts an MVI Cycle app into a React component', function(done) {
function main(sources: {react: ReactSource}) {
const inc$ = sources.react.select('button').events('press');
const inc = Symbol();
const inc$ = sources.react.select(inc).events('press');
const count$ = inc$.fold((acc: number, x: any) => acc + 1, 0);
const vdom$ = count$.map((i: number) =>
h(Touchable, {selector: 'button'}, [h(View, [h(Text, {}, '' + i)])]),
h(Touchable, {sel: inc}, [h(View, [h(Text, {}, '' + i)])]),
);
return {react: vdom$};
}
Expand Down

0 comments on commit 8d58c8f

Please sign in to comment.