{"_id":"@unleash/toolbar","_rev":"9-8d60adea1ed424d1f4dd6408d6e5ec8e","name":"@unleash/toolbar","dist-tags":{"latest":"1.2.1"},"versions":{"1.0.0":{"name":"@unleash/toolbar","version":"1.0.0","keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"author":{"name":"Unleash"},"license":"Apache-2.0","_id":"@unleash/toolbar@1.0.0","maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"}],"homepage":"https://github.com/Unleash/toolbar","bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"dist":{"shasum":"d5d6d08c3349ee3e638bfd7ffef8256b9aeb5e1a","tarball":"https://registry.npmjs.org/@unleash/toolbar/-/toolbar-1.0.0.tgz","fileCount":38,"integrity":"sha512-mDZolO/t/3zuIaKdEX9+uK3yNpOm+IFotiWVKvkmv5evQ582pl/B4BPbW9KyPNJ+UrPS54QwStLqdiXbItuPJw==","signatures":[{"sig":"MEYCIQCs9ci0ZQPgrCCXJZW7HJFDlMRKdV+NqfrMTKZ9E5lvUwIhAOvuhMd0/mQhet0cT19+t8HYmQekT+Y5vFVYwZFPPcWX","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":202082},"main":"./dist/index.es.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js"},"./next":{"types":"./dist/next/index.d.ts","import":"./dist/next.es.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react.es.js"},"./next/server":{"types":"./dist/next/server.d.ts","import":"./dist/next-server.es.js"},"./toolbar.css":"./dist/toolbar.css"},"gitHead":"80fb766c5769a772a380e3d2c2a6e0e36ce9e801","scripts":{"dev":"vite","lint":"biome check .","test":"vitest run","build":"tsc && vite build","test:ui":"vitest --ui","lint:fix":"biome check --write .","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage","serve:example:vue":"cd examples/vue && npm run dev","serve:example:react":"cd examples/react && npm run dev","serve:example:nextjs":"cd examples/nextjs && npm run dev","serve:example:angular":"cd examples/angular && npm start","serve:example:vanilla":"npx serve -p 3000 ."},"_npmUser":{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},"_npmVersion":"11.6.1","description":"Client-side override toolbar for Unleash JavaScript SDKs","directories":{},"_nodeVersion":"24.10.0","dependencies":{"lit":"^3.3.1"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^7.2.7","jsdom":"^27.3.0","react":"^18.3.1 || ^19.2.3","eslint":"^9.39.2","terser":"^5.44.1","vitest":"^4.0.15","cssnano":"^7.1.2","postcss":"^8.5.6","react-dom":"^18.3.1 || ^19.2.3","@eslint/js":"^9.39.2","typescript":"^5.3.3","@types/node":"^20.10.5","@types/react":"^18.3.1 || ^19.2.3","@types/eslint":"^9.6.1","@biomejs/biome":"^2.3.12","unleash-client":"^6.9.3","@unleash/nextjs":"^1.6.4","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.1 || ^19.2.3","typescript-eslint":"^8.49.0","@vitest/coverage-v8":"^4.0.15","@testing-library/dom":"^10.4.1","unleash-proxy-client":"^3.4.1","@testing-library/react":"^16.3.0","@testing-library/jest-dom":"^6.9.1","@unleash/proxy-client-react":"^5.0.1"},"peerDependencies":{"unleash-proxy-client":"^3.0.0"},"peerDependenciesMeta":{"@unleash/nextjs":{"optional":true},"@unleash/proxy-client-react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/toolbar_1.0.0_1769447434460_0.2332651190765962","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"@unleash/toolbar","version":"1.1.0","keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"author":{"name":"Unleash"},"license":"Apache-2.0","_id":"@unleash/toolbar@1.1.0","maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"},{"name":"nunogois","email":"github@nunogois.com"},{"name":"kwasniew","email":"kwasniewski.mateusz@gmail.com"}],"homepage":"https://github.com/Unleash/toolbar","bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"dist":{"shasum":"1d2a0773810d44efe9efabde5f6dba0cbe665f00","tarball":"https://registry.npmjs.org/@unleash/toolbar/-/toolbar-1.1.0.tgz","fileCount":3,"integrity":"sha512-RSSKMA5RLFefrtxQ3Gvi3w42iQFHnaRlKecNS8JzhoJslC2qEniHKg9WYyd70qNeK7BPOgE3XDAS0gxAfs91kQ==","signatures":[{"sig":"MEUCIQDvyo2EXQNwVIw2vpPFlCbtpUN/lrZNG5thMqgSS1nGbwIgF3JUNsuJsswHGMRlWyTVIIEnjq32SkGqEoxIA/FbulY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@unleash%2ftoolbar@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":31618},"main":"./dist/index.es.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js"},"./next":{"types":"./dist/next/index.d.ts","import":"./dist/next.es.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react.es.js"},"./next/server":{"types":"./dist/next/server.d.ts","import":"./dist/next-server.es.js"},"./toolbar.css":"./dist/toolbar.css"},"gitHead":"42dc80857aa66e981777b236aa2c1524bd5818c2","scripts":{"dev":"vite","lint":"biome check .","test":"vitest run","build":"tsc && vite build","test:ui":"vitest --ui","lint:fix":"biome check --write .","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage","serve:example:vue":"cd examples/vue && npm run dev","serve:example:react":"cd examples/react && npm run dev","serve:example:nextjs":"cd examples/nextjs && npm run dev","serve:example:angular":"cd examples/angular && npm start","serve:example:vanilla":"npx serve -p 3000 ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:11c30954-7694-471f-bf65-b0e4d3776351"}},"overrides":{"next":{"postcss":"^8.5.12"}},"deprecated":"Broken release: missing dist/. Use 1.1.1 or later.","repository":{"url":"git+https://github.com/Unleash/toolbar.git","type":"git"},"_npmVersion":"11.17.0","description":"Client-side override toolbar for Unleash JavaScript SDKs","directories":{},"_nodeVersion":"20.20.2","dependencies":{"lit":"^3.3.1"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.16","jsdom":"^27.3.0","react":"^18.3.1 || ^19.2.3","eslint":"^9.39.2","terser":"^5.44.1","vitest":"^4.0.15","cssnano":"^7.1.2","postcss":"^8.5.12","react-dom":"^18.3.1 || ^19.2.3","@eslint/js":"^9.39.2","typescript":"^5.3.3","@types/node":"^20.10.5","@types/react":"^18.3.1 || ^19.2.3","@types/eslint":"^9.6.1","@biomejs/biome":"^2.3.12","unleash-client":"^6.9.3","@unleash/nextjs":"^1.6.4","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.1 || ^19.2.3","typescript-eslint":"^8.49.0","@vitest/coverage-v8":"^4.0.15","@testing-library/dom":"^10.4.1","unleash-proxy-client":"^3.4.1","@testing-library/react":"^16.3.0","@testing-library/jest-dom":"^6.9.1","@unleash/proxy-client-react":"^5.0.1"},"peerDependencies":{"unleash-proxy-client":"^3.0.0"},"peerDependenciesMeta":{"@unleash/nextjs":{"optional":true},"@unleash/proxy-client-react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/toolbar_1.1.0_1782737646695_0.65138537230194","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"@unleash/toolbar","version":"1.1.1","keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"author":{"name":"Unleash"},"license":"Apache-2.0","_id":"@unleash/toolbar@1.1.1","maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"},{"name":"nunogois","email":"github@nunogois.com"},{"name":"davidleek","email":"david@getunleash.io"},{"name":"kwasniew","email":"kwasniewski.mateusz@gmail.com"}],"homepage":"https://github.com/Unleash/toolbar","bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"dist":{"shasum":"00780388403a56068fb65f686c1e52b719b75283","tarball":"https://registry.npmjs.org/@unleash/toolbar/-/toolbar-1.1.1.tgz","fileCount":41,"integrity":"sha512-l6sX5NcG94depeyjSWNraVKP3/+gw0tBXb6SmP0Hzux4w/n9oNIkYT+s1LTL/3VYwsd9ozjpSjT4X/slJCVhjg==","signatures":[{"sig":"MEUCIQCtmSQqCdQkolY6Jez7Yy4J+UTl+aXAX7KT1vWQOnNemAIgP249WnU8q5LD4DT5y/b80T1id1WbdIV6507HX4C8DJM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@unleash%2ftoolbar@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":225356},"main":"./dist/index.es.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js"},"./next":{"types":"./dist/next/index.d.ts","import":"./dist/next.es.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react.es.js"},"./next/server":{"types":"./dist/next/server.d.ts","import":"./dist/next-server.es.js"},"./toolbar.css":"./dist/toolbar.css"},"gitHead":"36e09d5e09f5263fadc242bcda147de801334b03","scripts":{"dev":"vite","lint":"biome check .","test":"vitest run","build":"tsc && vite build","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"biome check --write .","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage","serve:example:vue":"cd examples/vue && npm run dev","serve:example:react":"cd examples/react && npm run dev","serve:example:nextjs":"cd examples/nextjs && npm run dev","serve:example:angular":"cd examples/angular && npm start","serve:example:vanilla":"npx serve -p 3000 ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:11c30954-7694-471f-bf65-b0e4d3776351"}},"overrides":{"next":{"postcss":"^8.5.12"}},"repository":{"url":"git+https://github.com/Unleash/toolbar.git","type":"git"},"_npmVersion":"11.14.0","description":"Client-side override toolbar for Unleash JavaScript SDKs","directories":{},"_nodeVersion":"24.18.0","dependencies":{"lit":"^3.3.1"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.16","jsdom":"^27.3.0","react":"^18.3.1 || ^19.2.3","eslint":"^9.39.2","terser":"^5.44.1","vitest":"^4.0.15","cssnano":"^7.1.2","postcss":"^8.5.12","react-dom":"^18.3.1 || ^19.2.3","@eslint/js":"^9.39.2","typescript":"^5.3.3","@types/node":"^20.10.5","@types/react":"^18.3.1 || ^19.2.3","@types/eslint":"^9.6.1","@biomejs/biome":"^2.3.12","unleash-client":"^6.9.3","@unleash/nextjs":"^1.6.4","vite-plugin-dts":"^4.5.4","@types/react-dom":"^18.3.1 || ^19.2.3","typescript-eslint":"^8.49.0","@vitest/coverage-v8":"^4.0.15","@testing-library/dom":"^10.4.1","unleash-proxy-client":"^3.4.1","@testing-library/react":"^16.3.0","@testing-library/jest-dom":"^6.9.1","@unleash/proxy-client-react":"^5.0.1"},"peerDependencies":{"unleash-proxy-client":"^3.0.0"},"peerDependenciesMeta":{"@unleash/nextjs":{"optional":true},"@unleash/proxy-client-react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/toolbar_1.1.1_1783714219330_0.2914825240549086","host":"s3://npm-registry-packages-npm-production"}},"1.2.0":{"name":"@unleash/toolbar","version":"1.2.0","keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"author":{"name":"Unleash"},"license":"Apache-2.0","_id":"@unleash/toolbar@1.2.0","maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"},{"name":"nunogois","email":"github@nunogois.com"},{"name":"davidleek","email":"david@getunleash.io"},{"name":"kwasniew","email":"kwasniewski.mateusz@gmail.com"}],"homepage":"https://github.com/Unleash/toolbar","bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"dist":{"shasum":"90a2ca896ac619bb97f8eb53b7d6a065af208c93","tarball":"https://registry.npmjs.org/@unleash/toolbar/-/toolbar-1.2.0.tgz","fileCount":45,"integrity":"sha512-dFFzFP8cZ+Gr2r8CRyzDDnuTc4HZ7LIAJit4EJeTysDPNXVycpTflJ2qehoeLO35IZt2NbfI4IeQN0bSo+Bo8w==","signatures":[{"sig":"MEYCIQD0/+nhgaYi14//U/k1GhN+LPXPgfG/K1+uOYRYrYhKjAIhAKKuF6XN+nB0S26vtZ+dCHhHXhhtdg3IdghuFele6gg9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@unleash%2ftoolbar@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":291944},"main":"./dist/index.es.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.es.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js"},"./next":{"types":"./dist/next/index.d.ts","import":"./dist/next.es.js"},"./react":{"types":"./dist/react/index.d.ts","import":"./dist/react.es.js"},"./next/server":{"types":"./dist/next/server.d.ts","import":"./dist/next-server.es.js"},"./toolbar.css":"./dist/toolbar.css"},"gitHead":"6c55d320504267f0afabd80303ab1d2d14b5dc07","scripts":{"dev":"vite","lint":"biome check .","test":"vitest run","build":"tsc && vite build","prepare":"npm run build","test:ui":"vitest --ui","lint:fix":"biome check --write .","test:watch":"vitest","type-check":"tsc --noEmit","test:coverage":"vitest run --coverage","serve:example:vue":"cd examples/vue && npm run dev","serve:example:react":"cd examples/react && npm run dev","serve:example:nextjs":"cd examples/nextjs && npm run dev","serve:example:angular":"cd examples/angular && npm start","serve:example:vanilla":"npx serve -p 3000 ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:11c30954-7694-471f-bf65-b0e4d3776351"}},"overrides":{"next":{"postcss":"^8.5.12"},"sharp":">0.35.0"},"repository":{"url":"git+https://github.com/Unleash/toolbar.git","type":"git"},"_npmVersion":"11.14.0","description":"Client-side override toolbar for Unleash JavaScript SDKs","directories":{},"_nodeVersion":"24.18.0","dependencies":{"lit":"^3.3.1"},"_hasShrinkwrap":false,"devDependencies":{"vite":"^8.0.16","jsdom":"^27.3.0","react":"^18.3.1 || ^19.2.3","eslint":"^10.8.0","terser":"^5.44.1","vitest":"^4.0.15","cssnano":"^7.1.2","postcss":"^8.5.12","react-dom":"^18.3.1 || ^19.2.3","@eslint/js":"^9.39.2","typescript":"^5.3.3","@types/node":"^20.10.5","@types/react":"^18.3.1 || ^19.2.3","unplugin-dts":"^1.0.3","@types/eslint":"^9.6.1","@biomejs/biome":"^2.3.12","unleash-client":"^6.9.3","@unleash/nextjs":"^1.6.4","@types/react-dom":"^18.3.1 || ^19.2.3","typescript-eslint":"^8.49.0","@vitest/coverage-v8":"^4.0.15","@testing-library/dom":"^10.4.1","unleash-proxy-client":"^3.4.1","@testing-library/react":"^16.3.0","@testing-library/jest-dom":"^6.9.1","@unleash/proxy-client-react":"^5.0.1"},"peerDependencies":{"unleash-proxy-client":"^3.0.0"},"peerDependenciesMeta":{"@unleash/nextjs":{"optional":true},"@unleash/proxy-client-react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/toolbar_1.2.0_1786019765502_0.911707647650658","host":"s3://npm-registry-packages-npm-production"}},"1.2.1":{"name":"@unleash/toolbar","version":"1.2.1","description":"Client-side override toolbar for Unleash JavaScript SDKs","type":"module","main":"./dist/index.es.js","module":"./dist/index.es.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.es.js","types":"./dist/index.d.ts"},"./react":{"import":"./dist/react.es.js","types":"./dist/react/index.d.ts"},"./next":{"import":"./dist/next.es.js","types":"./dist/next/index.d.ts"},"./next/server":{"import":"./dist/next-server.es.js","types":"./dist/next/server.d.ts"},"./toolbar.css":"./dist/toolbar.css"},"scripts":{"dev":"vite","build":"tsc && vite build","prepare":"npm run build","type-check":"tsc --noEmit","lint":"biome check .","lint:fix":"biome check --write .","test":"vitest run","test:watch":"vitest","test:ui":"vitest --ui","test:coverage":"vitest run --coverage","serve:example:vanilla":"npx serve -p 3000 .","serve:example:react":"cd examples/react && npm run dev","serve:example:nextjs":"cd examples/nextjs && npm run dev","serve:example:angular":"cd examples/angular && npm start","serve:example:vue":"cd examples/vue && npm run dev"},"keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"author":{"name":"Unleash"},"repository":{"type":"git","url":"git+https://github.com/Unleash/toolbar.git"},"bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"homepage":"https://github.com/Unleash/toolbar","license":"Apache-2.0","peerDependencies":{"unleash-proxy-client":"^3.0.0"},"peerDependenciesMeta":{"@unleash/proxy-client-react":{"optional":true},"@unleash/nextjs":{"optional":true}},"devDependencies":{"@biomejs/biome":"^2.3.12","@eslint/js":"^9.39.2","@testing-library/dom":"^10.4.1","@testing-library/jest-dom":"^6.9.1","@testing-library/react":"^16.3.0","@types/eslint":"^9.6.1","@types/node":"^20.10.5","@types/react":"^18.3.1 || ^19.2.3","@types/react-dom":"^18.3.1 || ^19.2.3","@unleash/nextjs":"^1.6.4","@unleash/proxy-client-react":"^5.0.1","@vitest/coverage-v8":"^4.0.15","cssnano":"^7.1.2","eslint":"^10.8.0","jsdom":"^27.3.0","postcss":"^8.5.12","react":"^18.3.1 || ^19.2.3","react-dom":"^18.3.1 || ^19.2.3","terser":"^5.44.1","typescript":"^5.3.3","typescript-eslint":"^8.49.0","unleash-client":"^6.9.3","unleash-proxy-client":"^3.4.1","unplugin-dts":"^1.0.3","vite":"^8.0.16","vitest":"^4.0.15"},"dependencies":{"lit":"^3.3.1"},"overrides":{"next":{"postcss":"^8.5.12"},"sharp":">0.35.0"},"gitHead":"0860b3173517f1e578313d8aa743ff0238a1597e","_id":"@unleash/toolbar@1.2.1","_nodeVersion":"24.20.0","_npmVersion":"11.14.0","dist":{"integrity":"sha512-0eb4DP6KQDPbK9ltzXaDUYUVR1O+spxkqZYNOUHN/QXTaJc2SM1/imKzJbPdFEroC77xsFnCDD0QmJ57yeNKhA==","shasum":"86a71fa5147e3e04e6df230b90fb6d80225a822d","tarball":"https://registry.npmjs.org/@unleash/toolbar/-/toolbar-1.2.1.tgz","fileCount":49,"unpackedSize":297669,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@unleash%2ftoolbar@1.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDH/59hEZ2Sf6vfyTklP3bEcomXLn/nx7p24FZhHDTUZAIgFU6SAIguFdd9zHfWsA9mrpUZwCFtU5AAnZpUPg1TUos="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:11c30954-7694-471f-bf65-b0e4d3776351"}},"directories":{},"maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"},{"name":"nunogois","email":"github@nunogois.com"},{"name":"davidleek","email":"david@getunleash.io"},{"name":"kwasniew","email":"kwasniewski.mateusz@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/toolbar_1.2.1_1788776394560_0.36838879935325175"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-26T17:10:34.386Z","modified":"2026-09-07T10:19:55.029Z","1.0.0":"2026-01-26T17:10:34.690Z","1.1.0":"2026-06-29T12:54:06.871Z","1.1.1":"2026-07-10T20:10:19.480Z","1.2.0":"2026-08-06T12:36:05.699Z","1.2.1":"2026-09-07T10:19:54.709Z"},"bugs":{"url":"https://github.com/Unleash/toolbar/issues"},"author":{"name":"Unleash"},"license":"Apache-2.0","homepage":"https://github.com/Unleash/toolbar","keywords":["unleash","feature-flags","feature-toggles","debugging","toolbar","override","react","nextjs","ssr","development-tools"],"repository":{"type":"git","url":"git+https://github.com/Unleash/toolbar.git"},"description":"Client-side override toolbar for Unleash JavaScript SDKs","maintainers":[{"name":"foseberg","email":"fredrik.no@gmail.com"},{"name":"ivarconr","email":"ivarconr@gmail.com"},{"name":"alexcasalboni","email":"alex@alexcasalboni.com"},{"name":"chriswk","email":"npm@chriswk.no"},{"name":"sighphyre","email":"liquidwicked64@gmail.com"},{"name":"gfournier","email":"gastonfournier@gmail.com"},{"name":"sjaanus","email":"sellinjaanus@gmail.com"},{"name":"nunogois","email":"github@nunogois.com"},{"name":"davidleek","email":"david@getunleash.io"},{"name":"kwasniew","email":"kwasniewski.mateusz@gmail.com"}],"readme":"# Unleash Toolbar\n\nA client-side debugging toolbar for [Unleash](https://www.getunleash.io/) feature flags. Override flag values and context in real-time without server changes.\n\n![Unleash Toolbar Screenshot](toolbar.png)\n\n## Features\n\n- **Flag Overrides**: Force boolean flags ON/OFF or override variant values\n- **Context Overrides**: Modify userId, sessionId, environment, and custom properties\n- **Persistence**: Save overrides in memory, sessionStorage, or localStorage\n- **React Integration**: Seamlessly wraps the official `@unleash/proxy-client-react` SDK\n- **Next.js SSR Support**: Server-side rendering with cookie-based state sync using `@unleash/nextjs`\n- **Customizable UI**: Theming support and positioning options\n- **Draggable & Dismissible**: Drag the floating icon to any window edge, minimize to the icon, or hide it entirely until the next page refresh\n- **Keyboard First**: `Cmd/Ctrl+Shift+F` to summon, `Esc` to minimize, focus tethered back to wherever you opened it from, and full screen-reader semantics\n- **Custom Banner**: Optional message in the toolbar to clarify its scope for your team\n- **SDK Compatible**: Works with Unleash JavaScript SDK\n\n## Bundle Size\n\nThe toolbar is optimized for minimal impact on your application:\n\n- **Core**: ~12 KB gzipped (~2.4 KB entry + ~9.6 KB panel UI, loaded asynchronously)\n- **React**: ~0.6 KB gzipped (thin wrapper)\n- **Next.js**: ~0.7 KB gzipped (server utilities)\n- **CSS**: ~3 KB gzipped\n\n## Installation\n\n```bash\nnpm install @unleash/toolbar\n\n# For React integration\nnpm install @unleash/toolbar @unleash/proxy-client-react unleash-proxy-client\n\n# For Next.js SSR integration\nnpm install @unleash/toolbar @unleash/nextjs\n```\n\n## Quick Start\n\n### Vanilla JavaScript\n\n```javascript\nimport { initUnleashToolbar } from '@unleash/toolbar';\nimport { UnleashClient } from 'unleash-proxy-client';\nimport '@unleash/toolbar/toolbar.css';\n\n// Initialize toolbar with new Unleash client - returns wrapped client\nconst client = initUnleashToolbar(new UnleashClient({\n  url: 'https://your-unleash-instance.com/api/frontend',\n  clientKey: 'your-client-key',\n  appName: 'my-app'\n}), {\n  storageMode: 'local',\n  position: 'bottom-right',\n  initiallyVisible: true\n});\n\n// Start the client\nawait client.start();\n\n// Use the client for all flag evaluations\nconst isEnabled = client.isEnabled('my-feature');\nconst variant = client.getVariant('my-experiment');\n\n// Listen for changes (from toolbar or SDK updates)\nclient.on('update', () => {\n  // Re-evaluate flags when overrides change\n  const newValue = client.isEnabled('my-feature');\n  updateUI(newValue);\n});\n```\n\n### React\n\nThe toolbar integrates seamlessly with the official **`@unleash/proxy-client-react`** SDK. Just pass your configuration - the toolbar handles everything automatically!\n\n```bash\nnpm install @unleash/toolbar @unleash/proxy-client-react unleash-proxy-client\n```\n\n```tsx\nimport { useFlag, useVariant } from '@unleash/proxy-client-react';\nimport { UnleashToolbarProvider } from '@unleash/toolbar/react';\nimport '@unleash/toolbar/toolbar.css';\n\n// Same config format as the official React SDK\nconst config = {\n  url: 'https://your-unleash-instance.com/api/frontend',\n  clientKey: 'your-client-key',\n  appName: 'my-app',\n  refreshInterval: 15\n};\n\n// That's it! No need to import FlagProvider or manage the SDK client\nfunction App() {\n  return (\n    <UnleashToolbarProvider \n      config={config}\n      toolbarOptions={{\n        storageMode: 'local',\n        position: 'bottom-right'\n      }}\n    >\n      <MyComponent />\n    </UnleashToolbarProvider>\n  );\n}\n\n// Use hooks from the official React SDK - they work with toolbar overrides!\nfunction MyComponent() {\n  const isEnabled = useFlag('my-feature');\n  const variant = useVariant('my-experiment');\n  \n  return (\n    <div>\n      {isEnabled && <NewFeature />}\n      {variant.name === 'variant-a' && <VariantA />}\n    </div>\n  );\n}\n```\n\n**Key Points:**\n- Pass `config` directly to `UnleashToolbarProvider` - no other imports needed!\n- The toolbar automatically uses `FlagProvider` from the React SDK\n- Import hooks from `@unleash/proxy-client-react` (the official SDK)\n- All official React SDK hooks work seamlessly with toolbar overrides\n\n**Advanced: Custom FlagProvider or pre-instantiated client**\n```tsx\nimport { FlagProvider } from '@unleash/proxy-client-react';\nimport { UnleashClient } from 'unleash-proxy-client';\n\n// Option 1: Custom FlagProvider\n<UnleashToolbarProvider \n  FlagProvider={FlagProvider}  // Optional - use if you need customization\n  config={config}\n>\n  <MyApp />\n</UnleashToolbarProvider>\n\n// Option 2: Pre-instantiated client\nconst client = new UnleashClient({ /* config */ });\n\n<UnleashToolbarProvider \n  client={client}  // Pass client instead of config\n  toolbarOptions={{ /* ... */ }}\n>\n  <MyApp />\n</UnleashToolbarProvider>\n```\n\n\n### Next.js App Router (Client & Server Components)\n\nThe toolbar provides full Next.js App Router support with server-side rendering and cookie-based state synchronization.\n\n#### Client Components\n\n```tsx\n// app/layout.tsx\nimport { UnleashToolbarProvider } from '@unleash/toolbar/next';\nimport '@unleash/toolbar/toolbar.css';\n\nexport default function RootLayout({ children }) {\n  return (\n    <html>\n      <body>\n        <UnleashToolbarProvider\n          config={{\n            url: process.env.NEXT_PUBLIC_UNLEASH_URL!,\n            clientKey: process.env.NEXT_PUBLIC_UNLEASH_CLIENT_KEY!,\n            appName: 'my-next-app',\n          }}\n        >\n          {children}\n        </UnleashToolbarProvider>\n      </body>\n    </html>\n  );\n}\n```\n\n```tsx\n// app/page.tsx\n'use client';\n\nimport { useFlag, useVariant } from '@unleash/toolbar/next';\n\nexport default function HomePage() {\n  const isEnabled = useFlag('new-checkout');\n  const variant = useVariant('payment-provider');\n\n  return (\n    <div>\n      {isEnabled && <NewCheckout />}\n      <PaymentForm provider={variant.name} />\n    </div>\n  );\n}\n```\n\n#### Server Components with SSR\n\n```tsx\n// app/server-page/page.tsx\nimport { cookies } from 'next/headers';\nimport { getDefinitions, evaluateFlags, flagsClient } from '@unleash/nextjs';\nimport { applyToolbarOverrides } from '@unleash/toolbar/next/server';\n\nexport default async function ServerPage() {\n  // Fetch definitions from Unleash API (uses env config)\n  const definitions = await getDefinitions({\n    fetchOptions: { next: { revalidate: 15 } },\n  });\n\n  // Apply toolbar overrides from cookies\n  const cookieStore = await cookies();\n  const modifiedDefinitions = applyToolbarOverrides(definitions, cookieStore);\n\n  // Evaluate flags with context\n  const { toggles } = evaluateFlags(modifiedDefinitions, {\n    sessionId: 'session-id',\n    userId: 'user-id',\n  });\n\n  // Create offline client\n  const flags = flagsClient(toggles);\n\n  // Check flags server-side\n  const isEnabled = flags.isEnabled('new-feature');\n\n  return <div>{isEnabled ? 'Feature ON' : 'Feature OFF'}</div>;\n}\n```\n\n**Environment Variables for Next.js:**\n\n```env\n# Used by @unleash/nextjs SDK\nUNLEASH_SERVER_API_URL=https://your-unleash-instance.com/api\nUNLEASH_SERVER_API_TOKEN=your-server-token\nUNLEASH_APP_NAME=my-app\n\n# Used by client-side toolbar\nNEXT_PUBLIC_UNLEASH_URL=https://your-unleash-instance.com/api/frontend\nNEXT_PUBLIC_UNLEASH_CLIENT_KEY=your-client-key\nNEXT_PUBLIC_UNLEASH_APP_NAME=my-app\n```\n\n**How it works:**\n1. Client-side toolbar automatically syncs state to cookies\n2. Server components read toolbar state from cookies\n3. `applyToolbarOverrides()` modifies flag definitions before evaluation\n4. Flags evaluate server-side with toolbar overrides applied\n5. Changes in toolbar immediately affect both client and server rendering\n\n### Vue 3 (Composition API)\n\n```vue\n<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { useUnleash } from './composables/useUnleash'\n\n// Initialize Unleash with the composable\nconst { unleashClient, isReady, updateTrigger } = useUnleash()\n\n// Reactive flag states\nconst isEnabled = ref(false)\n\n// Evaluate flags\nconst evaluateFlags = () => {\n  if (!unleashClient.value) return\n  isEnabled.value = unleashClient.value.isEnabled('my-feature')\n}\n\n// Evaluate when ready\nwatch(isReady, (ready) => {\n  if (ready) evaluateFlags()\n})\n</script>\n```\n\n## Configuration Options\n\n### `initUnleashToolbar(client, options)`\n\n```typescript\ninterface InitToolbarOptions {\n  // Persistence mode (default: 'local')\n  // - 'local': Persists across tabs and browser restarts (RECOMMENDED for development)\n  // - 'session': Persists only in current tab, cleared when tab closes\n  // - 'memory': No persistence, cleared on page reload\n  storageMode?: 'memory' | 'session' | 'local';\n  \n  // Storage key for persistence (default: 'unleash-toolbar-state')\n  storageKey?: string;\n  \n  // UI position (default: 'bottom-right')\n  // Corner positions: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\n  // Side positions (vertically centered): 'left' | 'right'\n  // Used as the starting position; overridden once the user drags the toolbar.\n  position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'left' | 'right';\n  \n  // Allow dragging the floating icon to reposition the toolbar along any\n  // window edge. The chosen position is persisted. (default: true)\n  draggable?: boolean;\n  \n  // Initial visibility (default: false, but respects persisted state if available)\n  initiallyVisible?: boolean;\n  \n  // Optional informational message shown as a banner below the header.\n  // Useful for clarifying the toolbar's scope to your team, e.g.\n  // \"Only client-side flags are overridable here\". Empty by default.\n  banner?: string;\n  \n  // Optional URL shown as a link next to the banner message (opens in a new\n  // tab). Only rendered when `banner` is also set.\n  bannerLink?: string;\n  \n  // Text for the banner link (default: \"Read more\"). Only used with bannerLink.\n  bannerLinkText?: string;\n  \n  // Sort flags alphabetically instead of by evaluation order (default: false)\n  sortAlphabetically?: boolean;\n  \n  // Theme preset (default: 'light')\n  themePreset?: 'light' | 'dark';\n  \n  // Theme customization (overrides preset)\n  theme?: {\n    primaryColor?: string;\n    backgroundColor?: string;\n    textColor?: string;\n    borderColor?: string;\n    fontFamily?: string;\n  };\n  \n  // Custom container element (default: document.body)\n  container?: HTMLElement | null;\n\n  // Enable cookie sync for SSR (default: false)\n  // Set to true for Next.js or other SSR frameworks\n  enableCookieSync?: boolean;\n\n  // Render the floating toggle icon when collapsed (default: true)\n  // Set to false for a shortcut-only setup where the toolbar renders nothing\n  // until it is opened.\n  showToggleButton?: boolean;\n\n  // Keyboard shortcut that opens the panel, focuses it when already open, and\n  // minimizes it when pressed from inside (default: 'mod+shift+f')\n  // 'mod' is Cmd on macOS and Ctrl elsewhere. Set to false to register no\n  // global key listener.\n  shortcut?: string | false;\n\n  // Minimize the panel when a pointer press lands outside it (default: false)\n  closeOnOutsideClick?: boolean;\n\n  // Where to place focus when the panel opens (default: 'panel')\n  focusOnOpen?: 'panel' | 'search' | 'context';\n}\n```\n\n### Next.js Server Utilities\n\n```typescript\nimport { applyToolbarOverrides, applyToolbarOverridesToToggles, getToolbarStateFromCookies } from '@unleash/toolbar/next/server';\nimport type { ClientFeaturesResponse, IToggle } from '@unleash/nextjs';\n\n// Apply overrides before evaluation (recommended)\nconst modifiedDefinitions = applyToolbarOverrides(\n  definitions: ClientFeaturesResponse,\n  cookieStore: CookieStore\n): ClientFeaturesResponse;\n\n// Apply overrides after evaluation (alternative)\nconst modifiedToggles = applyToolbarOverridesToToggles(\n  toggles: IToggle[],\n  cookieStore: CookieStore\n): IToggle[];\n\n// Read toolbar state from cookies\nconst state = getToolbarStateFromCookies(\n  cookieStore: CookieStore\n): ToolbarState | null;\n```\n\n### Storage Modes Explained\n\n**`local` (default)**: Best for development workflows\n- ✅ Persists across all browser tabs\n- ✅ Survives page reloads and browser restarts\n- ✅ Set overrides once, test everywhere\n- Use case: Daily feature development and debugging\n\n**`session`**: Useful for isolated testing\n- ✅ Persists within current tab only\n- ✅ Survives page reloads in the same tab\n- ❌ Lost when tab is closed\n- Use case: Testing different configurations in multiple tabs simultaneously\n\n**`memory`**: Temporary testing only\n- ❌ Lost on every page reload\n- ❌ No persistence whatsoever\n- Use case: Quick one-off tests or strict security requirements\n\n## API Reference\n\n### Toolbar Instance\n\n```typescript\nconst toolbar = window.unleashToolbar;\n\n// Show/hide the toolbar\ntoolbar.show();\ntoolbar.hide();\n// Opens, or focuses an already-open panel, or minimizes it if focus is inside\ntoolbar.toggle();\n\n// Open with focus on a specific control\ntoolbar.show({ focus: 'search' });   // flag search box\ntoolbar.show({ focus: 'context' });  // first Context field (switches tab)\ntoolbar.show({ focus: 'panel' });    // the panel itself (default)\n\n// Get current state\nconst state = toolbar.getState();\n\n// Set flag overrides\ntoolbar.setFlagOverride('my-feature', { type: 'flag', value: true });\ntoolbar.setFlagOverride('my-variant', { type: 'variant', variantKey: 'variant-b' });\ntoolbar.setFlagOverride('my-feature', null); // Clear override\n\n// Set context overrides\ntoolbar.setContextOverride({\n  userId: 'test-user-123',\n  properties: { tier: 'premium' }\n});\n\n// Reset overrides\ntoolbar.resetOverrides();\ntoolbar.resetContextOverrides();\n\n// Cleanup\ntoolbar.destroy();\n```\n\n### Listening to Changes\n\nThe toolbar automatically triggers the Unleash SDK's `'update'` event when overrides change. Use the standard SDK pattern to listen for changes:\n\n```typescript\n// Listen to flag/context changes from the toolbar\nclient.on('update', () => {\n  console.log('Flags updated - re-evaluate your flags');\n  // Re-render your UI, re-check flags, etc.\n});\n```\n\nThis works for both toolbar changes (flag overrides, context overrides) and SDK changes (new config from server).\n\n### React Hooks\n\nUse hooks from the official `@unleash/proxy-client-react` SDK - they automatically work with toolbar overrides!\n\n```typescript\nimport {\n  useFlag,\n  useVariant,\n  useUnleashClient,\n  useUnleashContext,\n  useFlagsStatus\n} from '@unleash/proxy-client-react';\n\n// Check flag status - updates automatically when toolbar overrides change\nconst isEnabled = useFlag('my-feature');\n\n// Get variant - updates automatically when toolbar overrides change\nconst variant = useVariant('my-experiment');\n\n// Access client (the wrapped client from the toolbar)\nconst client = useUnleashClient();\n\n// Update context dynamically\nconst updateContext = useUnleashContext();\nawait updateContext({ userId: 'new-user-id' });\n\n// Check loading/ready state\nconst { flagsReady, flagsError } = useFlagsStatus();\n```\n\n### Next.js Hooks\n\nFor Next.js, import hooks from `@unleash/toolbar/next`, they're re-exported for convenience:\n\n```typescript\nimport { useFlag, useVariant, useUnleashClient } from '@unleash/toolbar/next';\n\nconst isEnabled = useFlag('my-feature');\nconst variant = useVariant('my-experiment');\n```\n\n## UI Features\n\n### Flag List Tab\n\n- **Override Controls**: Dropdown to set boolean or variant overrides\n- **Flag Info**: See default vs. effective values for each flag\n- **Quick Actions**: Reset individual flag overrides\n\n### Context Tab\n\n- **Standard Fields**: userId, sessionId, remoteAddress, environment, appName\n- **Custom Properties**: Edit or reset property values\n- **Live Updates**: Changes apply immediately to all evaluations\n\n### Header Actions\n\n- **Reset Flags**: Clear all flag overrides\n- **Reset Context**: Clear all context overrides\n- **Close**: Hide the toolbar\n\n## Keyboard & Accessibility\n\nThe toolbar is fully operable from the keyboard.\n\n### Shortcuts\n\n| Key | Action |\n| --- | --- |\n| `Cmd/Ctrl + Shift + F` | Open the panel, focus it when it is already open, or minimize it when pressed from inside |\n| `Esc` | Minimize, handing focus back to wherever you opened the panel from |\n| `Tab` / `Shift + Tab` | Move between controls; off either end, focus returns to the page where you left it |\n| `←` `→` | Switch tabs (while a tab has focus) |\n| `←` `→` | Change a flag's override between OFF / — / ON |\n\nRebind or disable the shortcut with the `shortcut` option:\n\n```javascript\ninitUnleashToolbar(client, {\n  shortcut: 'mod+shift+u', // 'mod' is Cmd on macOS, Ctrl elsewhere\n});\n\ninitUnleashToolbar(client, {\n  shortcut: false, // register no global key listener\n});\n```\n\n### Shortcut-driven setup\n\nTo render nothing until the toolbar is summoned, and land directly in the flag\nsearch box:\n\n```javascript\ninitUnleashToolbar(client, {\n  showToggleButton: false,\n  focusOnOpen: 'search',\n});\n```\n\nThe toolbar stays mounted and listening while \"closed\" — it is hidden with\n`display: none`, so there is no re-initialization cost on reopen, and it is out\nof both the tab order and the accessibility tree while hidden.\n\n> With `showToggleButton: false` **and** `shortcut: false` there is no way for a\n> user to reopen the toolbar; only the programmatic API can. Keep at least one of\n> them enabled.\n\n### Focus behaviour\n\nThe panel is not modal. The page underneath stays interactive, is never marked\n`inert`, and focus is never trapped — watching your app react to a flag change is\nthe whole point of the tool, and a keyboard user has to be able to get back out\nthere.\n\nOpened from the keyboard, focus lands on the panel itself rather than on a\ncontrol, so screen readers announce the region and its name — and the panel draws\na focus ring so sighted keyboard users can see that focus has left the page. The\nring stays off when the panel is opened by clicking the floating icon.\n\nFrom there, focus is **tethered** to wherever the panel was summoned from:\n\n- `Tab` off the last control (or `Shift+Tab` off the first) returns focus to the\n  element you opened the panel from, leaving the panel open. The next `Tab`\n  carries on through your page from that point.\n- The shortcut is the way back in. Pressed from the page with the panel open it\n  pulls focus into the panel rather than closing it; pressed from inside the\n  panel it minimizes.\n- `Esc` inside the panel minimizes and hands focus back to the same origin — or\n  to the floating icon when the icon is what opened it.\n\nWithout an origin to return to (the panel was opened by clicking the icon, or the\norigin has since been unmounted), `Tab` is left to the browser's own ordering.\n\n### Semantics\n\n- The panel is a labelled `region` landmark, so assistive tech can jump straight\n  to it regardless of where the toolbar sits in the tab order\n- Tabs use the WAI-ARIA tabs pattern, with arrow-key navigation and a roving tab stop\n- Each flag's OFF / — / ON control is a `radiogroup` labelled with the flag name,\n  so assistive tech reports which state is in effect. Its roving tab stop also\n  means a flag costs one `Tab` press to pass, not three\n- Icon-only controls carry visually hidden text rather than relying on `title`\n- Filtering the flag list announces its result count through a `status` region,\n  debounced so a burst of typing produces one announcement rather than one per\n  keystroke\n- Animations are suppressed under `prefers-reduced-motion: reduce`\n\n## Theme Customization\n\nOverride CSS variables or use the theme option:\n\n```javascript\nconst toolbar = initUnleashSessionToolbar({\n  theme: {\n    primaryColor: '#ff6b6b',\n    backgroundColor: '#ffffff',\n    textColor: '#2d3436',\n    borderColor: '#dfe6e9',\n    fontFamily: 'Inter, sans-serif',\n    focusColor: '#ff6b6b' // keyboard focus ring; optional\n  }\n});\n```\n\n### Focus ring colour\n\nThe keyboard focus ring follows `themePreset` automatically — a mid purple on\n`light`, a lighter purple on `dark`, both above the 3:1 contrast ratio WCAG\nrequires of non-text indicators. Controls on the coloured header use a white ring\ninstead, since `primaryColor` already has to be dark enough to carry the header's\nwhite text.\n\nSet `theme.focusColor` only when a custom `backgroundColor` would leave the\ndefault ring hard to see — e.g. a dark `backgroundColor` while staying on the\n`light` preset:\n\n```javascript\ninitUnleashToolbar(client, {\n  theme: { backgroundColor: '#101010', textColor: '#f5f5f5', focusColor: '#A9A6F5' },\n});\n```\n\nOr override CSS variables globally:\n\n```css\n:root {\n  --unleash-toolbar-primary: #your-color;\n  --unleash-toolbar-bg: #your-bg;\n  --unleash-toolbar-text: #your-text;\n  --unleash-toolbar-border: #your-border;\n  --unleash-toolbar-font: your-font;\n}\n```\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Build the library\nnpm run build\n\n# Run tests\nnpm test\n\n# Run tests in watch mode\nnpm run test:watch\n\n# Run tests with coverage\nnpm run test:coverage\n\n# Run type checking\nnpm run type-check\n\n# Run linter\nnpm run lint\n\n# Auto-fix linting issues\nnpm run lint:fix\n```\n\n### Example Applications\n\nThe repository includes example applications demonstrating integration with different frameworks:\n\n- **Vanilla JS** - Basic HTML/JavaScript integration\n  ```bash\n  npm run serve:example:vanilla\n  ```\n\n- **React** - Hooks and provider pattern with official React SDK\n  ```bash\n  npm run serve:example:react\n  ```\n\n- **Next.js App Router** - Server-side rendering with client and server components\n  ```bash\n  npm run serve:example:nextjs\n  ```\n\n- **Angular** - Service-based integration\n  ```bash\n  npm run serve:example:angular\n  ```\n\n- **Vue 3** - Composition API with composables\n  ```bash\n  npm run serve:example:vue\n  ```\n\nAll examples include:\n- Environment configuration setup\n- Multiple feature flags for testing\n- Variant flag demonstrations\n- Toolbar integration best practices\n- Server-side rendering examples (Next.js)\n\n## Requirements\n\n- **Browser**: Modern browsers with ES2020 support (Chrome 90+, Firefox 88+, Safari 14+)\n- **Unleash SDKs**:\n  - `unleash-proxy-client` ^3.0.0 (required)\n  - `@unleash/proxy-client-react` ^5.0.0 (optional, for React)\n  - `@unleash/nextjs` ^1.0.0 (optional, for Next.js SSR)\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nApache-2.0\n\n## Links\n\n- [Unleash Toolbar Documentation](https://docs.getunleash.io/integrate/toolbar)\n- [Unleash JavaScript SDK](https://github.com/Unleash/unleash-proxy-client-js)\n- [Unleash React SDK](https://github.com/Unleash/proxy-client-react)\n- [Unleash Next.js SDK](https://github.com/Unleash/unleash-nextjs-sdk)\n- [npm Package](https://www.npmjs.com/package/@unleash/toolbar)\n\n## Support\n\n- [GitHub Issues](https://github.com/Unleash/toolbar/issues)\n- [Unleash Slack Community](https://unleash-community.slack.com/)\n- [Unleash Documentation](https://docs.getunleash.io/)\n\n## Development\n\nDependency install scripts are disabled (`ignore-scripts=true` in `.npmrc`) as supply-chain hardening. This also skips this repo's own `prepare` script, so run `npm run prepare` manually after `npm ci`. CI and the release workflow run explicit build steps.\n","readmeFilename":"README.md"}