Skip to content

Instantly share code, notes, and snippets.

@mattiamanzati
Created June 2, 2016 23:02
Show Gist options
  • Select an option

  • Save mattiamanzati/eec8879c37ebf55d0938f58c2d8c52e6 to your computer and use it in GitHub Desktop.

Select an option

Save mattiamanzati/eec8879c37ebf55d0938f58c2d8c52e6 to your computer and use it in GitHub Desktop.
import xs, {Stream} from 'xstream';
import {run} from '@cycle/xstream-run';
import isolate from '@cycle/isolate';
import TextInput from './ui/TextInput';
import {makeDOMDriver, DOMSource, VNode, div} from '@cycle/dom';
interface MainSources{
DOM: DOMSource
}
interface ModelShape{
username: string
password: string
}
interface MainIntents{
change$: Stream<ModelShape>
}
interface MainModel{
value$: Stream<ModelShape>
}
interface MainSinks{
DOM: Stream<VNode>
}
function main(sources: MainSources): MainSinks & MainIntents & MainModel{
const username = isolate(TextInput, 'username')(sources);
// intents
const usernameChanged$ = username.change$;
const password = isolate(TextInput, 'password')(sources, {
value$: usernameChanged$.mapTo('')
});
const change$ = xs.combine(
(username, password) => ({username, password}),
username.change$,
password.change$
);
// model
const value$ = xs.combine(
(username, password) => ({username, password}),
username.value$,
password.value$
);
// view
const vtree$ = xs.combine(
(username, password) => div({}, [
username,
password
]),
username.DOM,
password.DOM
);
return {
DOM: vtree$,
value$,
change$
}
}
run(main, {
DOM: makeDOMDriver('#app')
});
import xs, {Stream} from 'xstream';
import {DOMSource, input, span, div, VNode} from '@cycle/dom';
export interface TextInputProps{
value$?: Stream<string>
}
export interface TextInputSources{
DOM: DOMSource
props?: TextInputProps
}
export interface TextInputIntents{
change$: Stream<string>
}
export interface TextInputModel{
value$: Stream<string>
}
export interface TextInputSinks{
DOM: Stream<VNode>
}
export interface TextInputComponentSinks extends TextInputSinks{
model: TextInputModel
intents: TextInputIntents
}
function intent(sources: TextInputSources): TextInputIntents{
const change$: Stream<string> = sources.DOM.select('input').events('keyup').map((ev: Event) => (<HTMLInputElement> ev.target).value);
return {
change$: sources.props && sources.props.value$ ? xs.merge(change$, sources.props.value$) : change$
};
}
function model(intents: TextInputIntents): TextInputModel {
const value$ = intents.change$.startWith('');
return {
value$
};
}
function view(model: TextInputModel): TextInputSinks{
const vtree$ = model.value$.map(value => div('.login', [
span('.label', value),
input('.test', {props: {value}})
]));
return {
DOM: vtree$
};
}
export default function TextInput(sources: TextInputSources, props?: TextInputProps): TextInputSinks & TextInputIntents & TextInputModel{
const componentIntents = intent(Object.assign({}, sources, {props}));
const componentModel = model(componentIntents);
return Object.assign(
view(componentModel),
componentModel,
componentIntents
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment