garbles/yolk
{ "createdAt": "2015-09-02T02:55:05Z", "defaultBranch": "master", "description": ":egg: A library for building asynchronous user interfaces.", "fullName": "garbles/yolk", "homepage": "", "language": "JavaScript", "name": "yolk", "pushedAt": "2016-08-03T16:29:04Z", "stargazersCount": 923, "topics": [], "updatedAt": "2024-12-17T11:12:20Z", "url": "https://github.com/garbles/yolk"}:rotating_light: This library is no longer being maintained :rotating_light:
:rotating_light: This is the README/source for the proposed Yolk v1. Go here to see the README for v0.10.1. :rotating_light:
Yolk 
A library for building asynchronous user interfaces.
-
Familiar: Yolk is a small library built on top of Virtual DOM and RxJS. It exposes a very limited API so that you don’t have to spend weeks getting up to speed. Yolk components are just plain functions that return JSX or hyperscript.
-
Everything is an observable: Yolk components consume RxJS observable streams as if they were plain values. From a websocket connection to a generator function to an event handler. If it can be represented as an observable, then it can be rendered directly into your markup.
-
Stateless: Being able to describe user interactions, control flow and plain values as observable streams means that application design becomes entirely declarative. There is no need to manually subscribe to observables in order to mutate or set component state.
Example
Section titled “Example”The following example renders a component with buttons to increment and decrement a counter.
import { h, render } from 'yolk'
import 'rxjs/add/operator/map'import 'rxjs/add/operator/merge'import 'rxjs/add/operator/scan'import 'rxjs/add/operator/startWith'
function Counter ({props, children, createEventHandler}) {
// map all plus button click events to 1 const handlePlus = createEventHandler() const plusOne$ = handlePlus.map(() => 1)
// map all minus button click events to -1 const handleMinus = createEventHandler() const minusOne$ = handleMinus.map(() => -1)
// merge both event streams together and keep a running count of the result const count$ = plusOne$.merge(minusOne$).scan((x, y) => x + y, 0).startWith(0)
// prop keys are always cast as observables const title$ = props.title.map(title => `Awesome ${title}`)
return ( <div> <h1>{title$}</h1> <div> <button id="plus" onClick={handlePlus}>+</button> <button id="minus" onClick={handleMinus}>-</button> </div> <div> <span>Count: {count$}</span> </div> {children} </div> )}
render(<Counter title="Example" />, document.getElementById('container'))Additionally, see the Yolk implementation of TodoMVC or The Flux Challenge.
The Yolk API is intentionally very limited so that you don’t have to spend weeks getting up to speed. With an understanding of RxJS, you can begin building with Yolk immediately.
Instance API
Section titled “Instance API”Yolk components inject a single object as an argument. The object has three keys: props, children, and createEventHandler.
props: Object<Observable>
Section titled “props: Object<Observable>”An object who’s keys are the props passed into the component. These props are wrapped in observables if they are not already observables.
import { h, render } from 'yolk'
function MyComponent({props}) { return <h1>{props.title.map(t => `${t}!`)}</h1>}
// both of the following will render the same result: `<h1>Hello!</h1>`
// render MyComponent with an observable as the title propconst title$ = new Rx.BehaviorSubject("Hello")render(<MyComponent title={title$} />, document.querySelector(`#container`))
// render MyComponent with a plain value as the title proprender(<MyComponent title="Hello" />, document.querySelector(`#container`))children: Observable
Section titled “children: Observable”An observable of the children passed to a component.
import { h, render } from 'yolk'
function MyComponent({children}) { return <p>{children}</p>}
render( <MyComponent><strong>HELLO!</strong><span>world...</span></MyComponent>, document.querySelector(`#container`))// renders <p><strong>HELLO!</strong><span>world...</span></p>createEventHandler(mapping: any, initialValue: any): Function
Section titled “createEventHandler(mapping: any, initialValue: any): Function”Creates a custom subject to be used as an event handler. If the event is invoked, it is pushed to the subject as it’s latest value. For example,
import { h, render } from 'yolk'
function MyComponent ({createEventHandler}) { // create an event handler const handleClick = createEventHandler()
// use event handler to count the number of clicks const numberOfClicks = handleClick.scan((acc, ev) => acc + 1, 0).startWith(0)
// create an element that displays the number of clicks // and a button to increment it return ( <div> <span>Number of clicks: {numberOfClicks}</span> <button onClick={handleClick}>Click me!</button> </div> )}Alternatively, we could have written,
import { h, render } from 'yolk'
function MyComponent ({createEventHandler}) { // map all events to 1, and emit a value of 0 first const handleClick = createEventHandler(1, 0)
const numberOfClicks = handleClick.scan((acc, inc) => acc + inc, 0)
return ( <div> <span>Number of clicks: {numberOfClicks}</span> <button onClick={handleClick}>Click me!</button> </div> )}If the first argument of createEventHandler is a function, it will be invoked with the event as the first argument.
Subscriptions to event handlers are automatically cleaned up when the component is unmounted.
Top Level API
Section titled “Top Level API”render(instance: YolkElement, node: HTMLElement): void
Section titled “render(instance: YolkElement, node: HTMLElement): void”Renders an instance of a YolkComponent inside of an HTMLElement.
import { render } from 'yolk'render(<span>Hello World!</span>, document.querySelector(`#container`))h(component: string|Function , [props: Object<any>], [...children: Array<any>]): YolkElement
Section titled “h(component: string|Function , [props: Object<any>], [...children: Array<any>]): YolkElement”If you prefer hyperscript over JSX, Yolk exposes a function h which can be used to write your components with hyperscript.
h also parses tags for brevity. For example, p.my-class will append a my-class class to a p tag, #some-id will
append a some-id id to a div tag.
import { h } from 'yolk'
function MyComponent ({createEventHandler}) { const handleClick = createEventHandler()
const numberOfClicks = handleClick.scan((acc, ev) => acc + 1, 0).startWith(0)
return h(`.my-counter-component`, {}, h(`span#counter`, {}, `Number of clicks: `, numberOfClicks), h(`button#clicker`, {onClick: handleClick}, `Click me!`) )}See [#using-jsx]!(Using JSX) for how to write Yolk components with JSX.
Using JSX
Section titled “Using JSX”It is highly suggested that you write Yolk with JSX. This is achieved using the Babel transpiler (version 6+). You should install your babel tool of choice (e.g., babel-cli or babel-loader) and babel-plugin-transform-react-jsx and configure the pragma option for transform-react-jsx.
Run:
npm i --save-dev babel-cli babel-plugin-transform-react-jsx.babelrc:
{ "plugins": [ ["transform-react-jsx", {"pragma": "h"}] ]}Then anywhere you use JSX it will be transformed into plain JavaScript. For example this,
<p>My JSX</p>Turns into,
h( "p", null, "My JSX");Without this pragma, Babel will assume that you mean to write JSX for React and you will receive React is undefined errors.
If you want to additionally transpile ES2015 code into ES5 code you should install and use babel-preset-es2015:
{ "presets": ["es2015"], "plugins": [ ["transform-react-jsx", {"pragma": "h"}] ]}See yolk-todomvc for a complete working example.
Supported Events
Section titled “Supported Events”Yolk supports the following list of standard browser events,
onAbort onBlur onCancel onCanPlay onCanPlayThrough onChange onClickonCompositionStart onCompositionUpdate onCompositionEnd onContextMenu onCopyonCueChange onCut onDblClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOveronDragStart onDrop onDurationChange onEmptied onEnded onEncypted onError onFocus onInputonInvalid onKeyDown onKeyPress onKeyUp onLoad onLoadedData onLoadedMetaData onLoadStartonMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUponPaste onPause onPlay onPlaying onProgress onRateChange onReset onResize onScroll onSearchonSeeked onSeeking onSelect onShow onStalled onSubmit onSuspend onTimeUpdate onTouchCancelonTouchEnd onTouchMove onTouchStart onToggle onVolumeChange onWaiting onWheelIn addition, Yolk supports the following custom browser events,
onMount onUnmountSupported Attributes
Section titled “Supported Attributes”Yolk supports the following list of standard element attributes,
accept acceptCharset accessKey action align alt async autoComplete autoFocus autoPlayautoSave bgColor border cite className color colSpan contentcontentEditable coords default defer dir dirName draggable dropZoneencType for headers height hidden href hrefLang httpEquiv icon id isMapitemProp keyType kind label lang max method min name noValidate openoptimum pattern ping placeholder poster preload radioGroup relrequired reversed rowSpan sandbox scope span spellCheck src srcLang startstep style summary tabIndex target title type useMap wrap allowFullScreenallowTransparency capture charset challenge cols contextMenu dateTime disabled formformAction formEncType formMethod formTarget frameBorder inputMode is list manifestmaxLength media minLength role rows seamless size sizes srcSet width checkedcontrols loop multiple readOnly selected srcDoc valueTo install Yolk, simply include it in your package.json,
npm install yolk@^1.0.0-beta --save