{"id":13516821,"url":"https://github.com/garbles/yolk","last_synced_at":"2025-12-12T05:56:07.560Z","repository":{"id":57404093,"uuid":"41776119","full_name":"garbles/yolk","owner":"garbles","description":":egg: A library for building asynchronous user interfaces.","archived":true,"fork":false,"pushed_at":"2016-08-03T16:29:04.000Z","size":1414,"stargazers_count":925,"open_issues_count":19,"forks_count":32,"subscribers_count":27,"default_branch":"master","last_synced_at":"2024-05-10T03:43:17.051Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/garbles.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-02T02:55:05.000Z","updated_at":"2024-01-15T05:17:33.000Z","dependencies_parsed_at":"2022-09-22T09:00:38.983Z","dependency_job_id":null,"html_url":"https://github.com/garbles/yolk","commit_stats":null,"previous_names":["brewhouseteam/yolk"],"tags_count":48,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbles%2Fyolk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbles%2Fyolk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbles%2Fyolk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/garbles%2Fyolk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/garbles","download_url":"https://codeload.github.com/garbles/yolk/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246432832,"owners_count":20776471,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T05:01:26.228Z","updated_at":"2025-10-22T21:09:40.241Z","avatar_url":"https://github.com/garbles.png","language":"JavaScript","readme":":rotating_light: This library is no longer being maintained :rotating_light:\n\n:rotating_light: This is the README/source for the proposed Yolk v1. [Go here](https://github.com/garbles/yolk/tree/v0.10.1) to see the README for v0.10.1. :rotating_light:\n\n\u003ch1\u003eYolk \u003cimg src=\"https://avatars3.githubusercontent.com/u/15056177?v=3\u0026s=50\" alt=\"https://twitter.com/patdryburgh\" /\u003e\u003c/h1\u003e\n\n[![Join the chat at https://gitter.im/yolkjs/yolk](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/yolkjs/yolk?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n[![circle-ci](https://circleci.com/gh/garbles/yolk/tree/master.png?style=shield)](https://circleci.com/gh/garbles/yolk)\n[![npm version](https://badge.fury.io/js/yolk.svg)](https://badge.fury.io/js/yolk)\n\nA library for building asynchronous user interfaces.\n\n* __Familiar__: Yolk is a small library built on top of [Virtual DOM](https://github.com/Matt-Esch/virtual-dom) and [RxJS](https://github.com/Reactive-Extensions/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.\n\n* __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.\n\n* __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.\n\n## Example\n\nThe following example renders a component with buttons to increment and decrement a counter.\n\n```js\nimport { h, render } from 'yolk'\n\nimport 'rxjs/add/operator/map'\nimport 'rxjs/add/operator/merge'\nimport 'rxjs/add/operator/scan'\nimport 'rxjs/add/operator/startWith'\n\nfunction Counter ({props, children, createEventHandler}) {\n\n  // map all plus button click events to 1\n  const handlePlus = createEventHandler()\n  const plusOne$ = handlePlus.map(() =\u003e 1)\n\n  // map all minus button click events to -1\n  const handleMinus = createEventHandler()\n  const minusOne$ = handleMinus.map(() =\u003e -1)\n\n  // merge both event streams together and keep a running count of the result\n  const count$ = plusOne$.merge(minusOne$).scan((x, y) =\u003e x + y, 0).startWith(0)\n\n  // prop keys are always cast as observables\n  const title$ = props.title.map(title =\u003e `Awesome ${title}`)\n\n  return (\n    \u003cdiv\u003e\n      \u003ch1\u003e{title$}\u003c/h1\u003e\n      \u003cdiv\u003e\n        \u003cbutton id=\"plus\" onClick={handlePlus}\u003e+\u003c/button\u003e\n        \u003cbutton id=\"minus\" onClick={handleMinus}\u003e-\u003c/button\u003e\n      \u003c/div\u003e\n      \u003cdiv\u003e\n        \u003cspan\u003eCount: {count$}\u003c/span\u003e\n      \u003c/div\u003e\n      {children}\n    \u003c/div\u003e\n  )\n}\n\nrender(\u003cCounter title=\"Example\" /\u003e, document.getElementById('container'))\n```\n\nAdditionally, see the Yolk implementation of [TodoMVC](https://github.com/yolkjs/yolk-todomvc) or [The Flux Challenge](https://github.com/staltz/flux-challenge/tree/master/submissions/garbles).\n\n## API\n\nThe Yolk API is intentionally very limited so that you don't have to spend weeks getting up to speed. With an understanding of [RxJS](https://github.com/ReactiveX/RxJS), you can begin building with Yolk immediately.\n\n### Instance API\n\nYolk components inject a single object as an argument. The object has three keys: `props`, `children`, and `createEventHandler`.\n\n##### `props: Object\u003cObservable\u003e`\n\nAn object who's keys are the props passed into the component. These props are wrapped in observables if they are not already observables.\n\n```js\nimport { h, render } from 'yolk'\n\nfunction MyComponent({props}) {\n  return \u003ch1\u003e{props.title.map(t =\u003e `${t}!`)}\u003c/h1\u003e\n}\n\n// both of the following will render the same result: `\u003ch1\u003eHello!\u003c/h1\u003e`\n\n// render MyComponent with an observable as the title prop\nconst title$ = new Rx.BehaviorSubject(\"Hello\")\nrender(\u003cMyComponent title={title$} /\u003e, document.querySelector(`#container`))\n\n// render MyComponent with a plain value as the title prop\nrender(\u003cMyComponent title=\"Hello\" /\u003e, document.querySelector(`#container`))\n```\n\n##### `children: Observable`\n\nAn observable of the children passed to a component.\n\n```js\nimport { h, render } from 'yolk'\n\nfunction MyComponent({children}) {\n  return \u003cp\u003e{children}\u003c/p\u003e\n}\n\nrender(\n  \u003cMyComponent\u003e\u003cstrong\u003eHELLO!\u003c/strong\u003e\u003cspan\u003eworld...\u003c/span\u003e\u003c/MyComponent\u003e,\n  document.querySelector(`#container`)\n)\n// renders \u003cp\u003e\u003cstrong\u003eHELLO!\u003c/strong\u003e\u003cspan\u003eworld...\u003c/span\u003e\u003c/p\u003e\n```\n\n##### `createEventHandler(mapping: any, initialValue: any): Function`\n\nCreates 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,\n\n```js\nimport { h, render } from 'yolk'\n\nfunction MyComponent ({createEventHandler}) {\n  // create an event handler\n  const handleClick = createEventHandler()\n\n  // use event handler to count the number of clicks\n  const numberOfClicks =\n    handleClick.scan((acc, ev) =\u003e acc + 1, 0).startWith(0)\n\n  // create an element that displays the number of clicks\n  // and a button to increment it\n  return (\n    \u003cdiv\u003e\n      \u003cspan\u003eNumber of clicks: {numberOfClicks}\u003c/span\u003e\n      \u003cbutton onClick={handleClick}\u003eClick me!\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\nAlternatively, we could have written,\n\n```js\nimport { h, render } from 'yolk'\n\nfunction MyComponent ({createEventHandler}) {\n  // map all events to 1, and emit a value of 0 first\n  const handleClick = createEventHandler(1, 0)\n\n  const numberOfClicks =\n    handleClick.scan((acc, inc) =\u003e acc + inc, 0)\n\n  return (\n    \u003cdiv\u003e\n      \u003cspan\u003eNumber of clicks: {numberOfClicks}\u003c/span\u003e\n      \u003cbutton onClick={handleClick}\u003eClick me!\u003c/button\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\nIf the first argument of createEventHandler is a function, it will be invoked with the event as the first argument.\n\nSubscriptions to event handlers are automatically cleaned up when the component is unmounted.\n\n### Top Level API\n\n##### `render(instance: YolkElement, node: HTMLElement): void`\n\nRenders an instance of a YolkComponent inside of an HTMLElement.\n\n```js\nimport { render } from 'yolk'\nrender(\u003cspan\u003eHello World!\u003c/span\u003e, document.querySelector(`#container`))\n```\n\n##### `h(component: string|Function , [props: Object\u003cany\u003e], [...children: Array\u003cany\u003e]): YolkElement`\n\nIf you prefer hyperscript over JSX, Yolk exposes a function `h` which can be used to write your components with hyperscript.\n`h` also parses tags for brevity. For example, `p.my-class` will append a `my-class` class to a `p` tag, `#some-id` will\nappend a `some-id` id to a `div` tag.\n\n```js\nimport { h } from 'yolk'\n\nfunction MyComponent ({createEventHandler}) {\n  const handleClick = createEventHandler()\n\n  const numberOfClicks =\n    handleClick.scan((acc, ev) =\u003e acc + 1, 0).startWith(0)\n\n  return h(`.my-counter-component`, {},\n    h(`span#counter`, {}, `Number of clicks: `, numberOfClicks),\n    h(`button#clicker`, {onClick: handleClick}, `Click me!`)\n  )\n}\n```\n\nSee [#using-jsx](Using JSX) for how to write Yolk components with JSX.\n\n## Using JSX\n\nIt is highly suggested that you write Yolk with JSX. This is achieved using the [Babel transpiler](http://babeljs.io/) (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`.\n\nRun:\n\n```sh\nnpm i --save-dev babel-cli babel-plugin-transform-react-jsx\n```\n\n`.babelrc`:\n\n```json\n{\n  \"plugins\": [\n    [\"transform-react-jsx\", {\"pragma\": \"h\"}]\n  ]\n}\n```\n\nThen anywhere you use JSX it will be transformed into plain JavaScript. For example this,\n\n```js\n\u003cp\u003eMy JSX\u003c/p\u003e\n```\n\nTurns into,\n\n```js\nh(\n  \"p\",\n  null,\n  \"My JSX\"\n);\n```\n\nWithout this pragma, Babel will assume that you mean to write JSX for React and you will receive `React is undefined` errors.\n\nIf you want to additionally transpile ES2015 code into ES5 code you should install and use `babel-preset-es2015`:\n\n```json\n{\n  \"presets\": [\"es2015\"],\n  \"plugins\": [\n    [\"transform-react-jsx\", {\"pragma\": \"h\"}]\n  ]\n}\n```\n\nSee [`yolk-todomvc`](https://github.com/yolkjs/yolk-todomvc) for a complete working example.\n\n## Supported Events\n\nYolk supports the following list of standard browser events,\n\n```\nonAbort onBlur onCancel onCanPlay onCanPlayThrough onChange onClick\nonCompositionStart onCompositionUpdate onCompositionEnd onContextMenu onCopy\nonCueChange onCut onDblClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver\nonDragStart onDrop onDurationChange onEmptied onEnded onEncypted onError onFocus onInput\nonInvalid onKeyDown onKeyPress onKeyUp onLoad onLoadedData onLoadedMetaData onLoadStart\nonMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp\nonPaste onPause onPlay onPlaying onProgress onRateChange onReset onResize onScroll onSearch\nonSeeked onSeeking onSelect onShow onStalled onSubmit onSuspend onTimeUpdate onTouchCancel\nonTouchEnd onTouchMove onTouchStart onToggle onVolumeChange onWaiting onWheel\n```\n\nIn addition, Yolk supports the following custom browser events,\n\n```\nonMount onUnmount\n```\n\n## Supported Attributes\n\nYolk supports the following list of standard element attributes,\n\n```\naccept acceptCharset accessKey action align alt async autoComplete autoFocus autoPlay\nautoSave bgColor border cite className color colSpan content\ncontentEditable coords default defer dir dirName draggable dropZone\nencType for headers height hidden href hrefLang httpEquiv icon id isMap\nitemProp keyType kind label lang max method min name noValidate open\noptimum pattern ping placeholder poster preload radioGroup rel\nrequired reversed rowSpan sandbox scope span spellCheck src srcLang start\nstep style summary tabIndex target title type useMap wrap allowFullScreen\nallowTransparency capture charset challenge cols contextMenu dateTime disabled form\nformAction formEncType formMethod formTarget frameBorder inputMode is list manifest\nmaxLength media minLength role rows seamless size sizes srcSet width checked\ncontrols loop multiple readOnly selected srcDoc value\n```\n\n## Setup\n\nTo install Yolk, simply include it in your `package.json`,\n\n```\nnpm install yolk@^1.0.0-beta --save\n```\n","funding_links":[],"categories":["Projects","JavaScript","others","Libraries Built with RxJS","Client-side"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarbles%2Fyolk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgarbles%2Fyolk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgarbles%2Fyolk/lists"}