{"_id":"1ch","_rev":"6-c6bb0ae957a3b17b22f3e4b9c1055dbf","name":"1ch","dist-tags":{"latest":"0.6.0"},"versions":{"0.1.0":{"name":"1ch","version":"0.1.0","author":{"url":"https://seva.dev","name":"Seva Maltsev","email":"me@seva.dev"},"license":"MIT","_id":"1ch@0.1.0","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"dist":{"shasum":"941d3e19584ce0bb7d5de6bd416327673ba44888","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.1.0.tgz","fileCount":6,"integrity":"sha512-VU/e+ZwFa2AJoLiZ1zl/JIvAuiCHci/0BhwZoeVWzakmXUDAaCDrHn+YOvFVc6UyXmHJTzDihMsWz8/mV20e1Q==","signatures":[{"sig":"MEUCIQDg30bpMPPjxXb6QZe4znyyzjvktPbqgGl/sWKFuETUTAIgM4PMREUYRNBN7sgOdy8uiGK53SYftbe1tdin/XhmVWM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":350408},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"gitHead":"76ca89ea65ac06de55f0f8ddeb9aa34e3887b614","scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","start":"NODE_ENV=production bun demo/server.ts","typecheck":"bun x tsc -p tsconfig.json","build:demo":"bun build ./demo/index.html --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --env='BUN_PUBLIC_*'","prepublishOnly":"npm run build"},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"repository":{"url":"git+https://github.com/TwoAbove/1ch.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal UI components for React","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.16.0","dependencies":{"react-reconciler":"^0.33.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","react":"^19","react-dom":"^19","@types/bun":"latest","typescript":"^5","@types/react":"^19","@types/react-dom":"^19","@types/react-reconciler":"^0.33.0"},"peerDependencies":{"react":"^18 || ^19","react-dom":"^18 || ^19"},"_npmOperationalInternal":{"tmp":"tmp/1ch_0.1.0_1770778678058_0.6331978059466903","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"1ch","version":"0.2.0","author":{"url":"https://seva.dev","name":"Seva Maltsev","email":"me@seva.dev"},"license":"MIT","_id":"1ch@0.2.0","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"dist":{"shasum":"caad9d6ba64003fa7ed70f39f0b965d07ff47bd4","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.2.0.tgz","fileCount":6,"integrity":"sha512-x/RCBqQM/V0IXANLUUH2t4T4VNOp9ZwLU8jc8yJRPxwWX29p+rNKzknd3dYYAImZ5wFyTo0Gmtf2ujcvLWNNTw==","signatures":[{"sig":"MEUCIQDtdRgHyKfWnxvH1jrP1EPXb8KKBQ3AsVWGlxmlCn6YCAIgcrJxhwsVH0xVYzW2ysKhPvztNUETrxi3e4mn6ZLocCI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":351099},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"gitHead":"09188d8d88ef1a168897e74aed0998941c118465","scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","start":"NODE_ENV=production bun demo/server.ts","typecheck":"bun x tsc -p tsconfig.json","build:demo":"bun build ./demo/main.tsx --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --env='BUN_PUBLIC_*' --entry-naming=main.[ext] --asset-naming=assets/[name]-[hash].[ext] && sed -e 's|./main.tsx|./main.js|' -e 's|</head>|<link rel=\"stylesheet\" href=\"./main.css\"></head>|' -e '/react-scan/d' demo/index.html > dist-demo/index.html","prepublishOnly":"npm run build"},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"repository":{"url":"git+https://github.com/TwoAbove/1ch.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal UI components for React","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.16.0","dependencies":{"react-reconciler":"^0.33.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","react":"^19","react-dom":"^19","@types/bun":"latest","typescript":"^5","@types/react":"^19","@types/react-dom":"^19","@types/react-reconciler":"^0.33.0"},"peerDependencies":{"react":"^18 || ^19","react-dom":"^18 || ^19"},"_npmOperationalInternal":{"tmp":"tmp/1ch_0.2.0_1770905773056_0.04096464300297753","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"1ch","version":"0.3.0","author":{"url":"https://seva.dev","name":"Seva Maltsev","email":"me@seva.dev"},"license":"MIT","_id":"1ch@0.3.0","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"dist":{"shasum":"e8bdf37838e7b53643c98def1e049553f7591018","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.3.0.tgz","fileCount":6,"integrity":"sha512-zdEOntrUhYE6Bf41u8BouSYIQxU2G01//+tw18AX0dBM1AqNDeuVjVdoxa3nPaN1pwQKqj6BbQu1rLs/081Lqw==","signatures":[{"sig":"MEUCIQCzASsr8noLTux6UKyA3oWRU9DyPzrxU8FcaBPWDqkJGgIgZeFYL1uVR1lJc17dVV6TEklAXeHrUCVPo1upKugk+Ac=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":421839},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"gitHead":"364b7388d29af6b7a6da2ddbb919be0d65cf3cb9","scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","start":"NODE_ENV=production bun demo/server.ts","typecheck":"bun x tsc -p tsconfig.json","build:demo":"bun build ./demo/main.tsx ./demo/docs-main.tsx --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --env='BUN_PUBLIC_*' --entry-naming=[name].[ext] --asset-naming=assets/[name]-[hash].[ext] && sed -e 's|./main.tsx|./main.js|' -e 's|</head>|<link rel=\"stylesheet\" href=\"./main.css\"></head>|' -e '/react-scan/d' demo/index.html > dist-demo/index.html && sed -e 's|./docs-main.tsx|./docs-main.js|' -e 's|</head>|<link rel=\"stylesheet\" href=\"./docs-main.css\"></head>|' demo/docs.html > dist-demo/docs.html","prepublishOnly":"npm run build"},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"repository":{"url":"git+https://github.com/TwoAbove/1ch.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal UI components for React","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.16.0","dependencies":{"diff":"^8.0.3","react-reconciler":"^0.33.0"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","react":"^19","react-dom":"^19","@types/bun":"latest","typescript":"^5","@types/diff":"^8.0.0","@types/react":"^19","@types/react-dom":"^19","@types/react-reconciler":"^0.33.0"},"peerDependencies":{"react":"^18 || ^19","react-dom":"^18 || ^19"},"_npmOperationalInternal":{"tmp":"tmp/1ch_0.3.0_1771033100014_0.20207596695731578","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"1ch","version":"0.4.0","author":{"url":"https://seva.dev","name":"Seva Maltsev","email":"me@seva.dev"},"license":"MIT","_id":"1ch@0.4.0","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"dist":{"shasum":"3116e1c661d950cfe5ad9186ec345fd3ce97527a","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.4.0.tgz","fileCount":6,"integrity":"sha512-zF5kKAAlok/+hyTmHOI0gofDKfo8HYZFvg4BMwk5/6OfC0xeyn/c0sIJCHsEQ+gKxguEW9xBVdu2KfWn42bf2g==","signatures":[{"sig":"MEYCIQC1ulE6FdNe4xU1kp6NYGnOPVscq9NruA+u+bTiPK1ZWgIhANKQQ9j9kf836OAqLhnOGFKzRXBHh1iaTHwLGm1J+6ic","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":349955},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"gitHead":"ceb3ebc36b69380d421295f0c1cb09bc045aae33","scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","start":"NODE_ENV=production bun demo/server.ts","typecheck":"bun x tsc -p tsconfig.json","build:demo":"rm -rf dist-demo && bun build ./demo/main.ts ./demo/agnostic.ts ./demo/docs.ts ./demo/repl.ts --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --entry-naming=[name].[ext] --asset-naming=assets/[name]-[hash].[ext] && sed -e 's|./main.ts|./main.js|' demo/index.html > dist-demo/index.html && sed -e 's|./agnostic.ts|./agnostic.js|' demo/agnostic.html > dist-demo/agnostic.html && sed -e 's|./docs.ts|./docs.js|' demo/docs.html > dist-demo/docs.html && sed -e 's|./repl.ts|./repl.js|' demo/repl.html > dist-demo/repl.html","prepublishOnly":"npm run build"},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"repository":{"url":"git+https://github.com/TwoAbove/1ch.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal UI rendered to fixed character grids via a custom HTML element","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.16.0","dependencies":{},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","@types/bun":"latest","typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/1ch_0.4.0_1771293774442_0.19649110743196352","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"1ch","version":"0.5.0","author":{"url":"https://seva.dev","name":"Seva Maltsev","email":"me@seva.dev"},"license":"MIT","_id":"1ch@0.5.0","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"dist":{"shasum":"edfc58cd5b237128ac9c77147ba42599c8371f27","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.5.0.tgz","fileCount":6,"integrity":"sha512-9EkpDE67n5FNfoPJK2Ay6+yRqhIePEIBtj+C3NbFBEKhU8uZ4CPqFNKW5z4zfAE3ufqy7w8XqG6ySPsbEnqqDg==","signatures":[{"sig":"MEUCIQD2S/65Ft6qq1rrU/FJTPoVNPCCQKC9vrosfpYH9ncQtwIgSdpYJ8hq+6EhbU0sqsKyLKfGhhtEX4pqCFVruNENzN4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":366572},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"gitHead":"652f1b13b193e4c6c8d7ba2afa166a1cc13640f9","scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","start":"NODE_ENV=production bun demo/server.ts","typecheck":"bun x tsc -p tsconfig.json","build:demo":"rm -rf dist-demo && bun build ./demo/main.ts ./demo/agnostic.ts ./demo/docs.ts ./demo/repl.ts --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --entry-naming=[name].[ext] --asset-naming=assets/[name]-[hash].[ext] && sed -e 's|./main.ts|./main.js|' demo/index.html > dist-demo/index.html && sed -e 's|./agnostic.ts|./agnostic.js|' demo/agnostic.html > dist-demo/agnostic.html && sed -e 's|./docs.ts|./docs.js|' demo/docs.html > dist-demo/docs.html && sed -e 's|./repl.ts|./repl.js|' demo/repl.html > dist-demo/repl.html","prepublishOnly":"npm run build"},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"repository":{"url":"git+https://github.com/TwoAbove/1ch.git","type":"git"},"_npmVersion":"10.9.2","description":"Terminal UI rendered to fixed character grids via a custom HTML element","directories":{},"sideEffects":["*.css"],"_nodeVersion":"22.16.0","dependencies":{},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8","@types/bun":"latest","typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/1ch_0.5.0_1771644729579_0.7798442584543137","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"1ch","version":"0.6.0","description":"Terminal UI rendered to fixed character grids via a custom HTML element","author":{"name":"Seva Maltsev","email":"me@seva.dev","url":"https://seva.dev"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/TwoAbove/1ch.git"},"homepage":"https://github.com/TwoAbove/1ch#readme","bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"type":"module","exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./style.css":{"default":"./dist/style.css"}},"sideEffects":["*.css"],"scripts":{"dev":"bun --hot demo/server.ts","build":"tsup","build:demo":"rm -rf dist-demo && bun build ./demo/main.ts ./demo/agnostic.ts ./demo/docs.ts ./demo/repl.ts --outdir=dist-demo --sourcemap --target=browser --minify --define:process.env.NODE_ENV='\"production\"' --entry-naming=[name].[ext] --asset-naming=assets/[name]-[hash].[ext] && sed -e 's|./main.ts|./main.js|' demo/index.html > dist-demo/index.html && sed -e 's|./agnostic.ts|./agnostic.js|' demo/agnostic.html > dist-demo/agnostic.html && sed -e 's|./docs.ts|./docs.js|' demo/docs.html > dist-demo/docs.html && sed -e 's|./repl.ts|./repl.js|' demo/repl.html > dist-demo/repl.html","typecheck":"bun x tsc -p tsconfig.json","start":"NODE_ENV=production bun demo/server.ts","prepublishOnly":"npm run build"},"dependencies":{},"devDependencies":{"@types/bun":"latest","tsup":"^8","typescript":"^5"},"_id":"1ch@0.6.0","gitHead":"73b311c92c486b59bdb70bebdb525b4bf317b8a3","_nodeVersion":"22.16.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-jHlDy9k5udShbq7nb9mPUi1o0pg3GNbdjwZW5vm0f2IF+8QsHRpqZ/7EbfnTwneFRk/3Kuxrpj/r0smP1JrO4g==","shasum":"5440eedf8e0a2a554c66b12061f438fc7ae8acf1","tarball":"https://registry.npmjs.org/1ch/-/1ch-0.6.0.tgz","fileCount":6,"unpackedSize":380091,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBX5vMhzoWgFFSAdxEStwBZY3YDa9IkVHh0wA/XGC/0/AiEAmyGtPGPfK1dHtYTa+ndeaDuEtKWcysBkInfeSiUsG58="}]},"_npmUser":{"name":"twoabove","email":"sevamaltsev@gmail.com"},"directories":{},"maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/1ch_0.6.0_1773277693285_0.33510139459030786"},"_hasShrinkwrap":false}},"time":{"created":"2026-02-11T02:57:57.946Z","modified":"2026-03-12T01:08:13.576Z","0.1.0":"2026-02-11T02:57:58.268Z","0.2.0":"2026-02-12T14:16:13.265Z","0.3.0":"2026-02-14T01:38:20.166Z","0.4.0":"2026-02-17T02:02:54.631Z","0.5.0":"2026-02-21T03:32:09.827Z","0.6.0":"2026-03-12T01:08:13.469Z"},"bugs":{"url":"https://github.com/TwoAbove/1ch/issues"},"author":{"name":"Seva Maltsev","email":"me@seva.dev","url":"https://seva.dev"},"license":"MIT","homepage":"https://github.com/TwoAbove/1ch#readme","repository":{"type":"git","url":"git+https://github.com/TwoAbove/1ch.git"},"description":"Terminal UI rendered to fixed character grids via a custom HTML element","maintainers":[{"name":"twoabove","email":"sevamaltsev@gmail.com"}],"readme":"# 1ch\n\nCharacter-grid UI that runs in the browser. One `<term-ui>` element turns semantic HTML into a fixed-width terminal render -- boxes, tables, charts, progress bars, status lines -- all from standard tags.\n\n![1ch](https://raw.githubusercontent.com/twoabove/1ch/main/demo/assets/demo.png)\n\n[Playground](https://1ch.app/repl) &middot; [Docs](https://1ch.app/docs) &middot; [npm](https://www.npmjs.com/package/1ch)\n\n## Install\n\n```bash\nnpm install 1ch\n```\n\n## Use\n\nRegister once, then forget about it:\n\n```ts\nimport { registerTermUIElement } from \"1ch\";\nimport \"1ch/style.css\";\nregisterTermUIElement();\n```\n\nDrop it in with your preferred reactivity provider:\n\n```tsx\nfunction DeployPanel() {\n  const [build, setBuild] = useState(0);\n  const { metrics } = useMetrics();\n\n  return (\n    <term-ui width=\"60\" mode=\"dark\">\n      <section gap=\"1\">\n        <article title=\"deploy v2.4.1\">\n          <progress label=\"build\" value={build} max=\"100\"></progress>\n          <progress label=\"tests\" value=\"94\" max=\"100\"></progress>\n        </article>\n        <figure height=\"4\" fill>\n          {metrics.map(v => <data value={v} />)}\n        </figure>\n        <nav>\n          <button onClick={() => deploy()}>deploy</button>\n          <button onClick={() => rollback()}>rollback</button>\n        </nav>\n        <footer left=\" healthy\" right=\"64s ago \"></footer>\n      </section>\n    </term-ui>\n  );\n}\n```\n\n`<article>` is a box. `<progress>` is a bar. `<figure>` is a chart. `<nav>` lays out horizontally. `<footer>` is a status line. No wrapper components, no special syntax -- just HTML that happens to render as a terminal.\n\n## Why\n\nTables draw with `│─┼`. Progress bars fill with `████░░░░`. Buttons are `[ deploy ]`. Everything snaps to a character grid and it just looks *right*.\n\nWho needs designs for internal tools when a character grid gives you a clean UI for free? Dashboards, admin panels, monitoring views, CLI-style apps -- just write the HTML and it looks like something you'd actually want to use.\n\nYour CSS still works -- `display: grid`, `gap`, `grid-template-columns` get picked up from `getComputedStyle` and mapped to the grid. It's a web component, so React, Vue, Svelte, htmx, plain HTML -- whatever. `onClick` on a `<button>` fires like you'd expect.\n\nZero dependencies. Also does markdown and JSON (`source-format=\"markdown\"` on the element).\n\n## Quick reference\n\n| Element | Becomes |\n|---------|---------|\n| `<article title=\"X\">` | box |\n| `<figure>` | chart (text content, `<data>` children, or `values`) |\n| `<footer left=\"X\" right=\"Y\">` | status bar |\n| `<nav>` | horizontal stack |\n| `<progress>` | bar |\n| `<hr>` / `<hr label=\"X\">` | separator / divider |\n| `<pre>` | code block |\n| `<table>` | table |\n| `<section>`, `<div>` | container (layout from CSS) |\n\nNeed custom behavior? Register your own compiler via `registerHtmlTagCompiler()`. Full details in the [docs](https://1ch.app/docs).\n\n## License\n\nMIT\n","readmeFilename":"README.md"}