Skip to content

Instantly share code, notes, and snippets.

@AxelRHD
Created November 12, 2022 12:37
Show Gist options
  • Save AxelRHD/b6dc8f8719ee26fb29c64f01c9c9d90b to your computer and use it in GitHub Desktop.
Save AxelRHD/b6dc8f8719ee26fb29c64f01c9c9d90b to your computer and use it in GitHub Desktop.
Cycle.JS with JSX, Typescript and Parcel (Primer)
import { jsx, VNode } from "snabbdom";
import xs from "xstream";
import { Stream } from "xstream";
import run from "@cycle/run";
import { MainDOMSource, makeDOMDriver } from "@cycle/dom";
import { IStreams, ISources } from "./interfaces";
import { Navbar } from './components/navbar'
const intent = (sources: ISources): IStreams => {
const domSource = sources.DOM;
return {
toggleClicked$: domSource.select('.input').events('click')
}
}
const model = (actions: IStreams): Stream<any> => {
const toggleState$ = actions.toggleClicked$
.map(ev => ev.target.checked)
.startWith(true)
.debug('togglestate')
return toggleState$
}
const view = (domSource: MainDOMSource, model$: Stream<any>): Stream<VNode> => {
const navProps$ = xs.of({ message: "Super new header" }).debug('navProps')
const nav = Navbar({ DOM: domSource, props: navProps$ })
const tst$ = domSource.select('h1.super').events('click')
.map(v => !v)
.startWith(false)
const state$ = xs.combine(model$, nav.DOM)
.map(([model, childDom]) => {
return { ...model, childDom }
})
return state$.map(state =>
<div>
{ state.childDom }
<input attrs={{ type: "checkbox", class: "input", checked: state.toggle }} />
<span>Toggle me</span>
<p>{ state.toggle ? 'ON' : 'off'}</p>
</div>
)
}
const main = (sources: ISources): { DOM: Stream<VNode> } => {
const actions = intent(sources);
return {
DOM: view(sources.DOM, model(actions))
}
}
run(main, {
DOM: makeDOMDriver('#app')
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cycle Testing</title>
<script type="module" src="./src/app.tsx"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
import { MainDOMSource } from "@cycle/dom"
import { HTTPSource, RequestInput } from "@cycle/http"
import { Driver } from "@cycle/run"
import { Stream } from "xstream"
export interface ISources {
DOM: MainDOMSource,
HTTP?: Driver<Stream<RequestInput>, HTTPSource>
}
// export interface IMainSink {
// DOM: Stream<VNode>
// }
export interface IStreams {
[key: string]: Stream<any>
}
import { jsx, VNode } from "snabbdom";
import xs from "xstream";
import { Stream } from "xstream";
import { MainDOMSource } from "@cycle/dom";
export const Navbar = (sources: { DOM: MainDOMSource, props: Stream<any> }):
{ DOM: Stream<VNode>, value?: Stream<any> } => {
const domSource = sources.DOM
const props$ = sources.props
const headerClicked$ = domSource.select('h1.super').events('click')
const headerColor$ = headerClicked$
.mapTo('green')
.startWith('blue')
const state$ = xs.combine(props$, headerColor$)
.map(([props, headerColor]) => {
return { ...props, headerColor }
})
const vdom$ = state$
.map(state =>
<h1
style={{ color: state.headerColor }}
attrs={{ class: "super" }}
>{ state.message }</h1>
)
return {
DOM: vdom$
}
}
{
"name": "parcel-cycle-playground",
"version": "0.1.0",
"author": "AxelRHD",
"license": "MIT",
"scripts": {
"dev": "parcel index.html"
},
"dependencies": {
"@cycle/dom": "^23.1.0",
"@cycle/http": "^15.4.0",
"@cycle/run": "^5.7.0",
"snabbdom": "^3.5.1",
"xstream": "^11.14.0"
},
"devDependencies": {
"parcel": "^2.8.0",
"process": "^0.11.10"
}
}
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "jsx",
"jsxFragmentFactory": "Fragment"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment