{"_id":"0ui","_rev":"6-ca03f269df98e1af9c80f2f801a32d1a","name":"0ui","dist-tags":{"latest":"1.2.0"},"versions":{"1.0.0":{"name":"0ui","version":"1.0.0","author":{"name":"Roman Liutikov"},"license":"MIT","_id":"0ui@1.0.0","maintainers":[{"name":"roman01la","email":"roman01la@romanliutikov.com"}],"dist":{"shasum":"528d3f53602eb960074e75cde97250caa066c3af","tarball":"https://registry.npmjs.org/0ui/-/0ui-1.0.0.tgz","fileCount":8,"integrity":"sha512-AdorVTmz4yQLp5UT+KvaO0BTaxD5mQER/Hv+re/33KIronAKKY30t/LJU2NrhLhIhTGwB/FDzC8pZXcJ0g6IRg==","signatures":[{"sig":"MEUCIQCMVZ+rUUcCJEqxIeDum08o90XJW/MNNe2JVOe8h6K1HAIgGoKjoMd/OwwhXlTyGHr6aL780quRAZE/F5NI2bcU4k4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":7007},"gitHead":"6b481481f6bc17368527872b25441ccf66f45bc7","scripts":{"build:example":"webpack --config ./example/webpack.config.js --mode=production"},"_npmUser":{"name":"roman01la","email":"roman01la@romanliutikov.com"},"_npmVersion":"5.6.0","description":"A set of utilities for building UIs with React","directories":{},"_nodeVersion":"8.7.0","dependencies":{"imtbl":"^1.0.0","react":"^16.2.0"},"_hasShrinkwrap":false,"devDependencies":{"webpack":"^4.2.0","react-dom":"^16.2.0","babel-core":"^6.26.0","webpack-cli":"^2.0.13","babel-loader":"^7.1.4","babel-preset-react":"^6.24.1","babel-preset-stage-2":"^6.24.1"},"_npmOperationalInternal":{"tmp":"tmp/0ui_1.0.0_1522016650479_0.5443336544213373","host":"s3://npm-registry-packages"}},"1.1.0":{"name":"0ui","version":"1.1.0","author":{"name":"Roman Liutikov"},"license":"MIT","_id":"0ui@1.1.0","maintainers":[{"name":"roman01la","email":"roman01la@romanliutikov.com"}],"dist":{"shasum":"301695712aca1dcab1a22ccbad91d387cd9b1845","tarball":"https://registry.npmjs.org/0ui/-/0ui-1.1.0.tgz","fileCount":11,"integrity":"sha512-r2Omvc5p5gdz/2IcU2UVBZ+gXY/yFI97VFsyQ2+/2SU1VpLacDztcjj4Fw2Bg6eRloP5k4OvfCg/PftsEXWTog==","signatures":[{"sig":"MEQCIA21yxxu0C4z+lnjdBjX1V82c7PRBxJa/7R2MO2FWrHZAiAoHJ+K7XKNosj0B1+MhBWACMlziomUobTy8ssL1ys3OQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":18475},"gitHead":"5c3776472b77f601c0b2d125ad4d128dd6979d70","scripts":{"build":"webpack --config webpack.config.js --mode=production","build:example":"webpack --config ./example/webpack.config.js --mode=development --watch"},"_npmUser":{"name":"roman01la","email":"roman01la@romanliutikov.com"},"_npmVersion":"5.6.0","description":"A set of utilities for building UIs with React","directories":{},"_nodeVersion":"8.7.0","dependencies":{"imtbl":"^1.0.0","react":"^16.2.0"},"_hasShrinkwrap":false,"devDependencies":{"webpack":"^4.2.0","react-dom":"^16.2.0","babel-core":"^6.26.0","webpack-cli":"^2.0.13","babel-loader":"^7.1.4","babel-preset-react":"^6.24.1","babel-preset-stage-2":"^6.24.1"},"_npmOperationalInternal":{"tmp":"tmp/0ui_1.1.0_1522063676827_0.7435922069520879","host":"s3://npm-registry-packages"}},"1.2.0":{"name":"0ui","version":"1.2.0","author":{"name":"Roman Liutikov"},"license":"MIT","_id":"0ui@1.2.0","maintainers":[{"name":"roman01la","email":"roman01la@romanliutikov.com"}],"dist":{"shasum":"90c5f811cdb40526c203837b9f704b93ffa737c6","tarball":"https://registry.npmjs.org/0ui/-/0ui-1.2.0.tgz","fileCount":17,"integrity":"sha512-C+iXu/CtX2BCdxd8wRKfV+6CKolVPlWr7LqvyOQpXgNABIQ7iv3AkUXUbWYDl7frWtgSoDA2YouIRYyfnmFmIA==","signatures":[{"sig":"MEQCIDPXLqlQgJyIB4kiBElftByv/OkuktQ3hzjrgBQ00SLVAiAwF622sM0M7HnSXzZQv+PsdtvJE50rvsj8QTf6VTFBYA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":23308},"gitHead":"6f7093ee04b7e3f9ec5fbc5b5bab1d0ef78869b5","scripts":{"test":"jest ./test/*.js","build":"webpack --config webpack.config.js --mode=production","build:example":"webpack --config ./example/webpack.config.js --mode=development --watch"},"_npmUser":{"name":"roman01la","email":"roman01la@romanliutikov.com"},"_npmVersion":"5.6.0","description":"A set of utilities for building UIs with React","directories":{},"_nodeVersion":"8.7.0","dependencies":{"imtbl":"^1.0.0","react":"^16.2.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^22.4.3","webpack":"^4.2.0","react-dom":"^16.2.0","babel-core":"^6.26.0","webpack-cli":"^2.0.13","babel-loader":"^7.1.4","babel-preset-react":"^6.24.1","babel-preset-stage-2":"^6.24.1"},"_npmOperationalInternal":{"tmp":"tmp/0ui_1.2.0_1522080767367_0.21700876535777947","host":"s3://npm-registry-packages"}}},"time":{"created":"2018-03-25T22:24:10.479Z","modified":"2025-05-19T19:04:20.197Z","1.0.0":"2018-03-25T22:24:10.567Z","1.1.0":"2018-03-26T11:27:56.888Z","1.2.0":"2018-03-26T16:12:47.468Z"},"author":{"name":"Roman Liutikov"},"license":"MIT","description":"A set of utilities for building UIs with React","maintainers":[{"email":"roman01la@romanliutikov.com","name":"romanliutikov"}],"readme":"_A set of utilities for building UIs with React_\n\n[Demo](https://jsfiddle.net/qrtzgju2/5/)\n\nv1.2.0\n\n```\nnpm i 0ui\n```\n\nSee an example of how everything is used together in `example/src/index.js`\n\n## UMD build\n\n```html\n<script src=\"https://unpkg.com/0ui/dist/0ui.umd.js\"></script>\n```\n\n## core lib\n\n`lib/core.js`\n\n_Random utilities_\n\n### Stupid pattern matching\n\n_More like a shorthand for `switch/case`_\n\n```js\nimport { match } from \"0ui/lib/core\";\n\nmatch(\"loading\")({\n  loading: () => console.log(\"Loading\"),\n  error: () => console.log(\"Error\")\n});\n// \"Error\"\n```\n\n## imtbl\n\nImmutable style data manipulation for plain JavaScript objects, see [imtbl](https://github.com/roman01la/imtbl) lib.\n\n## State\n\n`lib/state.js`\n\n### State object\n\n_Independent state object_\n\n```js\nimport State from \"0ui/lib/state\";\n\nconst state = State.create(0);\n\nstate.addWatch(\"key\", (key, state, prevVal, nextVal) => {\n  console.log(prevVal, nextVal);\n});\n\nstate.swap(val => val + 1); // 0 1\n```\n\n## Derived state\n\n`lib/derived-state.js`\n\n_Derives state -> state' with a function and propagates updates from state -> state'_\n\n```js\nimport State from \"0ui/lib/state\";\nimport DerivedState from \"0ui/lib/derived-state\";\n\nconst bucket = State.create({\n  items: [\n    {\n      price: 104.5\n    },\n    {\n      price: 78.2\n    }\n  ]\n});\n\nconst bucketPrice = DerivedState.create(bucket, ({ items }) =>\n  items.reduce((sum, { price }) => sum + price, 0)\n);\n\nbucketPrice.state; // 182.7\n\nbucket.swap(removeFirstItem);\n\nbucketPrice.state; // 178.2\n```\n\n## Multimethod\n\n`lib/multimethod.js`\n\n> Multiple dispatch or multimethods is a feature of some programming languages in which a function or method can be dynamically dispatched based on the run-time (dynamic) type or, in the more general case some other attribute, of more than one of its arguments. [Wikipedia](https://en.wikipedia.org/wiki/Multiple_dispatch)\n\n```js\nimport MultiMethod from \"0ui/lib/multimethod\";\n\nconst toJSON = MultiMethod.create(v => {\n  if (Array.isArray(v)) {\n    return \"array\";\n  } else {\n    return typeof v;\n  }\n});\n\ntoJSON.addMethod(\"string\", v => JSON.stringify(v));\n\ntoJSON.addMethod(\"number\", v => v.toString());\n\ntoJSON.addMethod(\"array\", arr => {\n  const jsonArr = arr.map(v => toJSON.dispatch(v)).join(\", \");\n  return `[${jsonArr}]`;\n});\n\ntoJSON.addMethod(\"object\", o => {\n  const jsonObj = Object.entries(o)\n    .map(([k, v]) => toJSON.dispatch(k) + \":\" + toJSON.dispatch(v))\n    .join(\", \");\n  return `{${jsonObj}}`;\n});\n\ntoJSON.dispatch({\n  items: [1, \"two\"]\n});\n// {\"items\":[1, \"two\"]}\n```\n\n## UI\n\n`lib/ui.js`\n\n_React Component API wrapper. Subscribes to multiple State objects._\n\n```js\nimport { createComponent } from \"0ui/lib/ui\";\nimport State from \"0ui/lib/state\";\n\nconst Counter = createComponent({\n  states: {\n    count: State.create(0) // local state\n  },\n  render(states, props) {\n    const { count } = states;\n\n    return (\n      <div>\n        <button onClick={() => count.swap(v => v - 1)}>-</button>\n        <span>{count.state}</span>\n        <button onClick={() => count.swap(v => v + 1)}>+</button>\n      </div>\n    );\n  }\n});\n```\n","readmeFilename":"README.md"}