{"_id":"@bananacool467/ui-tools","_rev":"33-c6b112a84f3bcd631aa2911a6c4b6623","name":"@bananacool467/ui-tools","dist-tags":{"latest":"0.2.2-beta","beta":"0.2.2-beta"},"versions":{"0.1.0-beta":{"name":"@bananacool467/ui-tools","version":"0.1.0-beta","keywords":["ui"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.0-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"dist":{"shasum":"6d593a92af1926aff940a9bfbcb8fca3c7ef9f38","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.0-beta.tgz","fileCount":168,"integrity":"sha512-ZNObbBdMGSX08OZRSY/Q/D6p/QOL2NKyl0hcqxUiNxd95OpB6ZmiBcN5C5Njg34miRXIGihWP2tl+qm5p+LQUw==","signatures":[{"sig":"MEQCIBxxXfDqZKnrzwFIX4z+bLGPmie+z0Q+gkAEOe5LN+oRAiBkfqW6MRzUVbxRaw8CNK+5AHpGKXZiuCxX35PEpDr9bA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":579157},"main":"dist/index.js","types":"./dist/index.d.ts","gitHead":"fd0ab3cdb3ead3f13888e38003fec5e6a1a8d134","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","typescript":"^7.0.2","@types/react":"^19.2.17","@xterm/xterm":"^6.0.0","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12","@types/react-dom":"^19.2.3","@xterm/addon-fit":"^0.11.0","@bananacool467/authtics-host":"^0.1.7"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.0-beta_1784778401221_0.3781638200625428","host":"s3://npm-registry-packages-npm-production"}},"0.1.1-beta":{"name":"@bananacool467/ui-tools","version":"0.1.1-beta","keywords":["ui"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.1-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"dist":{"shasum":"38551beb7c4eb8eaaacd1f996ba79f99be2e902e","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.1-beta.tgz","fileCount":166,"integrity":"sha512-WOscFd7azDYrf/asSzvoVlYbRW7LRqBfb78FQiYl4cZbWS+L5KJ1gIIe6o8O+3w9aWmm4cduh+2O9Q4Lrx2kcQ==","signatures":[{"sig":"MEUCIQCpMZ5GCmMXvm95KRfCLklpSFOdMPMfLPWniyd6i0+OowIgFZv4mGCoZx9sB5CJmkRcTb26832folP8MWxPiNXlPKg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":324583},"main":"dist/index.js","types":"./dist/index.d.ts","gitHead":"e58c03e43989bbce9316e1f5a67383b10af585ac","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","typescript":"^7.0.2","@types/react":"^19.2.17","@xterm/xterm":"^6.0.0","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12","@types/react-dom":"^19.2.3","@xterm/addon-fit":"^0.11.0","@bananacool467/authtics-host":"^0.1.7"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"@types/node":"^26.1.1"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.1-beta_1784778836329_0.5740545771280743","host":"s3://npm-registry-packages-npm-production"}},"0.1.2-beta":{"name":"@bananacool467/ui-tools","version":"0.1.2-beta","keywords":["ui"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.2-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"dist":{"shasum":"dc0199a04584cbcdde3e226a43972f9f7f394ba3","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.2-beta.tgz","fileCount":166,"integrity":"sha512-z83iQ5vMnFeILm3ydgLR04t47E62gqlEKxaJrSe9oNj0uBlCqmt9Mobzr0SjqqXeVSrRi8/mbgIBHK4DU9vntg==","signatures":[{"sig":"MEUCIFUNeQHMffH2Pvwk8YLImjBjD9zzprdaMCiQ8tmimmUGAiEA4FZ+NFj7d4385yPxfNJXZjP05RCiy9J7pRjzZmsgr4U=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":324591},"main":"dist/index.js","types":"./dist/index.d.ts","gitHead":"e58c03e43989bbce9316e1f5a67383b10af585ac","scripts":{"test":"echo \"Error: no test specified\" && exit 1","build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.2-beta_1784782311149_0.12850184140408016","host":"s3://npm-registry-packages-npm-production"}},"0.1.3-beta":{"name":"@bananacool467/ui-tools","version":"0.1.3-beta","keywords":["ui","tool","react","typescript","tsx","jsx"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.3-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"dist":{"shasum":"81a69408ac23015954a37540204084548e0d212f","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.3-beta.tgz","fileCount":168,"integrity":"sha512-oU2w5DulAK2zvYezPL9Dg1qi3o+0d6B+eVkbQ9KQktTSLD1jrnh0ZFndH+TapxZugO6ds62IWDeD9NGoipDDoQ==","signatures":[{"sig":"MEUCIAbYC3vNvk0O+3sLlMvoO2k3Jbd7GYKw7G+U2V7g4dQeAiEA2xE3c822punlSVcBkMinCHldcJDVH8I6RpWNF2h3I4k=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":332794},"main":"dist/index.js","types":"./dist/index.d.ts","gitHead":"d98f299b8510b49c80ca8de6b780332e1aa93f05","scripts":{"build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.3-beta_1784869780119_0.20471933945814813","host":"s3://npm-registry-packages-npm-production"}},"0.1.4-beta":{"name":"@bananacool467/ui-tools","version":"0.1.4-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.4-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"dist":{"shasum":"cea41e8941a97596cf071a028c03e2fd75b85fe4","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.4-beta.tgz","fileCount":166,"integrity":"sha512-31KOBbQini2Mm7wls8qYxCycvJdjEN4nbaRzy72WRCoF0T/WXgxd5gPYBiNT28Y+sCnOWk7kiTE/DbmGF9VxSg==","signatures":[{"sig":"MEUCIQDKWsdRceXQBKC1uHadqtTS//RvYtlv/MXHYE7Q+074OAIgOMpuxRI4ibuK83WHDdsmn92z0c8nCygjxROHWJnBLps=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":325392},"main":"dist/index.js","types":"./dist/index.d.ts","gitHead":"50e327b130422c8cd7f2ce1ab46240b48f0f22f7","scripts":{"build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.4-beta_1784870086826_0.05098835742385521","host":"s3://npm-registry-packages-npm-production"}},"0.1.5-beta":{"name":"@bananacool467/ui-tools","version":"0.1.5-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.5-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"b5d78140ab36b7669c5dbf332d04b232896df69b","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.5-beta.tgz","fileCount":167,"integrity":"sha512-yhz4+XEmste6FgpFAYv+rwtJOcDH3IWxxLgHTVy6swBNkRMkzvxA3IxiSljJ2vwk6MNquZ1n5ISnGQ8Xg4MW8Q==","signatures":[{"sig":"MEYCIQDgmaTJteZsTMSsBXm99qWX+3s/jFC8fR2fylxiQCch0gIhAN//9LpUOgztQIq5WGrA/NSsGXefWMyQF8kydqP0sYYm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":327382},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"8106960212af76a89dbcefae9cb7203bdcf62aa0","scripts":{"build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.5-beta_1784944734305_0.18128587980401623","host":"s3://npm-registry-packages-npm-production"}},"0.1.6-beta":{"name":"@bananacool467/ui-tools","version":"0.1.6-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.6-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"8f0e516b08d6ee796adde58f1c605231976bc562","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.6-beta.tgz","fileCount":227,"integrity":"sha512-tlZzCP6sokP7x5LZ2R8YubsBfGSUVz81BK+XXc8cq72UCcnZ146MrJ0175P3YhW+89/qhP1PeetxXV3mAZkvOw==","signatures":[{"sig":"MEQCIDvMvCiuDZqsYozadbwrXccYm5lj4SB8zgcDfhhAZhZAAiAaj83No1SFasPN+s1F3y0aWySzgBMZkPbSmqqqe8sDyA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":481720},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"244ce8d10dde4154bc3ce06bbfe9f59005f81753","scripts":{"build":"tsc"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.6-beta_1784946412529_0.5610048718592089","host":"s3://npm-registry-packages-npm-production"}},"0.1.7-beta":{"name":"@bananacool467/ui-tools","version":"0.1.7-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.7-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"b20b86e2c0fa539743cfe6d779ffa6386cf11710","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.7-beta.tgz","fileCount":227,"integrity":"sha512-O7m6V5bvbuLPvqhU40F803/XMVVaeAbqDsWXiE9y++Wu1eI0J/WlUr99MaJVeuHk19082ePZ/ZgeZg3LthOgiA==","signatures":[{"sig":"MEUCIArao0hv6K2ewUOazMSgQY9cXecGorkKGsThbJl7YmRVAiEAtBHZwscMOpBObgEVnE6LJK9MFMnWRPmL4vpr1alG3uU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":481221},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"9ee40544629d1bf44d91728cfcbac4456cb5330f","scripts":{"build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.7-beta_1784948203941_0.5218836329095882","host":"s3://npm-registry-packages-npm-production"}},"0.1.8-beta":{"name":"@bananacool467/ui-tools","version":"0.1.8-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.8-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"bb5fbc3be2b092f7be12487198c06fbd268b010f","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.8-beta.tgz","fileCount":239,"integrity":"sha512-t8d76gTb//1DkaxK5jbJFy+N7Q7i66spHyCzwfNEz6fMjOtjBZaDX+Dc6ci2fYGaLhClOhcY780by764Rs5X3w==","signatures":[{"sig":"MEQCICeWzk1KCjfxHN+xT8T/S6z9uzFlMyI7/zRxcKdc/6CRAiBWO1vScIZr+8Ys9hhDy/X+XPcCxB3dXw+Ugu/GZ0X0mg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":497655},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"1bff63f28d5bb20630eca9cad57f0e1fcaf9b99e","scripts":{"build":"tsc && [ -d dist/src ] && mv dist/src/* dist/ && rmdir dist/src || true","setup":"npm i @types/node @types/react @types/react-dom typescript","prepublishOnly":"npm run build"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"deprecated":"Security issue: unauthenticated terminal WebSocket. Upgrade to 0.1.9-beta or newer.","repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"os":"^0.1.2","ws":"^8.21.0","@types/ws":"^8.18.1","child_process":"^1.0.2","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"decomment":"^0.9.5","typescript":"^7.0.2","@types/node":"^26.1.1","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/authtics-host":"^0.1.7"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.8-beta_1785254014997_0.8521873891031133","host":"s3://npm-registry-packages-npm-production"}},"0.1.9-beta":{"name":"@bananacool467/ui-tools","version":"0.1.9-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.1.9-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"df8688b0390c134b641dbf56b7fb4ba58aed0bed","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.1.9-beta.tgz","fileCount":488,"integrity":"sha512-qkbFuSPr33kwubEaANLNqdxaT4o2WLsJpcGjqDXI8/hAJ5ttfyqEOMLvtUsKKJtzwAiydFS32fWEO55R+3MYdw==","signatures":[{"sig":"MEUCIHVFl5CtWW+K1qNAwFGBE2aTWpvwFfsHxU1gO+uEe5XuAiEAj4CK5oG4ktwhBKPinaByB8D4EtU+mDUDKOIATitiLXQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1093762},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"93dec3a4e5ffe1f0fd38e398b8c71ce7b902ebb7","scripts":{"build":"tsc && [ -d dist/src ] && mv dist/src/* dist/ && rmdir dist/src || true","setup":"npm i @types/node @types/react @types/react-dom typescript","prepublishOnly":"npm run build"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements","directories":{},"_nodeVersion":"22.22.0","dependencies":{"ws":"^8.21.0","@types/ws":"^8.18.1","@babel/parser":"^8.0.4","@babel/generator":"^8.0.0","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"eslint":"^10.9.1","@eslint/js":"^10.0.1","typescript":"npm:@typescript/typescript6@^6.0.2","@types/node":"^26.1.1","typescript7":"npm:typescript@^7.0.2","@types/react":"^19.2.17","@types/react-dom":"^19.2.3","@bananacool467/pt":"^0.1.0-beta.4","typescript-eslint":"^8.68.0","@bananacool467/ui-tools":"file:pack&bananacool467:ui-tools","@bananacool467/authtics-host":"^0.2.5"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.1.9-beta_1787794483558_0.46489691184573756","host":"s3://npm-registry-packages-npm-production"}},"0.2.0-beta":{"name":"@bananacool467/ui-tools","version":"0.2.0-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.2.0-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"6a38d7453413ee5f534995ed99a0f926748e2286","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.2.0-beta.tgz","fileCount":488,"integrity":"sha512-3iFEaBzvVsD6dsGrZrkwtQoUS7cexkqXmh+kie/a3QZ0gtB+hMKUyWN3EkEy399pKEx35/U+LOgxWL/yCLZlOw==","signatures":[{"sig":"MEUCIHcPe73psQ6UFMpMyETFp2Ev7kX1jtF41eU9Gtl0clRtAiEArNe0ko0T6mXkf+++CslZ9mb9hudWG3WJVmvF7oulrqc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1107545},"main":"dist/index.js","types":"dist/index.d.ts","gitHead":"3a3b6f2f7a461faa0af16a3bf1034b570585fa8c","scripts":{"build":"tsc && [ -d dist/src ] && mv dist/src/* dist/ && rmdir dist/src || true","setup":"npm i @types/node @types/react @types/react-dom typescript","prepublishOnly":"npm run build"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements + Tools, for frontend and backend","directories":{},"_nodeVersion":"22.22.0","dependencies":{"ws":"^8.21.0","@types/ws":"^8.18.1","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"eslint":"^10.9.1","@eslint/js":"^10.0.1","typescript":"npm:@typescript/typescript6@^6.0.2","@types/node":"^26.1.1","typescript7":"npm:typescript@^7.0.2","@types/react":"^19.2.17","@babel/parser":"^8.0.4","@babel/generator":"^8.0.0","@types/react-dom":"^19.2.3","@bananacool467/pt":"^0.1.0-beta.4","typescript-eslint":"^8.68.0","@bananacool467/ui-tools":"file:pack&bananacool467:ui-tools","@bananacool467/authtics-host":"^0.2.5"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.2.0-beta_1788020290964_0.4362282300956526","host":"s3://npm-registry-packages-npm-production"}},"0.2.1-beta":{"name":"@bananacool467/ui-tools","version":"0.2.1-beta","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements","backend","frontend"],"author":{"name":"bananacool467"},"license":"MIT","_id":"@bananacool467/ui-tools@0.2.1-beta","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"homepage":"https://github.com/bananakitssu/ui-tools#readme","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"bfb4e1f817a218373dbbc55efe31d4f2e0bb901e","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.2.1-beta.tgz","fileCount":496,"integrity":"sha512-83rRSTswcIbuYVpENlSSO53J/WU0bLjbuTr7kXWaIIyl7omuDCv9fAWAmOc5EMkEoaYUILvaN7BsK7mmMqJCkQ==","signatures":[{"sig":"MEUCIF+wroAQgA8UC/TFcxfz5K8//MYTiCcoJGuYiWA4USthAiEAzlbEtdhluJcqpxdUHDZeH1wCgprHQcHWml06SrgAMug=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1170421},"main":"dist/index.js","types":"dist/index.d.ts","exports":{".":"./dist/index.js","./backend":"./dist/backend.js"},"gitHead":"35a6849472cdf9e5182d6bdceefb63873a21d1f4","scripts":{"build":"tsc && [ -d dist/src ] && mv dist/src/* dist/ && rmdir dist/src || true","setup":"npm i @types/node @types/react @types/react-dom typescript","prepublishOnly":"npm run build"},"_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements + Tools, for frontend and backend","directories":{},"_nodeVersion":"22.22.0","dependencies":{"ws":"^8.21.0","@types/ws":"^8.18.1","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"eslint":"^10.9.1","@eslint/js":"^10.0.1","typescript":"npm:@typescript/typescript6@^6.0.2","@types/node":"^26.1.1","typescript7":"npm:typescript@^7.0.2","@types/react":"^19.2.17","@babel/parser":"^8.0.4","@babel/generator":"^8.0.0","@types/react-dom":"^19.2.3","@bananacool467/pt":"^0.1.0-beta.4","typescript-eslint":"^8.68.0","@bananacool467/ui-tools":"file:pack&bananacool467:ui-tools","@bananacool467/authtics-host":"^0.2.5"},"_npmOperationalInternal":{"tmp":"tmp/ui-tools_0.2.1-beta_1788405322208_0.37702190471053654","host":"s3://npm-registry-packages-npm-production"}},"0.2.2-beta":{"_id":"@bananacool467/ui-tools@0.2.2-beta","bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"dist":{"shasum":"474fff6cc3fb473131f5b010b81a41df6a5f89fe","tarball":"https://registry.npmjs.org/@bananacool467/ui-tools/-/ui-tools-0.2.2-beta.tgz","fileCount":257,"integrity":"sha512-c07UuDTdTn82kEALrbN1YVAEyltqiJw1m5jlwHjn5EuBYAJExeQXFrHwQRDXpg7SEc53SUNi+KRFgf019HIRDg==","signatures":[{"sig":"MEYCIQDP3JKCArSI8bkHWHX+w5oo/f9Vfwix7ciYq8CsdBIVJgIhANuYjNywXk44RzRQB447FAx+bkzeMi3EpD8a4DQzZP5k","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQDkKplxFAtLI7laS7NFS1xL4UJ5yOfl2FKDKF4AQZ0eAgIhAPt/l6m4U+uMZCe4gdedrjThPJV4LuZsSrjlZVqZ+3ST"}],"unpackedSize":651378},"main":"dist/index.js","name":"@bananacool467/ui-tools","types":"dist/index.d.ts","author":{"name":"bananacool467"},"exports":{".":"./dist/index.js","./backend":"./dist/backend.js"},"gitHead":"e96ad90e0d2bf76b449cdafdfe57676c05a85b2d","license":"MIT","scripts":{"build":"tsc && [ -d dist/src ] && mv dist/src/* dist/ && rmdir dist/src || true","setup":"npm i @types/node @types/react @types/react-dom typescript","prepublishOnly":"npm run build"},"version":"0.2.2-beta","_npmUser":{"name":"bananacool467","email":"bananacool467@protonmail.com"},"homepage":"https://github.com/bananakitssu/ui-tools#readme","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements","backend","frontend"],"repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"_npmVersion":"10.9.4","description":"UI Elements + Tools, for frontend and backend","directories":{},"maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"_nodeVersion":"22.22.0","dependencies":{"ws":"^8.21.0","@types/ws":"^8.18.1","@lydell/node-pty":"^1.2.0-beta.12"},"publishConfig":{"access":"public","registry":"https://registry.npmjs.org/"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^10.9.1","@eslint/js":"^10.0.1","typescript":"npm:@typescript/typescript6@^6.0.2","@types/node":"^26.1.1","typescript7":"npm:typescript@^7.0.2","@types/react":"^19.2.17","@babel/parser":"^8.0.4","@babel/generator":"^8.0.0","@types/react-dom":"^19.2.3","@bananacool467/pt":"^0.1.0-beta.4","typescript-eslint":"^8.68.0","@bananacool467/ui-tools":"file:pack&bananacool467:ui-tools","@bananacool467/authtics-host":"^0.2.5"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ui-tools_0.2.2-beta_1789843032564_0.9199496724796183"}}},"time":{"created":"2026-07-23T03:46:41.061Z","modified":"2026-09-19T18:37:12.824Z","0.1.0-beta":"2026-07-23T03:46:41.424Z","0.1.1-beta":"2026-07-23T03:53:56.455Z","0.1.2-beta":"2026-07-23T04:51:51.303Z","0.1.3-beta":"2026-07-24T05:09:40.272Z","0.1.4-beta":"2026-07-24T05:14:46.981Z","0.1.5-beta":"2026-07-25T01:58:54.512Z","0.1.6-beta":"2026-07-25T02:26:52.666Z","0.1.7-beta":"2026-07-25T02:56:44.092Z","0.1.8-beta":"2026-07-28T15:53:35.198Z","0.1.9-beta":"2026-08-27T01:34:43.783Z","0.2.0-beta":"2026-08-29T16:18:11.150Z","0.2.1-beta":"2026-09-03T03:15:22.385Z","0.2.2-beta":"2026-09-19T18:37:12.668Z"},"bugs":{"url":"https://github.com/bananakitssu/ui-tools/issues"},"author":{"name":"bananacool467"},"license":"MIT","homepage":"https://github.com/bananakitssu/ui-tools#readme","keywords":["ui","tool","react","typescript","tsx","jsx","ui-tools","ui-components","ui-elements","backend","frontend"],"repository":{"url":"git+https://github.com/bananakitssu/ui-tools.git","type":"git"},"description":"UI Elements + Tools, for frontend and backend","maintainers":[{"name":"bananacool467","email":"bananacool467@protonmail.com"}],"readme":"# UI Tools\n\n<p align=\"center\">\n  <img alt=\"version\" src=\"https://img.shields.io/badge/version-v0.2.2-green?style=for-the-badge\" />\n  <img alt=\"version type\" src=\"https://img.shields.io/badge/version_type-BETA-yellow?style=for-the-badge\" />\n  <img alt=\"license\" src=\"https://img.shields.io/github/license/bananakitssu/ui-tools?style=for-the-badge\" />\n  <img alt=\"downloads\" src=\"https://img.shields.io/npm/dm/@bananacool467/ui-tools?style=for-the-badge\" />\n</p>\n\n<p align=\"center\">\n  <a href=\"https://npmjs.org/package/@bananacool467/ui-tools\"><img alt=\"NPM\" src=\"https://img.shields.io/badge/NPM-@bananacool467%2Fui--tools-red?style=for-the-badge&logo=npm\" /></a>\n  <a href=\"https://github.com/bananakitssu/ui-tools\"><img alt=\"GitHub\" src=\"https://img.shields.io/badge/GitHub-bananakitssu%2Fui--tools-grey?style=for-the-badge&logo=github\" /></a>\n</p>\n\nA small React + TypeScript component and UI-tools library for frontend applications, with an optional Node.js backend terminal API.\n\n> **Status:** UI Tools is currently under development and published as a beta package.\n\n## Security\n\nUI Tools has a documented security history. Earlier beta releases of the optional backend terminal had insufficient authentication around the WebSocket/PTY terminal.\n\n- `0.1.0-beta` through `0.1.8-beta` are treated as affected by the historical terminal authentication issue.\n- `0.1.9-beta` added authentication before WebSocket upgrades and PTY creation.\n- `0.2.0-beta` added additional connection, origin, session, environment, and execution hardening.\n- `0.2.1-beta` adds credential verification and additional execution/sandbox controls.\n- The terminal backend is exposed separately through `@bananacool467/ui-tools/backend`.\n- Installing the package does **not** start the terminal. The terminal functionality must be explicitly imported and used by an application.\n- The package does not define a `postinstall` script.\n\nFor the detailed security policy and current status, see [`SECURITY.md`](SECURITY.md) and [`SECURITY-STATUS.md`](SECURITY-STATUS.md). The machine-readable LLM context is available in [`llms.txt`](llms.txt) and [`llms-full.txt`](llms-full.txt).\n\n## Installation\n\n### NPM\n\n```bash\nnpm i @bananacool467/ui-tools@latest\n```\n\n### From GitHub\n\n```bash\ngit clone https://github.com/bananakitssu/ui-tools\ncd ui-tools\nnpm run setup\nnpm run build\n```\n\nThe package exposes the browser/React API from `@bananacool467/ui-tools` and the Node.js terminal API from `@bananacool467/ui-tools/backend`.\n\n## Quick start\n\n```tsx\nimport {\n  Button,\n  Card,\n  ThemeProvider,\n  Typography,\n} from '@bananacool467/ui-tools';\n\nexport function App() {\n  return (\n    <ThemeProvider>\n      <Card title=\"Hello UI Tools\">\n        <Typography variant=\"body1\">\n          A simple React UI built with UI Tools.\n        </Typography>\n        <Button onClick={() => console.log('clicked')}>\n          Click me\n        </Button>\n      </Card>\n    </ThemeProvider>\n  );\n}\n```\n\n`ThemeProvider` is optional because the library has a built-in default theme, but using it is recommended when customizing application-wide styling.\n\n---\n\n# Documentation\n\n## Public exports\n\nThe root entry point (`src/index.ts`) re-exports the following public API:\n\n### Layout\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `Box` / `BoxProps` | Polymorphic basic container | `as`, `p`, `bgcolor` |\n| `Container` / `ContainerProps` | Centered page container | `maxWidth`, `fullHeight` |\n| `View` / `ViewProps` | Flexbox layout primitive | `as`, `direction`, `align`, `justify`, `wrap`, `gap`, `flex` |\n| `Grid` / `GridProps` | CSS grid container/item | `container`, `span`, `columns`, `spacing` |\n| `Paper` / `PaperProps` | Surface with elevation or border | `as`, `elevation`, `variant`, `square` |\n| `Card` / `CardProps` | Pre-styled content card | `title`, `elevation`, `variant` |\n| `Divider` / `DividerProps` | Horizontal/vertical divider | `orientation`, `children` |\n\n### Navigation and menus\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `AppBar` / `AppBarProps` | Application header | `position`, `color`, `elevation` |\n| `AppBarTitle` / `AppBarTitleProps` | Flexible title inside `AppBar` | `children`, `style` |\n| `Breadcrumbs` | Breadcrumb navigation | See `BreadcrumbsProps` in the generated TypeScript declarations |\n| `BottomNavigation` | Bottom navigation UI | See its TypeScript props |\n| `Tabs` / `TabsProps` / `TabItem` | Tab navigation with active indicator | `items`, `value`, `onChange` |\n| `Menu` / `MenuProps` / `MenuItem` | Click-triggered popup menu | `items`, `children` |\n| `ContextMenu` / `ContextMenuProps` / `ContextMenuItem` | Right-click context menu | `items`, `children` |\n| `Pagination` / `PaginationProps` | Page navigation | `count`, `page`, `onChange` |\n| `Link` / `LinkProps` | Styled anchor/link primitive | `href`, `onClick` plus anchor attributes |\n\n### Inputs and controls\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `Button` / `ButtonProps` | Primary/secondary action button | `variant`, `isLoading` plus button attributes |\n| `IconButton` / `IconButtonProps` | Circular icon action | `size`, `color` plus button attributes |\n| `Fab` / `FabProps` | Floating action button | `size`, `color`, `variant` plus button attributes |\n| `Input` / `InputProps` | Labeled text input | `label`, `error`, `helperText`, `labelColor`, `activeColor` plus input attributes |\n| `TextArea` / `TextAreaProps` | Labeled multiline input | `label`, `error`, `helperText`, `labelColor`, `activeColor` plus textarea attributes |\n| `Select` / `SelectProps` / `SelectOption` | Custom keyboard-accessible select | `label`, `options`, `value`, `onChange`, `placeholder` |\n| `Checkbox` / `CheckboxProps` | Checkbox control | `label`, `labelColor` plus checkbox attributes |\n| `Radio` / `RadioProps` | Radio control | `label`, `labelColor` plus radio attributes |\n| `RadioGroup` / `RadioGroupProps` | Controlled group of radios | `label`, `name`, `value`, `onChange`, `direction` |\n| `Switch` / `SwitchProps` | Toggle switch | `label`, `labelColor` plus checkbox attributes |\n| `Slider` / `SliderProps` | Numeric range slider | `label`, `value`, `min`, `max`, `step`, `disabled`, `onChange`, `showValue` |\n\n### Feedback and overlays\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `Alert` / `AlertProps` / `AlertSeverity` | Inline status message | `severity`, `title`, `onClose`, `children` |\n| `Badge` / `BadgeProps` | Badge or notification dot | `content`, `color`, `variant`, `max`, `invisible`, `children` |\n| `Chip` / `ChipProps` | Compact label/tag | `label`, `color`, `variant`, `onDelete`, `onClick` |\n| `Modal` / `ModalProps` | Centered modal dialog | `isOpen`, `onClose`, `title`, `children` |\n| `PromptModal` / `PromptModalProps` | Modal containing a text prompt | `isOpen`, `onClose`, `onConfirm`, `title`, `message`, `label`, `placeholder`, `defaultValue`, `confirmText`, `cancelText`, `destructive` |\n| `Drawer` / `DrawerProps` | Sliding modal surface | `isOpen`, `onClose`, `anchor`, `children` |\n| `Tooltip` / `TooltipProps` | Delayed hover/focus tooltip | `label`, `children`, `placement` |\n| `ToastProvider` / `useToast` / `Toast` / `ToastType` | Application toast notifications | `addToast(message, type?, duration?)`, `removeToast(id)` |\n\n### Data display and progress\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `Avatar` / `AvatarProps` | Image or fallback avatar | `src`, `alt`, `children`, `size`, `color`, `variant` |\n| `List` / `ListProps` | Styled unordered list | `disablePadding`, `children` |\n| `ListItem` / `ListItemProps` | List row with optional actions/adornments | `button`, `onClick`, `selected`, `disabled`, `startAdornment`, `endAdornment`, `primary`, `secondary` |\n| `CircularProgress` / `CircularProgressProps` | Circular progress indicator | `value`, `size`, `strokeWidth`, `color`, `trackColor` |\n| `LinearProgress` / `LinearProgressProps` | Linear progress indicator | `value`, `color`, `trackColor` |\n| `Skeleton` / `SkeletonProps` | Loading placeholder | `variant`, `width`, `height` |\n| `Typography` / `TypographyProps` / `TypographyVariant` | Themed text and headings | `variant`, `as`, `color`, `align` |\n\n### Theme and hooks\n\n| Export | Purpose |\n| --- | --- |\n| `defaultTheme` / `Theme` | Built-in design tokens and theme type |\n| `ThemeProvider` / `ThemeProviderProps` | Deep-merges custom theme values with `defaultTheme` |\n| `useTheme` | Reads the active theme |\n| `useRipple` / `RippleItem` | Reusable ripple interaction state and controls |\n\n### Terminal UI\n\n| Export | Purpose | Main props |\n| --- | --- | --- |\n| `Terminal` / `TermProps` | Browser terminal connected to a terminal WebSocket | `token`, `url`, `width`, `height`, `controls`, `p`, `bgcolor`, `controlscolor`, `variant` |\n\n> **Important:** `Terminal` is the client-side terminal UI. The Node.js WebSocket/PTY server is provided separately through `@bananacool467/ui-tools/backend`.\n\n---\n\n## Layout components\n\n### `Box`\n\n`Box` is a lightweight polymorphic container. `as` changes the rendered HTML element, `p` uses a spacing token, and `bgcolor` accepts one of the theme background names or a custom CSS color.\n\n```tsx\n<Box as=\"section\" p=\"lg\" bgcolor=\"surfaceSunken\">\n  Content\n</Box>\n```\n\n### `View`\n\n`View` is a flexbox primitive:\n\n```tsx\n<View direction=\"row\" align=\"center\" justify=\"space-between\" gap={16}>\n  <Typography>Left</Typography>\n  <Button>Right</Button>\n</View>\n```\n\n`direction` is `row | column`; `align` supports `start | center | end | stretch | baseline`; and `justify` supports `start | center | end | space-between | space-around | space-evenly`.\n\n### `Grid`\n\nUse `container` for the grid itself and `span` for an item:\n\n```tsx\n<Grid container columns={12} spacing={16}>\n  <Grid span={8}>Main</Grid>\n  <Grid span={4}>Sidebar</Grid>\n</Grid>\n```\n\n### `Paper` and `Card`\n\n```tsx\n<Paper elevation={2}>\n  Surface content\n</Paper>\n\n<Card title=\"Account\" elevation=\"card\" variant=\"outlined\">\n  Card content\n</Card>\n```\n\n`Paper` supports elevations `0` through `4` and `elevation | outlined` variants. `Card` maps `flat`, `card`, and `modal` to predefined paper elevations.\n\n### `Container`\n\n```tsx\n<Container maxWidth=\"lg\" fullHeight>\n  Page content\n</Container>\n```\n\nAvailable `maxWidth` values are `sm`, `md`, `lg`, `xl`, or `false` to remove the maximum width.\n\n---\n\n## Buttons and controls\n\n### `Button`\n\n`Button` extends the normal React button attributes and adds `variant` and `isLoading`.\n\n```tsx\n<Button variant=\"primary\">Save</Button>\n<Button variant=\"secondary\">Cancel</Button>\n<Button isLoading>Saving...</Button>\n```\n\n`isLoading` also disables the button while the loading indicator is shown.\n\n### `IconButton` and `Fab`\n\n```tsx\n<IconButton size=\"small\" aria-label=\"Settings\">\n  ⚙\n</IconButton>\n\n<Fab size=\"large\">+</Fab>\n```\n\nBoth controls include the library ripple interaction.\n\n### `Checkbox`, `Radio`, and `Switch`\n\nThese controls support the normal React input attributes while adding an optional label and label color.\n\n```tsx\n<Checkbox label=\"Enable notifications\" checked={enabled} onChange={handleChange} />\n<Radio label=\"Option A\" value=\"a\" checked={value === 'a'} onChange={handleChange} />\n<Switch label=\"Dark mode\" checked={dark} onChange={handleChange} />\n```\n\n### `RadioGroup`\n\n`RadioGroup` controls the `name`, `checked`, and `onChange` values of its radio children:\n\n```tsx\n<RadioGroup\n  label=\"Plan\"\n  name=\"plan\"\n  value={plan}\n  onChange={setPlan}\n>\n  <Radio value=\"free\" label=\"Free\" />\n  <Radio value=\"pro\" label=\"Pro\" />\n</RadioGroup>\n```\n\n### `Select`\n\n```tsx\n<Select\n  label=\"Country\"\n  options={[\n    { label: 'Trinidad and Tobago', value: 'tt' },\n    { label: 'Canada', value: 'ca' },\n  ]}\n  value={country}\n  onChange={setCountry}\n/>\n```\n\nThe component supports mouse selection plus `Enter`, `Space`, `ArrowUp`, `ArrowDown`, `Escape`, and `Tab` keyboard interaction.\n\n### `Slider`\n\n```tsx\n<Slider\n  label=\"Volume\"\n  min={0}\n  max={100}\n  value={volume}\n  onChange={setVolume}\n  showValue\n/>\n```\n\nIf `value` is omitted, the slider manages its own internal value starting at `min`.\n\n---\n\n## Feedback and overlays\n\n### `Alert`\n\n`severity` is one of `success`, `error`, `info`, or `warning`.\n\n```tsx\n<Alert severity=\"success\" title=\"Saved\">\n  Your changes were saved.\n</Alert>\n```\n\n### `Badge`\n\n```tsx\n<Badge content={7}>\n  <Avatar>BK</Avatar>\n</Badge>\n\n<Badge variant=\"dot\">\n  <Avatar>BK</Avatar>\n</Badge>\n```\n\nNumeric standard badges are capped using `max` and displayed as `max+` when exceeded. `invisible` hides the badge without removing its child.\n\n### `Chip`\n\n```tsx\n<Chip label=\"TypeScript\" variant=\"outlined\" onDelete={() => removeTag()} />\n```\n\n### `Modal`\n\n`Modal` renders through a portal and manages body scroll, focus, Escape-to-close, and Tab focus wrapping.\n\n```tsx\n<Modal isOpen={open} onClose={() => setOpen(false)} title=\"Confirm\">\n  <Typography>Are you sure?</Typography>\n</Modal>\n```\n\n### `PromptModal`\n\n```tsx\n<PromptModal\n  isOpen={open}\n  onClose={() => setOpen(false)}\n  title=\"Rename\"\n  label=\"Name\"\n  defaultValue=\"New project\"\n  onConfirm={(value) => rename(value)}\n/>\n```\n\nPressing Enter in the input confirms the prompt. `destructive` changes the confirm action styling.\n\n### `Drawer`\n\n```tsx\n<Drawer\n  isOpen={open}\n  onClose={() => setOpen(false)}\n  anchor=\"left\"\n>\n  Navigation\n</Drawer>\n```\n\n`anchor` supports `left`, `right`, `top`, and `bottom`. Escape closes an open drawer and the body is locked while it is mounted.\n\n### `Menu` and `ContextMenu`\n\n```tsx\n<Menu\n  items={[\n    { label: 'Edit', onClick: edit },\n    { label: 'Delete', danger: true, onClick: remove },\n    { label: '', divider: true },\n  ]}\n>\n  <Button>Actions</Button>\n</Menu>\n```\n\n`ContextMenu` uses the same `MenuItem`-style fields but opens from a right-click instead of a trigger click.\n\n### `Tooltip`\n\n```tsx\n<Tooltip label=\"More information\" placement=\"right\">\n  <Button aria-label=\"Info\">?</Button>\n</Tooltip>\n```\n\nTooltips appear after a short delay on mouse hover or focus.\n\n### Toasts\n\nWrap the application with `ToastProvider`, then call `useToast` from descendants:\n\n```tsx\n<ToastProvider>\n  <App />\n</ToastProvider>\n```\n\n```tsx\nconst { addToast, removeToast } = useToast();\n\naddToast('Saved successfully', 'success');\naddToast('Something went wrong', 'error', 5000);\n```\n\n`ToastType` is `success | error | info | warning`. The default duration is 3000 ms; a duration of `0` leaves the toast until it is explicitly removed.\n\n---\n\n## Progress and loading\n\n### `CircularProgress`\n\n```tsx\n<CircularProgress />\n<CircularProgress value={65} size={48} strokeWidth={5} />\n```\n\nOmitting `value` creates an indeterminate spinner. Values are clamped to `0..100`.\n\n### `LinearProgress`\n\n```tsx\n<LinearProgress />\n<LinearProgress value={65} />\n```\n\nAs with `CircularProgress`, omitting `value` produces an indeterminate indicator.\n\n### `Skeleton`\n\n```tsx\n<Skeleton variant=\"text\" width=\"240px\" />\n<Skeleton variant=\"circular\" />\n<Skeleton variant=\"rectangular\" height={120} />\n```\n\nVariants are `text`, `circular`, and `rectangular`.\n\n---\n\n## Typography\n\n`TypographyVariant` supports:\n\n- `h1`\n- `h2`\n- `h3`\n- `h4`\n- `body1`\n- `body2`\n- `caption`\n- `overline`\n\n```tsx\n<Typography variant=\"h2\">Dashboard</Typography>\n<Typography variant=\"body2\" color=\"#666\">Last updated just now.</Typography>\n<Typography variant=\"caption\" align=\"center\">Caption</Typography>\n```\n\nUse `as` when you need a different semantic HTML element without changing the visual variant.\n\n---\n\n## Theme system\n\nThe library ships with `defaultTheme`, containing colors, spacing, radii, shadows, and typography tokens.\n\n```tsx\nimport {\n  ThemeProvider,\n  defaultTheme,\n  useTheme,\n} from '@bananacool467/ui-tools';\n\nconst theme = {\n  colors: {\n    primary: '#7c3aed',\n  },\n  spacing: {\n    md: '18px',\n  },\n};\n\nfunction App() {\n  return (\n    <ThemeProvider theme={theme}>\n      <Page />\n    </ThemeProvider>\n  );\n}\n\nfunction Page() {\n  const theme = useTheme();\n  return <div style={{ color: theme.colors.primary }}>Hello</div>;\n}\n```\n\n`ThemeProvider` accepts a deep partial theme and merges it with the default theme, so you only need to provide the tokens you want to override.\n\n### Default spacing\n\n`xs`, `sm`, `md`, `lg`, `xl`, `xxl` → `4px`, `8px`, `16px`, `24px`, `32px`, `48px`.\n\n### Default radii\n\n`sm`, `md`, `lg`, `xl`, `pill`.\n\n### Typography tokens\n\nThe default theme provides display/body font families, sizes from `xs` through `3xl`, and weights `regular`, `medium`, `semibold`, and `bold`.\n\n---\n\n# Terminal\n\nUI Tools has two separate pieces for terminal functionality:\n\n1. `Terminal` — the React/browser terminal component.\n2. `useTerminal` — the Node.js backend WebSocket/PTY handler, exported from `@bananacool467/ui-tools/backend`.\n\nThe backend **requires an authentication token** before it will create a WebSocket session or spawn a PTY.\n\n## Backend installation\n\nThe backend uses `ws` and `@lydell/node-pty`. They are dependencies of the package.\n\nImport it with:\n\n```ts\nimport { useTerminal } from '@bananacool467/ui-tools/backend';\n```\n\n## Minimal backend setup\n\n```ts\nconst terminalHandler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n});\n\napp.get('/terminal-stream', terminalHandler);\n```\n\nThe browser component receives the same token:\n\n```tsx\n<Terminal token={terminalToken} />\n```\n\nThe browser sends the token through the WebSocket subprotocol rather than putting it in the URL query string.\n\n> Do not expose a long-lived terminal token in a public application. Prefer an authenticated application session or a short-lived credential.\n\n## `useTerminal` options\n\n```ts\ninterface UseTerminalOptions {\n  path?: string;\n  shell?: string;\n  shellArgs?: string[];\n  maxHistory?: number;\n  token: string | undefined;\n  restrictToLocalhost?: boolean;\n  startupShell?: string;\n  startupShellArgs?: string[];\n  allowedOrigins?: string[];\n  strictConnection?: boolean;\n  executionMode?: 'sandbox' | 'restricted' | 'host';\n  strictExecution?: boolean;\n  sandboxCommand?: string;\n  workspaceRoot?: string;\n  allowNetwork?: boolean;\n  authentication?: (\n    providedToken: string | null,\n    req: IncomingMessage,\n    res: ServerResponse\n  ) => false | { id: string } | Promise<false | { id: string }>;\n  credentials?: Cred[];\n  credVerification?: (cred: CredExpect[]) => boolean;\n  strictEnv?: boolean;\n  env?: Record<string, string>;\n  maxSessions?: number;\n  maxConnections?: number;\n}\n```\n\n### Authentication\n\nThe simplest authentication mode is a shared token:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n});\n```\n\nFor application-specific authentication, provide `authentication`. Return `false` to reject a connection or an object containing a stable user `id` to authenticate it:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  authentication: async (providedToken, req, res) => {\n    const user = await getUserFromSession(req);\n    if (!user || providedToken !== user.terminalToken) {\n      return false;\n    }\n    return { id: user.id };\n  },\n});\n```\n\nWhen an existing session is resumed, its user ID is checked against the authenticated user.\n\n### Credential challenges\n\nFor an additional credential prompt, provide `credentials` and `credVerification`:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  credentials: [\n    { credName: 'PIN', credTypes: ['password', 'string'] },\n  ],\n  credVerification: (credentials) => {\n    return credentials.some(\n      (cred) => cred.credName === 'PIN' && cred.credValue === '1234'\n    );\n  },\n});\n```\n\n`CredTypes` are `password`, `string`, and `number`. The terminal UI handles the credential challenge flow.\n\n### Connection restrictions\n\nFor local development, keep the terminal bound to localhost:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  restrictToLocalhost: true,\n});\n```\n\n`restrictToLocalhost` defaults to `true`.\n\nTo restrict WebSocket origins:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  strictConnection: true,\n  allowedOrigins: ['https://your-app.example'],\n});\n```\n\n### Execution modes\n\n`executionMode` supports three modes:\n\n| Mode | Behavior |\n| --- | --- |\n| `restricted` | Default. Uses a limited environment/PATH but runs the shell on the host. **Not a security sandbox.** |\n| `host` | Runs directly with the host environment. Intended for development only. |\n| `sandbox` | Runs the shell through Bubblewrap (`bwrap`) on Linux. Fails closed if a usable user namespace cannot be created. |\n\nFor a Linux Bubblewrap setup:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  executionMode: 'sandbox',\n  workspaceRoot: process.cwd(),\n  allowNetwork: false,\n});\n```\n\nBubblewrap is not Docker. Install `bwrap` using your operating system's package manager. The sandbox mounts the configured workspace at `/workspace` and, unless `allowNetwork` is enabled, unshares the network namespace.\n\n> `strictEnv` and `restricted` are hardening measures, not substitutes for isolation. Do not present host execution as a security boundary for hostile or multi-tenant users.\n\n### Environment\n\nBy default, restricted/sandbox execution receives a minimal environment. You can add variables with `env`:\n\n```ts\nconst handler = await useTerminal({\n  token: process.env.TERMINAL_TOKEN,\n  env: {\n    SESSION_ID: '123',\n  },\n});\n```\n\nUse `strictEnv: true` when you want to explicitly control the environment rather than inheriting the host environment.\n\n### Resource limits\n\nThe backend has built-in limits for terminal sessions and connections:\n\n- Maximum history: 1 MiB.\n- Maximum message size: 64 KiB.\n- Maximum session lifetime: 1 hour.\n- Default maximum sessions: 100.\n- Default maximum WebSocket connections: 100.\n\n`maxHistory`, `maxSessions`, and `maxConnections` can be configured through `UseTerminalOptions`; the message-size and maximum-lifetime constants are enforced internally.\n\n---\n\n# Terminal component\n\n`Terminal` renders the terminal UI in React and communicates with the backend through WebSockets.\n\nThe `url` prop is a **path on the current host**, not a complete WebSocket URL. The component automatically builds the WebSocket URL using the current page's protocol and host:\n\n```tsx\n<Terminal\n  token={terminalToken}\n  url=\"/terminal-stream\"\n  width={600}\n  height={420}\n  controls\n/>\n```\n\nIf `url` is omitted, the default path is `/terminal-stream`. For an HTTPS page the component uses `wss://`; for an HTTP page it uses `ws://`.\n\nUseful props include:\n\n- `token` — required authentication token.\n- `url` — relative WebSocket endpoint path on the current host; defaults to `/terminal-stream`.\n- `width` / `height` — terminal dimensions.\n- `controls` — shows terminal controls.\n- `p` — theme spacing token for padding.\n- `bgcolor` — theme background name or custom color.\n- `controlscolor` — theme/custom color for controls.\n- `variant` — terminal visual variant.\n\nThe component includes terminal interaction such as text selection, scrolling, keyboard modifiers, ANSI foreground/background colors, credential prompts, and session reconnection behavior.\n\n---\n\n# Ripple hook\n\n`useRipple` is exported for components that need the same interaction effect used by buttons and selection controls.\n\n```tsx\nconst { ripples, startRipple, endRipple } = useRipple(false);\n\nstartRipple(x, y, size);\nendRipple();\n```\n\n`RippleItem` contains `id`, `x`, `y`, `size`, `active`, and `exiting` state.\n\n---\n\n# Accessibility and behavior notes\n\nSeveral components include built-in interaction behavior rather than being simple visual wrappers:\n\n- `Modal` traps Tab focus while open, closes on Escape, locks body scrolling, and restores the previously focused element.\n- `Drawer` closes on Escape and locks body scrolling while open.\n- `Select` supports keyboard navigation and exposes combobox/listbox roles.\n- `Alert`, `Toast`, `Modal`, and `Drawer` use appropriate ARIA roles where applicable.\n- `Button`, `Checkbox`, `Radio`, `Switch`, `IconButton`, and `ListItem` include ripple interactions.\n- `Tooltip` responds to both pointer hover and focus.\n\n---\n\n# Source-only files and exports\n\nThe public root API is defined by `src/index.ts`, not by every file that happens to exist under `src/`.\n\nA few source files deserve special mention:\n\n- `Video.tsx` currently declares a **default export**. Because `src/index.ts` uses `export *`, its default export is not re-exported as a named `Video` export from `@bananacool467/ui-tools`.\n- `Autocomplete.tsx`, `CodeEditor.tsx`, and other source files that are not referenced by `src/index.ts` are not part of the root public API.\n- `Rating.tsx` is also not referenced by the current root export list.\n- The backend entry point is intentionally separate: `src/backend.ts` exports the terminal backend API from `@bananacool467/ui-tools/backend`.\n\nFor the authoritative TypeScript API, use the generated `dist/*.d.ts` files produced by `npm run build`.\n\n---\n\n# Build\n\n```bash\nnpm run setup\nnpm run build\n```\n\nThe build compiles TypeScript and flattens the generated `dist/src` output into `dist`.\n\n# License\n\nMIT\n","readmeFilename":"README.md","users":{"bananacool467":true}}