├── .editorconfig
├── .gitignore
├── 404.html
├── LICENSE
├── README.md
├── _config.yml
├── _includes
├── footer.html
├── homepage-content.md
└── img
│ ├── actuators-senses-input-output.svg
│ ├── actuators-senses.svg
│ ├── completed-stream.svg
│ ├── custom-element-drivers.svg
│ ├── cycle-nested-frontpage.svg
│ ├── dataflow-component.svg
│ ├── dataflow-minimap.svg
│ ├── egghead.svg
│ ├── fold-counter.svg
│ ├── hci-inputs-outputs.svg
│ ├── human-computer-diagram.svg
│ ├── intent-translation.svg
│ ├── main-domdriver-side-effects.svg
│ ├── main-eq-mvi.svg
│ ├── modules-foo-bar.svg
│ ├── mvc-diagram.svg
│ ├── nested-components.svg
│ ├── passive-foo-bar.svg
│ ├── reactive-foo-bar.svg
│ ├── simple-human-computer.svg
│ └── view-translation.svg
├── _layouts
├── blank.html
└── default.html
├── _posts
├── 2015-01-21-community.md
├── 2015-01-22-documentation.md
├── 2015-01-23-drivers.md
├── 2015-01-25-components.md
├── 2015-01-26-model-view-intent.md
├── 2015-01-28-basic-examples.md
├── 2015-01-29-streams.md
├── 2015-01-30-dialogue.md
└── 2015-01-31-getting-started.md
├── _sass
├── basic.sass
├── colors.sass
├── dimens.sass
├── documentation.sass
├── homepage.sass
├── mixins.sass
├── typography.sass
└── vendor.sass
├── android-icon-144x144.png
├── android-icon-192x192.png
├── android-icon-36x36.png
├── android-icon-48x48.png
├── android-icon-72x72.png
├── android-icon-96x96.png
├── apple-icon-114x114.png
├── apple-icon-120x120.png
├── apple-icon-144x144.png
├── apple-icon-152x152.png
├── apple-icon-180x180.png
├── apple-icon-57x57.png
├── apple-icon-60x60.png
├── apple-icon-72x72.png
├── apple-icon-76x76.png
├── apple-icon-precomposed.png
├── apple-icon.png
├── archive.html
├── browserconfig.xml
├── favicon-16x16.png
├── favicon-32x32.png
├── favicon-96x96.png
├── favicon.ico
├── img
├── cyclejs_logo.svg
└── egghead.png
├── index.html
├── js
└── example-hello-world.min.js
├── main.sass
├── manifest.json
├── ms-icon-144x144.png
├── ms-icon-150x150.png
├── ms-icon-310x310.png
└── ms-icon-70x70.png
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | end_of_line = lf
5 | insert_final_newline = true
6 | indent_style = space
7 | indent_size = 2
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .sass-cache/
3 | .DS_Store
4 | _site/
5 |
6 | # Editors
7 | .idea/
8 |
9 | .jekyll-metadata
10 |
--------------------------------------------------------------------------------
/404.html:
--------------------------------------------------------------------------------
1 | ---
2 | layout: default
3 | ---
4 |
5 | 404
8 |
4 | {% include /img/cycle-nested-frontpage.svg %} 5 |
6 | 7 | Cycle's core abstraction is your application as a pure function `main()` where inputs are read effects (*sources*) from the external world and outputs (*sinks*) are write effects to affect the external world. These I/O effects in the external world are managed by *drivers*: plugins that handle DOM effects, HTTP effects, etc. 8 | 9 | The internals of `main()` are built using Reactive Programming primitives, which maximizes separation of concerns and provides a fully declarative way of organizing your code. The *dataflow* is plainly visible in the code, making it readable and traceable. 10 | 11 | ## Example 12 | 13 | {% highlight text %} 14 | npm install xstream @cycle/xstream-run @cycle/dom 15 | {% endhighlight %} 16 | 17 | {% highlight js %} 18 | import {run} from '@cycle/xstream-run'; 19 | import {div, label, input, hr, h1, makeDOMDriver} from '@cycle/dom'; 20 | 21 | function main(sources) { 22 | const sinks = { 23 | DOM: sources.DOM.select('.field').events('input') 24 | .map(ev => ev.target.value) 25 | .startWith('') 26 | .map(name => 27 | div([ 28 | label('Name:'), 29 | input('.field', {attrs: {type: 'text'}}), 30 | hr(), 31 | h1('Hello ' + name), 32 | ]) 33 | ) 34 | }; 35 | return sinks; 36 | } 37 | 38 | run(main, { DOM: makeDOMDriver('#app-container') }); 39 | {% endhighlight %} 40 | 41 | 42 | 43 |68 | {% include /img/dataflow-minimap.svg %} 69 |
70 |103 | {% include /img/nested-components.svg %} 104 |
105 | 106 | Sources and sinks are the interface between the application and the drivers, but they are also the interface between a child component and its parent. Cycle.js components can be simply GUI widgets like in other frameworks, but they are not limited to GUIs only. You can make Web Audio components, network requests components, and others, since the sources/sinks interface is not exclusive to the DOM. 107 | 108 | ## Learn it in 1h 37min 109 | 110 |111 | {% include /img/egghead.svg %} 112 |
113 | 114 | Got 1 hour and 37 minutes? That is all it takes to learn the essentials of Cycle.js. Watch [**this free Egghead.io video course**](https://egghead.io/series/cycle-js-fundamentals) given by the creator of Cycle.js. Understand Cycle.js from within by following how it is built from scratch, then learn how to transform your ideas into applications. 115 | 116 | 117 | 118 | ## Supports... 119 | 120 | - [**Virtual DOM rendering**](https://github.com/cyclejs/cyclejs/tree/master/dom) 121 | - [**Server-side rendering**](https://github.com/cyclejs/cyclejs/tree/master/examples/isomorphic) 122 | - [**JSX**](http://cycle.js.org/getting-started.html) 123 | - [**TypeScript**](https://github.com/cyclejs/cyclejs/tree/master/examples/bmi-typescript) 124 | - [**React Native**](https://github.com/cyclejs/cycle-react-native) 125 | - [**Time traveling**](https://github.com/cyclejs/cycle-time-travel) 126 | - [**Routing with the History API**](https://github.com/cyclejs/history) 127 | - [**And more...**](https://github.com/cyclejs-community/awesome-cyclejs) 128 | -------------------------------------------------------------------------------- /_includes/img/actuators-senses-input-output.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/actuators-senses.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/completed-stream.svg: -------------------------------------------------------------------------------- 1 | 31 | -------------------------------------------------------------------------------- /_includes/img/custom-element-drivers.svg: -------------------------------------------------------------------------------- 1 | 74 | -------------------------------------------------------------------------------- /_includes/img/cycle-nested-frontpage.svg: -------------------------------------------------------------------------------- 1 | 2 | 98 | -------------------------------------------------------------------------------- /_includes/img/dataflow-component.svg: -------------------------------------------------------------------------------- 1 | 2 | 53 | -------------------------------------------------------------------------------- /_includes/img/dataflow-minimap.svg: -------------------------------------------------------------------------------- 1 | 2 | 86 | -------------------------------------------------------------------------------- /_includes/img/egghead.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/fold-counter.svg: -------------------------------------------------------------------------------- 1 | 2 | 64 | -------------------------------------------------------------------------------- /_includes/img/hci-inputs-outputs.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/human-computer-diagram.svg: -------------------------------------------------------------------------------- 1 | 55 | -------------------------------------------------------------------------------- /_includes/img/intent-translation.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_includes/img/main-domdriver-side-effects.svg: -------------------------------------------------------------------------------- 1 | 75 | -------------------------------------------------------------------------------- /_includes/img/main-eq-mvi.svg: -------------------------------------------------------------------------------- 1 | 2 | 47 | -------------------------------------------------------------------------------- /_includes/img/modules-foo-bar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/mvc-diagram.svg: -------------------------------------------------------------------------------- 1 | 60 | -------------------------------------------------------------------------------- /_includes/img/nested-components.svg: -------------------------------------------------------------------------------- 1 | 2 | 42 | -------------------------------------------------------------------------------- /_includes/img/passive-foo-bar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/reactive-foo-bar.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/simple-human-computer.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /_includes/img/view-translation.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /_layouts/blank.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | {% if page.author %}{% endif %} 7 | 8 |29 | {% include /img/human-computer-diagram.svg %} 30 |
31 | 32 | However, in practice, we write our `main()` function targeted at a `domDriver()`. For a user interacting with a browser, we only need to make our `main()` interact with the DOM. Whenever we need to show something to the user, we instead show that to the DOM, and the DOM together with the browser shows that to our user. When we need to detect the user's interaction events, we attach event listeners on the DOM, and the DOM will notify us when the user interacts with the browser on the computer. 33 | 34 |35 | {% include /img/main-domdriver-side-effects.svg %} 36 |
37 | 38 | Notice there are two directions of interaction with the external world through the DOM. The *write* effect is the renderization of our Snabbdom VNodes to DOM elements which can be shown on the user's screen. The *read* effect is the detection of DOM events generated by the user manipulating the computer. 39 | 40 | The `domDriver()` manages these two effects while allowing them to be interfaced with the `main()`. The *input* to `domDriver()` captures instructions for the *write* effect, and the *read* effect is exposed as the *output* of `domDriver()`. The anatomy of the `domDriver()` function is roughly the following: 41 | 42 | {% highlight js %} 43 | function domDriver(vdom$) { 44 | // Use vdom$ as instructions to create DOM elements 45 | // ... 46 | return { 47 | select: function select(selector) { 48 | // returns an object with two functions: `events()` 49 | // and `elements()`. Function `events(eventType)` 50 | // returns the stream of `eventType` DOM events 51 | // happening on the elements matched by `selector`. 52 | // Function `elements()` is the stream of DOM 53 | // elements matching the given `selector`. 54 | } 55 | }; 56 | } 57 | {% endhighlight %} 58 | 59 | The input `vdom$` is the output from `main()`, and the output of `domDriver()` is the input to `main()`: 60 | 61 | {% highlight js %} 62 | function main(sources) { 63 | // Use sources.DOM.select(selector).events(eventType) 64 | // ... 65 | // Create vdom$ somehow 66 | // ... 67 | return { 68 | DOM: vdom$ 69 | }; 70 | } 71 | {% endhighlight %} 72 | 73 | As a recap: 74 | 75 | - `main()`: takes **sources** as input, returns **sinks** 76 | - `domDriver()`: takes **sinks** as input, performs write and read effects, returns **sources**. 77 | 78 |