{"_id":"emberwick","_rev":"16-b9dbf0b4676110fa53236c0e728fd55f","name":"emberwick","dist-tags":{"latest":"0.11.0"},"versions":{"0.1.0":{"name":"emberwick","version":"0.1.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.1.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"dist":{"shasum":"93e9a6ae5c70815cfab718e069411807fd6e5db4","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.1.0.tgz","fileCount":14,"integrity":"sha512-w18sfzJWeB4c/d5zPk4YRD36HxW8d2VecInuCDkm/O0StL0uKsCvTK12/LFcQEO1lbmd4gFw1oQ8jEFW+wwSWQ==","signatures":[{"sig":"MEYCIQCQVowHDgC7KyXAm+9unTv9q9+Y4Fsr77VJSkHKqwPBNwIhAKCeXGZImQyeY6oT7ez+HSaJjsfIZ0eu/tjuDe6cFjRj","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":270273},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.1.0_1789565520409_0.9361111924924046","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"emberwick","version":"0.1.1","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.1.1","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app/","dist":{"shasum":"460efadd8d9f5fd6e676ccb9e152294be284fa33","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.1.1.tgz","fileCount":14,"integrity":"sha512-HsAe0xgb9ETEKPvZ9W1vuE/XRakiXEXtLsPRn124aa3ibDcfBBx4Qeg+7X2/gQoA/8ulN7asTxf5pIn7BKBNBQ==","signatures":[{"sig":"MEYCIQCZ80zJ9K/E5mKwq0SoWU1Q2LkXRp8ha30JbPJGgxE2/QIhAIisO9Wpg9NA7zYS2dvzoyTEBNiXvIVuIcBT33wuR7ZM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCID9lGilOlJF+XO/xiXdNiPEEFpKb5F+hckWcaEgJeBI/AiA3KUjmhZsY4vrRucakgxXkSjt5zf8Lmp5OJix2k4PTUQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":270318},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.1.1_1789570033045_0.41757656334882975","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"emberwick","version":"0.2.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.2.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"dist":{"shasum":"da703ff2ce5ea59ee43efb0562d9bfa48752c294","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.2.0.tgz","fileCount":14,"integrity":"sha512-CBYgOP6kaZYmcXZdrAE0Dc4gf+G0df2b9N9YqfZeF09zIzgMDHzQ9I5uMI2BYT3Ili5y+OoN0TFRGTPsxIv7lw==","signatures":[{"sig":"MEUCIQCGP+i4Le/rHGg4iD43QzbTw30vybW3JGegJvtP3qOZJQIgbjdbiwpY6b18AhegEY7tTJPYFiXUMfHblxW+HxuJB/s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIB3pTQU5e6+BOrnpj6HDmtDqtn+ULkWIHFEE2xz45Q5WAiAckXBjIyGHCdbO19nIga9p4LuM8qNnqebM3rpacrY/rg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":354991},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"5cb1ca3d302b2a27fe670ac845668e3b9149d1b0","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.2.0_1789712585002_0.7731917887693764","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"emberwick","version":"0.3.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.3.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"dist":{"shasum":"5848efda63c71fed636738a27c7c3dd5f7b918cf","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.3.0.tgz","fileCount":14,"integrity":"sha512-Z8pJaKEmP/fBpK5tfwtWqQjeShyN4DHFbfGyTWKK9RpHaOWX0bBPVhB/ewfAiOuahpvku9gC5RUUodboIvLflg==","signatures":[{"sig":"MEUCIQDFjFzMmrDRJsTCjylZGmXfHXIEvvLVYDoRyGfDKCfJAgIgYzhspYqKWuI4f20oRU1Sf87nfYNIcbi10FV11cWeocs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCGML2cyrFxegTIg9GS+Rgel1fHay+TpACCtTy4RFc7awIhANoJ9xwcKKJMc4gY8rvdImzF0mOKgQQOO9rj+f1axdXu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":366526},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"f0e01fc932b7cd47c9db9da1fc381dea44ac50a1","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.3.0_1789714630281_0.13488656108274677","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"emberwick","version":"0.4.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.4.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"dist":{"shasum":"169483089e9020c403c060f722706d5b2130d3f6","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.4.0.tgz","fileCount":14,"integrity":"sha512-zfSbPSSSOrnCIlKwtVRrTGP3YX18Oee9vfXr4XxiykbdwWcyfvW/E1HLoeJuKR/v6ixxW/bNlOH3y0GAKC5ftA==","signatures":[{"sig":"MEUCIQCtWJQM20/6AUoGGRb5jdqW3B0XPi0km20Ge0vtDwoZRQIgEdbmIzsbQeUK1oDL2ls3gmjfswkAuEC16yJVEiJzims=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDA4si/oaLQHPV+5JABhuhJAJCyHsit7XRCcabpN1FBgQIhAOpxxN1SuuygPEVUlQ5jmF4VDJ4j4q/tJNy9sfigVFFM","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":424758},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"a75c9e615529c4cbb2a19f2bf5e5e0b2981049e4","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.4.0_1789733401188_0.8444094338079791","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"emberwick","version":"0.4.1","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"license":"MIT","_id":"emberwick@0.4.1","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"dist":{"shasum":"6fa57acbe9ae71df146c5efe8a7b92aaa62bd549","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.4.1.tgz","fileCount":15,"integrity":"sha512-8CGyFrNCHvQW5udpQPBQXV6bU37XXZ6Ip97VcZBzR7xT0gdTdSQRW38G5a5T+U9M948a3vjp2kxAlB9HcYNbuw==","signatures":[{"sig":"MEYCIQCSsuWrqSbFUEgq3vdtKek2qiwiw+bgdNaZHO+rLGfDTgIhAP+cG7tqUr/ZLpVpz98Xx5sfI77x2rSkYuEgs9SnDhLu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICn37FZ+Z1NMvnziVZomGWeOvd0f0aDDdhLIvHL4N3PJAiEAwaOh7ZSoYSedCuEYU5L52VPBRgak6MYyYWc2x4A61Fo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":437821},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"ed08ac058e92ad877e661e70616744268c1f40aa","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.4.1_1789766507087_0.8617145310337107","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"emberwick","version":"0.4.2","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.4.2","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"e1d33c75a2e8ed25b845112a0057ae6b739eb60c","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.4.2.tgz","fileCount":15,"integrity":"sha512-xwifB+Olj8IN6r+mksd74p+dYqVfrXbFQ+wfm1wMUS+X+IIoDujGUK8N8TOmbFd5RqLpRqQ/86raANtBiGtd+A==","signatures":[{"sig":"MEQCICkyFhM25yqF/75wnhIlcOU+oYHSQsvZBiZvMRMxmWIqAiBT1GnsaDfb4S7GlGtlACHm6bUuFZ5XBdnVQBiMjUQfTg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIHPh7ETeDHe96LNAVII59lbkU4aal8UzrIzhoc1lCJNWAiAJDR4QHyuozzjMFmUSmXC0UE65A2T94rCc5WyQurkQHg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":438664},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"7ba2d889c400fa6e025ff0d0b3316c11f6ad0481","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.4.2_1789766912609_0.843937206612051","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"emberwick","version":"0.5.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.5.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"c3b25256561546a4ca471c895f917eb8c51abd35","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.5.0.tgz","fileCount":15,"integrity":"sha512-LqpUngbDs6ScMQq7R4zO9FW52JBK5GI+pzyAlMVoI/mSecAaHFZHa+pWxUtkRHK0NtFOcnqQydjRu4zFv0WAtA==","signatures":[{"sig":"MEQCIHzdTcyf6Bo6nwt0O0cQuNk0rxlFPmzFphkZuBTaM3i9AiAGP8Ebdle48B/vJLhpF+SVqzhqmYsetmhA7HrBmXFotA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQC5ZgGS+sTeohRMyRznD5AnrdqYqpTD/PJV0QhT2BsC/QIhANgq7A+Wq+pKYVsiyHUDDOJSPXIH+mKlTVChw4MzHiuR","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":469152},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"7ba2d889c400fa6e025ff0d0b3316c11f6ad0481","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.5.0_1789767787504_0.1824922330837908","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"emberwick","version":"0.5.1","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.5.1","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"e5e9f8ab1d1a3a1268e186ca54397f943e6d8b57","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.5.1.tgz","fileCount":15,"integrity":"sha512-2Bmk7X/PNSDHIJD265mutwOqe5fNWk8OhS8U+qdKsxbJaSiTgli7B7ylIQUHh8nioC5zCM8YXZJBh/aczaYrsg==","signatures":[{"sig":"MEUCIQCGZr5Z4aEXIoVebHpii1G59SL9j7fyOQHIsU/m6WjefQIgeqN3NpnWMoI0N3lW7hUlwNHChS3vaumATK7y+Wo5+K8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDg+/S/A4Qpa8UjAGnfnURm4rUUVE5dtcqkAEJa2Czu3AiEA6EdwcYRxzXN/OuImBEO+GNhST55VDNb7kEdxgnIIr9E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":496697},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./umd":"./umd/emberwick.umd.js","./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"7c5aaf2a4b954b24e1570107c2a2d324df217fc7","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.5.1_1789812160757_0.8523924801319118","host":"s3://npm-registry-packages-npm-production"}},"0.6.0":{"name":"emberwick","version":"0.6.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.6.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"0426ad15541d1291ffab6533008682e528848b33","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.6.0.tgz","fileCount":15,"integrity":"sha512-B9zPZYtD4EoUxK4WQAzkL44yz6enKqjhyIqn3kw/M8jQ14f7KQbm6QUtAhlciWcMPJasDS2RHJB9H7ZeY03LqA==","signatures":[{"sig":"MEQCICNUP0CeazcDBeSZMd0iHVwHj45tEwWmmBp8CiYiUAETAiA/CoFi3Z5+q7hv4N+25tqT7THjL/xXoJgd0OB2Z6nI9A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDLf0KWolsFmaXs9kaJZU5mgPWBuB3XZKThDi21aP0j+wIhAIf5wG8v9VWZN7zsberSXTf3uOFSFBEFpzstHvLN+Ayz","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":516203},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"9d7d84b849c692d86fe766ff40d00c668f1c089c","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.6.0_1789819545393_0.24051641561300396","host":"s3://npm-registry-packages-npm-production"}},"0.6.2":{"name":"emberwick","version":"0.6.2","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.6.2","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"7cb4676fe6a1d17802aec7c3ea685c55d94d94f1","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.6.2.tgz","fileCount":15,"integrity":"sha512-bRCPg7I0UK4weQkKehRNFwsQJTvVOKyqMxfsk3Uwtbe+JpEhKspV9/2P2YiqH3PvLAQURrTtV0DaB4yJVXWYdg==","signatures":[{"sig":"MEUCIApOAOuYKCrL1oKoz04TmIxI33HJAWkQV1sJ2TBN+dtsAiEAmWVWhNclM8FqrSnGU2HObBEObKseR24Zf32s9HivGcs=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQDtMcZ5reR6GZW7d3jEfyrF4NBPxmVGa5aV3TP/Mf3CNQIhAOoQYc0dCcw7ID7fNsrpgmVhL495T+A8Fp6wM6CKH5Rc","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":532893},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"222318a792ac2a699c0985a469dfe1ac83c227a0","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.6.2_1789887630624_0.4805148518485485","host":"s3://npm-registry-packages-npm-production"}},"0.7.0":{"name":"emberwick","version":"0.7.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.7.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"5b9d17c90f7b5b2dc869a85845a112aa3ccff32f","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.7.0.tgz","fileCount":15,"integrity":"sha512-LyKj2bCyLkmikbt/O+q/VGm1RNs5emljGKLsNvNU+rBbSBhtnKHLTTs00V4YG9/NmaHoei7YJZQXBQrI6zaACg==","signatures":[{"sig":"MEQCIADVsBvsQ7gwaD9HZsba9/DDD7AERX1iH/aACd600uIaAiAW5Q6lECVgE7Ok+IXLfvwcT95330J5RPm5ihq+LKoNeA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDWTXIY+A7Q0PZlpkpc+hC9mzUKObYSkT79iC3xaCNecgIgJ6QaZOTQOctcKFS7wEmHm+93fcbxkM6lTNLRSceqW9s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":586660},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"5c1255832bb8222c52884a1ff22b5861d86bb251","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.7.0_1789888151814_0.7688019475533847","host":"s3://npm-registry-packages-npm-production"}},"0.8.0":{"name":"emberwick","version":"0.8.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.8.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"8816d19c8ab0e20a2cf650d72e1b543cc35027b6","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.8.0.tgz","fileCount":15,"integrity":"sha512-NOaPS/MNZY6S/UltqoU70CbflwZxGk4DDQFvciSvOfNiIdIL6n9daAx3Lxkniaf9tgD4kdyVhaQrjPZq+j0N0g==","signatures":[{"sig":"MEQCICBbZH5ObBVmMFdVPl9TcYTb7w2HjutMlGIXgkgEfsVfAiB8qzFYn11BfYl7EE3noDwgOdbVEA4nZPBtZh6F88zyoA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIESbjrjpsxmA037RPJAML8n9JUkH2MPNKPCgumL3bHiVAiEAxdzxAiGlOG/LHAsj3Dh+8wjEl7pxxYprXxgOoUyxIaw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":615261},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"132c2362e69dad75bef18e7e46ea4c9821a45cdc","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.8.0_1789888716161_0.4324328298889064","host":"s3://npm-registry-packages-npm-production"}},"0.9.0":{"name":"emberwick","version":"0.9.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.9.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"6ce44dae666d3be3e31fc52b192cf002f0d15aaf","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.9.0.tgz","fileCount":15,"integrity":"sha512-DhQJGOy9nWSDIm6IDb92mHWGlZciYFjOlcxrqDUlbdpWJepvq9R2AqF5xrbsPgAJHbgVeywKtEFc458D077QVA==","signatures":[{"sig":"MEQCIBMiMsEUoPoyNq3DWd0MWrsLBEqjfvQNyCtXF+2NPOw0AiA6s5OAiqI7LaRrkWfSYi1vWIYPlj7ZblICJQsyqzuWHw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIBGys7BY8oxeulf7WkdlzfH/oE1kgMt5D9lTLx2rkQsRAiA0m3yn1K1GAy5EslwJ8HlyR9bjurYRRyXkQvKlb06ekA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":664469},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"071eaab7eaef8b77e5cd3645d685c21f9b4fb1bc","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.9.0_1789900089714_0.4845821130228096","host":"s3://npm-registry-packages-npm-production"}},"0.10.0":{"name":"emberwick","version":"0.10.0","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","_id":"emberwick@0.10.0","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"homepage":"https://emberwick.ldio.app","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"de3234a810e0e3803afae5e33face97955c35c8d","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.10.0.tgz","fileCount":15,"integrity":"sha512-58gZaGey8VLtK21QqhbvztiBbjJrUBs0rHZnjx297tnKjgvVmrfGlMFlZ1wlQiAVlMzASzlEzO/cUQdpB7v2Iw==","signatures":[{"sig":"MEUCIBQvlG8sMvBaNr3cl26lUOgWjXPoW3d3KwsoHgt/0YCbAiEA3FARX+y732SNVKBZp1tQaDQieQeeTyXTbjbiWzog18I=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQCQwm2cPglNzbiIn6Bbzo6LHGgwTlAWxnl1qvzQZ7On5AIgXsPLzLX+gm03qo+9L6zoB6ifrAr3nUeR3AqA8Kclfqk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":739537},"main":"./index.js","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"9894ffd02b2dd9db9b2cca96768a334b0f2ff3a5","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"jsdelivr":"./umd/emberwick.umd.js","repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/emberwick_0.10.0_1789932439988_0.22516189491234262","host":"s3://npm-registry-packages-npm-production"}},"0.11.0":{"_id":"emberwick@0.11.0","bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"dist":{"shasum":"ada06d233b415d541210afe4930f6d655d6f5db1","tarball":"https://registry.npmjs.org/emberwick/-/emberwick-0.11.0.tgz","fileCount":15,"integrity":"sha512-6foTEE0hJggBi79t63oaeX/dABC47AEb/oEk/Cr/R5dcqx3T7bRrt5wxBdxIeUu3d73xpak3ZZLoRCj11cWm1A==","signatures":[{"sig":"MEUCIHNbjeaA5q2XQXYBWRbAgNvCo4BEcSmlo7fg9Vc4obc0AiEA0VwUep/rhbxMjvVGKyAXmZJp5R/FYd7cV+3IgpWpZek=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIB86bddEwNyEPf8UsJEm5qWv5r/bPR1FLR4y3yNCOordAiBJ5y4R4KGe04MPO2mDfsTurQU1GErhgYn06tqKNpUaeA=="}],"unpackedSize":778477},"main":"./index.js","name":"emberwick","type":"module","types":"./index.d.ts","unpkg":"./umd/emberwick.umd.js","author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"module":"./index.js","engines":{"node":">=18"},"exports":{".":{"types":"./index.d.ts","import":"./index.js"},"./react":{"types":"./react.d.ts","import":"./react.js"},"./package.json":"./package.json","./webcomponent":{"types":"./webcomponent.d.ts","import":"./webcomponent.js"}},"gitHead":"9cf01a5662d0da5f51c1c6a23d7fb88ea866702b","license":"MIT","version":"0.11.0","_npmUser":{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"homepage":"https://emberwick.ldio.app","jsdelivr":"./umd/emberwick.umd.js","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"_npmVersion":"11.6.0","description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","directories":{},"maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"sideEffects":["./webcomponent.js"],"_nodeVersion":"24.9.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"peerDependencies":{"react":">=17"},"peerDependenciesMeta":{"react":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/emberwick_0.11.0_1790357024601_0.849765414185436"}}},"time":{"created":"2026-09-16T13:32:00.057Z","modified":"2026-09-25T17:23:44.851Z","0.1.0":"2026-09-16T13:32:00.527Z","0.1.1":"2026-09-16T14:47:13.151Z","0.2.0":"2026-09-18T06:23:05.119Z","0.3.0":"2026-09-18T06:57:10.476Z","0.4.0":"2026-09-18T12:10:01.301Z","0.4.1":"2026-09-18T21:21:47.200Z","0.4.2":"2026-09-18T21:28:32.734Z","0.5.0":"2026-09-18T21:43:07.604Z","0.5.1":"2026-09-19T10:02:40.845Z","0.6.0":"2026-09-19T12:05:45.476Z","0.6.2":"2026-09-20T07:00:30.702Z","0.7.0":"2026-09-20T07:09:11.922Z","0.8.0":"2026-09-20T07:18:36.278Z","0.9.0":"2026-09-20T10:28:09.839Z","0.10.0":"2026-09-20T19:27:20.076Z","0.11.0":"2026-09-25T17:23:44.705Z"},"bugs":{"url":"https://github.com/shreeshyla-hanasoge/Emberwick/issues"},"author":{"name":"Shreeshyla Hanasoge","email":"shreeshyla.hanasoge@gmail.com"},"license":"MIT","homepage":"https://emberwick.ldio.app","keywords":["candlestick","chart","charting","financial","trading","ohlc","canvas","realtime","tradingview-alternative"],"repository":{"url":"git+https://github.com/shreeshyla-hanasoge/Emberwick.git","type":"git"},"description":"Smooth flowing candlestick charts for the web — canvas-rendered, zero-dependency, pluggable data feeds.","maintainers":[{"name":"shreeshyla.hanasoge","email":"shreeshyla.hanasoge@gmail.com"}],"readme":"# Emberwick\n\nA smooth-flowing candlestick chart for the web. Canvas-rendered, framework-free,\nand driven by a pluggable data feed — drop it into any financial frontend and\npoint it at your own market data.\n\n- **Zero dependencies.** The core imports nothing but DOM and Canvas APIs.\n- **Framework-agnostic.** Works in React, Vue, Svelte, or a plain `<script type=\"module\">`.\n- **Actually smooth.** Ticks ease into the forming candle, the price axis glides\n  to new bounds, zoom is cursor-anchored and eased, panning has inertia.\n  (While a live feed is attached and the chart is following realtime, zoom\n  holds the right edge instead, so the newest candle stays put.)\n- **Fast on big data.** One `requestAnimationFrame` loop, dirty-flag driven,\n  with visible-range culling — 500k bars loaded costs only the ~200 on screen.\n- **Annotated.** Nine marker shapes, price lines and shaded zones, with\n  collision-aware stacking and hit-testing for hover and click.\n\n---\n\n## Installing\n\n### From npm\n\n```bash\nnpm install emberwick\n```\n\n```js\nimport { createChart, RandomFeed } from 'emberwick'\n```\n\n### From a CDN, no build step\n\n```html\n<div id=\"chart\" style=\"height: 480px\"></div>\n<script src=\"https://unpkg.com/emberwick/umd/emberwick.umd.js\"></script>\n<script>\n  const chart = Emberwick.createChart(document.getElementById('chart'))\n  chart.setFeed(new Emberwick.RandomFeed({ timeframe: 60000, speed: 60 }))\n</script>\n```\n\nThe UMD build is core-only and exposes the global `Emberwick`. It is for\n`<script>` tags and CDNs only — there is deliberately no `emberwick/umd`\nimport specifier, because a UMD file loaded as an ES module exports nothing\nand quietly assigns a global instead.\n\n> **Emberwick is ESM-only.** `import` works everywhere; `require('emberwick')`\n> does not, and Node reports that as `No \"exports\" main defined`. Use a dynamic\n> `await import('emberwick')` from CommonJS, or the UMD build above.\n\n### By vendoring the source\n\nNothing stops you copying the core in directly:\n\n```bash\ncp -r src/chart /path/to/your-project/src/emberwick\n```\n\n```js\nimport { createChart, RandomFeed } from './emberwick/index.js'\n```\n\nThe folder is self-contained — `src/chart/` has no imports that point outside\nitself, and no framework dependency. Anything that can bundle ES modules\n(Vite, webpack, Rollup, esbuild, or a browser with native ESM) can consume it\nas-is.\n\n### Entry points\n\n| Import | Contents |\n|---|---|\n| `emberwick` | The core: `createChart`, `Chart`, feeds, themes, motion primitives |\n| `emberwick/react` | `<EmberwickChart />` React component |\n| `emberwick/webcomponent` | Registers `<emberwick-chart>` (side-effecting import) |\n\nTypeScript declarations ship for all three entries. The UMD build is not an\nimport specifier — it is a file you point a `<script>` tag or a CDN at.\n\n---\n\n## Quick start\n\n```js\nimport { createChart, RandomFeed } from 'emberwick'\n\nconst chart = createChart(document.getElementById('chart'))\nawait chart.setFeed(new RandomFeed({ timeframe: 60_000 }))\n```\n\nThe container needs a real size — the chart fills it and follows resizes:\n\n```html\n<div id=\"chart\" style=\"width: 100%; height: 480px\"></div>\n```\n\n> The container's `position` is set to `relative` automatically if it is\n> `static`, because the canvas layers are absolutely positioned inside it.\n\nWithout a feed, push bars in directly:\n\n```js\nconst chart = createChart(el)\nchart.setData(bars)          // Bar[], ascending by time\nchart.update(formingBar)     // merge a tick into the last candle (animates)\nchart.append(newBar)         // open a new candle\n```\n\n---\n\n## The bar shape\n\nOne contract, used everywhere:\n\n```js\n{\n  time: 1737024000000,  // ms epoch, start of the bar\n  open: 100.2,\n  high: 101.4,\n  low:  99.8,\n  close: 100.9,\n  volume: 1420,\n}\n```\n\nPrices may be **numbers or numeric strings**. Plenty of real sources send\nstrings — Laravel serialises decimal columns that way, as do several exchange\nREST APIs — so they are coerced rather than rejected. Anything else (`null`,\n`undefined`, booleans, objects, `'abc'`) is not a price: it is skipped, and a\nchart with nothing plottable draws no price axis rather than inventing one.\n\nBars must be **ascending by time** and **de-duplicated**. A bar older than the\nnewest one is dropped rather than applied — an out-of-order tick would\notherwise overwrite the newest candle and leave a duplicate timestamp behind.\n\nThe chart infers the timeframe from the **median** gap between consecutive\nbars, sampled across the dataset (or takes it from `feed.timeframe`). The\nmedian rather than the first pair, because any exchange with a trading session\nputs a large gap at each day boundary — on NSE minute data, `bars[1] - bars[0]`\nacross an overnight break reads as 17.75 hours.\n\n---\n\n## Plugging in your own data — the `DataFeed` interface\n\nThis is the seam the whole library is built around. The core never knows where\nbars come from: implement two methods and it works.\n\n```js\nimport { DataFeed } from 'emberwick'\n\nclass MyApiFeed extends DataFeed {\n  constructor() {\n    super({ symbol: 'AAPL', timeframe: 60_000 })\n  }\n\n  // Historical bars ENDING at `to` (exclusive). Return [] when exhausted.\n  async getBars({ symbol, timeframe, to, limit }) {\n    const qs = new URLSearchParams({ symbol, tf: timeframe, limit })\n    if (to) qs.set('to', to)\n    const res = await fetch(`/api/candles?${qs}`)\n    return res.json()   // Bar[], ascending by time\n  }\n\n  // Live updates. Return an unsubscribe function.\n  subscribe(handler) {\n    const ws = new WebSocket('wss://example.com/stream')\n    ws.onmessage = (e) => {\n      const { bar, closed } = JSON.parse(e.data)\n      handler({ type: closed ? 'append' : 'update', bar })\n    }\n    return () => ws.close()\n  }\n}\n\nawait chart.setFeed(new MyApiFeed())\n```\n\n### Feed contract\n\n| Member | Required | Purpose |\n|---|---|---|\n| `symbol` | yes | Passed back to you in `getBars` |\n| `timeframe` | yes | Bar duration in ms; sets the chart's time axis |\n| `getBars({ symbol, timeframe, to, limit })` | yes | `Promise<Bar[]>`. `to: null` means \"most recent\". Return `[]` to signal no more history |\n| `subscribe(handler)` | for live data | Returns an unsubscribe function |\n| `prime(lastBar)` | optional | Called once after history loads, so the feed can seed its forming candle |\n| `destroy()` | optional | **Yours to call.** The chart never does: `detachFeed()` and `chart.destroy()` only run the unsubscribe that `subscribe()` returned |\n\n### Update messages\n\n```js\nhandler({ type: 'update', bar })  // forming candle changed → animates\nhandler({ type: 'append', bar })  // a new candle opened\n```\n\n`update` is the one that produces the flowing motion. Send it as often as your\nfeed ticks — 500 messages between two frames still cost exactly one repaint,\nbecause rendering is decoupled from data arrival.\n\n### Lazy history\n\nWhen the user pans to within **80 bars** of the left edge, the chart calls\n`getBars({ to: oldestLoadedTime, limit: 1000 })` and prepends the result,\nholding the view on the same bars. Return an empty array and it stops asking\npermanently. The page size is fixed at 1000; `initialBars` sizes only the\nfirst load.\n\nA rejected page is retried on the next pan and only stops being requested\nafter three consecutive failures — subscribe to `'error'` to see them.\n\n---\n\n## API\n\n### `createChart(container, options?)`\n\nReturns a `Chart`. (`new Chart(container, options)` is equivalent.)\n\n```js\nconst chart = createChart(el, {\n  theme: { background: '#000', up: '#00d68f' },\n  volumeRatio: 0.18,     // fraction of height for the volume strip\n  magnet: true,          // crosshair snaps to nearest OHLC\n  animate: true,         // live-candle easing\n  touchCrosshair: true,  // tap to place, long-press to scrub (see Touch)\n  touchCrosshairDelay: 350,  // ms a finger rests before a drag scrubs\n  initialBars: 1500,     // first getBars() page size\n  timeScale: { spacing: 9, minSpacing: 0.8, maxSpacing: 160, rightOffset: 12 },\n  priceScale: { mode: 'linear', tau: 120, marginTop: 0.12, marginBottom: 0.12 },\n\n  // Annotations can be supplied up front instead of via the setters.\n  markers: [{ time: 1717070400000, shape: 'arrowUp', text: 'BUY' }],\n  priceLines: [{ price: 148.2, title: 'target' }],\n  zones: [{ from: 143.5, to: 145.9, label: 'value area' }],\n})\n```\n\n### Methods\n\n| Method | Description |\n|---|---|\n| `setData(bars)` | Replace all bars and snap to the right edge |\n| `update(bar)` | Merge a tick into the forming candle (animated) |\n| `append(bar)` | Open a new candle |\n| `setFeed(feed)` | `async` — loads history, then subscribes. Detaches any previous feed |\n| `detachFeed()` | Unsubscribe, keep the bars on screen |\n| `subscribe(event, fn)` | Returns an unsubscribe fn. See events below |\n| `setMarkers(markers)` | Replace every marker |\n| `getMarkers()` | Current markers, normalised, each with its resolved bar index. See below |\n| `addMarker(marker)` | Append one marker |\n| `removeMarker(id)` | Remove by id |\n| `clearMarkers()` | Remove all markers |\n| `setPriceLines(lines)` | Replace every horizontal price line |\n| `setZones(zones)` | Replace every shaded region |\n| `markerAt(x, y)` | Hit-test plot coordinates, returns a marker or `null` |\n| `setTheme(partial)` | Merge theme keys and repaint |\n| `setPriceMode(mode)` | `'linear'` or `'log'` |\n| `setAnimate(bool)` | Toggle live-candle easing |\n| `setMagnet(bool)` | Toggle crosshair OHLC snapping |\n| `visibleRange()` | The window currently on screen — the same payload the `'visibleRange'` event carries |\n| `snapToRealtime()` | Jump back to the newest bar and re-enable autoscale |\n| `startReplay(options?)` | Begin bar-by-bar playback. Returns the `Replay`, or `null` if there is nothing to replay |\n| `stopReplay()` | Leave replay and reveal the whole dataset again |\n| `replayState()` | Current playback state. `{ active: false, ... }` when not replaying |\n| `chart.replay` | Getter — the active `Replay` controller, or `null` |\n| `toImage()` | PNG data URL of the composited layers |\n| `fitContent()` | Zoom and scroll so the whole dataset is on screen. Not animated |\n| `setVisibleRange({ from, to })` | Open on a window of it instead — inclusive bar indices. Not animated |\n| `setTimeZone(zone)` | Format every rendered timestamp in an IANA zone, or `null` for local |\n| `hideCrosshair()` | Dismiss a crosshair a tap or long-press left standing. No-op on mouse |\n| `resize()` | Re-measure the container now. Resizes and pixel-ratio changes are automatic |\n| `resume()` | Restart the render loop after it gave up. See below |\n| `destroy()` | Remove listeners, stop the loop, drop canvases |\n| `chart.fps` | Getter — measured frames per second |\n\n### Events\n\n```js\nconst off = chart.subscribe('crosshair', (payload) => {\n  if (!payload) return           // pointer is on no pane\n  const { index, bar, price, pane } = payload   // `price` is in THAT pane's scale\n  legend.textContent = `O ${bar.open} H ${bar.high} L ${bar.low} C ${bar.close}`\n})\noff()  // unsubscribe\n```\n\n| Event | Payload |\n|---|---|\n| `'crosshair'` | `{ index, bar, price, pane }`, or `null` when the pointer is on no pane — off the plot, on the time axis, or in the seam between two |\n| `'markerHover'` | The marker under the pointer, or `null` when none is |\n| `'markerClick'` | The clicked marker. Only fires on a hit, never with `null` |\n| `'visibleRange'` | `{ from, to, fromTime, toTime, barCount, spacing, settled }` |\n| `'replay'` | `{ active, playing, index, length, progress, speed, time, bar, atEnd }` |\n| `'error'` | The thrown value from a failed feed read. See below |\n\nA drag that happens to end on top of a marker does not fire `'markerClick'` —\npanning and clicking stay distinct.\n\n### Feed errors\n\n`getBars()` is your code, so it can reject — a 502, an expired token, an\naborted request. Both paths that call it (`setFeed()` and the lazy history\npaging) route a rejection to `'error'` rather than letting it escape as an\nunhandled rejection:\n\n```js\nchart.subscribe('error', (err) => {\n  toast('Could not load market data')\n  console.error(err)\n})\n```\n\nWith no `'error'` subscriber the failure is logged to the console instead of\nvanishing. `setFeed()` itself never rejects, so `await chart.setFeed(feed)`\nis safe to leave unguarded; subscribe to `'error'` to react to the failure.\n\nA failed history page retries on the next pan, and stops being requested only\nafter three consecutive failures — one transient 500 does not permanently\ndisable lazy history.\n\n### Frame errors\n\n`'error'` also fires if the render loop gives up. A single throwing frame is\nrecovered automatically: the pending layers are put back and the frame is\nretried. Ten *consecutive* failures — a lost canvas context, say — stop the\nloop instead of spinning at 60fps, and that is reported here:\n\n```js\nchart.subscribe('error', (err) => {\n  console.error(err)\n  // once the cause is dealt with:\n  chart.resume()\n})\n```\n\n`resume()` returns `false` if the chart is destroyed or the loop is already\nrunning, so it is safe to call blindly. Nothing else revives a stopped loop —\nnot even `invalidate()` — because a chart on a live feed would otherwise\nre-enter the failure on every tick.\n\n### Tracking the visible range\n\n`'visibleRange'` is a **state** event rather than a notification, which makes it\nusable without any debouncing of your own:\n\n- A new subscriber is called **immediately** with the current window, so it\n  never has to wait for the user to pan before it knows what is on screen.\n- It then fires **only when the window actually changes**. Indices are\n  integers, so a slow pan at 9px/bar produces roughly one event every nine\n  frames, not one per frame.\n- `spacing` is reported but is deliberately *not* part of the change test — it\n  is a float that moves every frame of an eased zoom, and keying on it would\n  turn this into a 60/sec firehose. Use it for level-of-detail decisions.\n- `settled` *is* part of the change test, so the final event of a gesture\n  always arrives with `settled: true`. That makes \"wait until the view stops\n  moving, then do the expensive thing\" a safe pattern.\n\n```js\nconst off = chart.subscribe('visibleRange', async (r) => {\n  // paginate backwards when the user approaches the left edge\n  if (r.from < 50 && r.settled && r.fromTime) {\n    const older = await myApi.bars({ to: r.fromTime, limit: 500 })\n    chart.setData(older.concat(chart.bars))\n  }\n})\n```\n\nSyncing a second chart is the other common use — feed `fromTime`/`toTime`\nstraight into the other instance. And `chart.visibleRange()` returns the same\npayload on demand if you would rather poll than subscribe.\n\n> The chart also paginates backwards **on its own** through\n> `feed.getBars({ to })` whenever you have attached a feed. This event is for\n> when you want to drive that yourself, or to drive something other than data.\n\n---\n\n## Replay\n\nPlay a fixed dataset back bar by bar — backtesting playback, a market-open\nrecap, a training drill.\n\n```js\nchart.setData(bars)\n\nconst replay = chart.startReplay({ from: 200, speed: 4 })\nreplay.play()\n\nchart.subscribe('replay', (s) => {\n  scrubber.value = s.index\n  clock.textContent = new Date(s.time).toLocaleTimeString()\n  if (s.atEnd) playBtn.textContent = 'Restart'\n})\n```\n\nThe chart is never put into a special mode. The controller keeps the dataset\naside and hands the chart only the **revealed prefix**, so scales, crosshair,\nannotations and `'visibleRange'` behave exactly as they do on live data that\nhappens to end at the cursor.\n\nRevealing the next bar goes through the same path a feed tick takes, so the\ncandle grows in and the axis glides. Scrubbing swaps the prefix and jumps —\neasing a scrub would read as lag, the same rule the pan gesture follows.\n\n### `chart.startReplay(options?)`\n\n| Option | Default | Notes |\n|---|---|---|\n| `bars` | the chart's current bars | The dataset to replay. Never mutated |\n| `from` | midpoint | Starting cursor index |\n| `speed` | `1` | Multiplier, clamped to `0.25`–`500` |\n| `baseInterval` | `1000` | Real ms one bar takes at 1× |\n| `loop` | `false` | Restart at the end instead of stopping |\n| `follow` | `true` | Re-anchor the right edge on the cursor when scrubbing |\n\nReturns the `Replay`, or `null` when there are fewer than two bars. While a\nreplay is active an attached feed is ignored, so live ticks cannot fight the\ncursor; `stopReplay()` restores the full dataset and resumes normal service.\n\n`setData()` also ends a replay — new data means the dataset being replayed no\nlonger exists. The controller you were handed is detached at that point and\nits transport methods become no-ops, so check `chart.replay` rather than\nholding the old reference. Calling `startReplay()` twice detaches the first\ncontroller the same way.\n\n### Transport\n\nEvery method returns the controller, so calls chain.\n\n| Method | Description |\n|---|---|\n| `play()` / `pause()` / `toggle()` | Pressing play at the end restarts from the beginning |\n| `seek(index)` | Move the cursor. Out-of-range values clamp |\n| `step(n = 1)` | Relative move; `step(-1)` goes back a bar |\n| `toStart()` / `toEnd()` | Jump to either end |\n| `setSpeed(x)` | Clamped to `0.25`–`500`. Never bursts bars on a rate change |\n| `setLoop(bool)` | Toggle looping |\n\nReadable state: `index`, `length`, `progress` (0–1), `speed`, `time`, `bar`,\n`atEnd`, `playing`, and `interval` (real ms between bars at the current\nspeed).\n\n### The `'replay'` event\n\n`{ active, playing, index, length, progress, speed, time, bar, atEnd }`.\n\nLike `'visibleRange'` it is a **state** event: a new subscriber is called\nimmediately, and after `stopReplay()` it fires once with `active: false` so a\nUI can reset itself without special-casing teardown. `chart.replayState()`\nreturns the same payload on demand.\n\n**Markers after the cursor are hidden, not clamped.** Time→index resolution\nsnaps to the nearest bar, so without that filter every future trade would pile\nonto the newest revealed candle — and a replay that shows you tomorrow's\nentries is worse than no replay at all.\n\nThe cursor never goes below index 1: the scales infer the timeframe from the\nfirst pair of bars.\n\n---\n\n## Series\n\nCandles are not the only thing worth drawing on a price axis. A **series** is\nan arbitrary y-value over the same time axis — a moving average, a VWAP, an\nequity curve, a band.\n\n```js\nchart.setSeries('ema20', {\n  data: [{ time: 1717070400000, value: 148.2 }, ...],\n  color: '#c084fc',\n})\nchart.setSeries('sma50', { data: sma50, color: '#38bdf8', lineWidth: 1 })\n```\n\nSeries are **keyed**, so updating one leaves the rest alone — a panel of\ntwelve indicators does not rebuild eleven of them to toggle the twelfth.\nInsertion order is draw order, and they paint over the candles but under\nprice lines and markers.\n\n| Method | Description |\n|---|---|\n| `setSeries(id, options)` | Create, or update in place. Omit `data` to change only presentation |\n| `setSeriesData(id, points)` | Replace the points, keep the options |\n| `setSeriesVisible(id, bool)` | Hide without discarding. Hidden series do not autoscale |\n| `removeSeries(id)` | Drop one |\n| `clearSeries()` | Drop all |\n| `getSeries()` | Each series' resolved options, in draw order |\n\n| Option | Default | Notes |\n|---|---|---|\n| `data` | — | `{ time, value }[]`. `time` is ms epoch, resolved to the nearest bar |\n| `pane` | `'price'` | Which pane draws it. Throws if that pane does not exist |\n| `color` | `theme.textStrong` | |\n| `lineWidth` | `1.5` | |\n| `lineStyle` | `'solid'` | `'solid'`, `'dashed'`, `'dotted'` |\n| `stepped` | `false` | Draw as a step function instead of interpolating |\n| `visible` | `true` | |\n| `title` | — | Passthrough metadata for `getSeries()`. Never drawn |\n\n### Gaps\n\n**A point with no value lifts the pen.** `value` absent, `null`, or anything\nnon-numeric ends the current line; the next valued point starts a fresh one.\n\n```js\nchart.setSeries('rsi', { data: [\n  { time: t0, value: 55.2 },\n  { time: t1 },              // no value here — the line breaks\n  { time: t2, value: 61.8 },\n]})\n```\n\nThis is the one design decision worth stating plainly: a missing value is\n**never** drawn as zero and **never** interpolated across. An indicator with\nno value during its warm-up period is not an indicator sitting at zero, and a\nline that quietly connects across a gap is a line that lies about the data.\n\n### Scale\n\nVisible series widen the price scale along with the bars, so a value outside\nthe candle range is in view rather than clipped at the edge. Hidden series are\nexcluded from that. Points more than one timeframe outside the loaded bar\nrange are not drawn at all, on the same reasoning as markers.\n\nSeries share the price axis with the candles. An equity curve at 200,000\nagainst a price around 100 will technically render, but the candles will be a\nflat line — a second pane with its own scale is the answer, and it does not\nexist yet.\n\n---\n\n## Panes\n\nAn oscillator cannot share a scale with a price. RSI lives on 0–100 and MACD\naround zero; put either on a chart of an instrument trading at 24,000 and the\ncandles collapse into a flat line.\n\nA **pane** is a horizontal band with its own price scale, sharing the time\naxis with every other pane.\n\n```js\nchart.addPane('rsi', { weight: 1 })\nchart.setSeries('rsi14', { data: points, pane: 'rsi', color: '#c084fc' })\n```\n\n| Method | Description |\n|---|---|\n| `addPane(id, options)` | Add a band below the existing ones. Returns its `PaneInfo` |\n| `removePane(id)` | Remove it, and every series routed to it |\n| `panes()` | Every pane, top to bottom. `panes()[0]` is always the price pane |\n| `pane(id)` | One pane, or `null` |\n| `paneScale(id)` | That pane's live `PriceScale` |\n| `paneRect(id)` | A copy of its rect, in CSS px |\n\n| Option | Default | Notes |\n|---|---|---|\n| `weight` | `1` | Flex share of the plot height. The price pane is `3` |\n| `minHeight` | `40` | Floor in CSS px |\n| `priceScale` | chart's | This pane's scale options |\n| `title` | — | Passthrough metadata. Not drawn |\n\n`'price'` is the pane candles, volume, markers, price lines and zones always\ndraw on. It cannot be removed, and it is always the top band.\n\n**An unknown pane id throws.** Defaulting to the price pane would put an RSI at\n50 through a 24,000 scale and flatten the candles — exactly the failure panes\nexist to prevent, arriving with no error at all.\n\nA pane whose series are all hidden, or which has none, draws no axis rather\nthan inventing one — the same rule the price pane follows with no bars.\n\n### Migrating from `chart.ps` and `chart.plot`\n\nBoth still work and still address the price pane. `paneScale('price')` and\n`paneRect('price')` are the replacements, and they say which pane they mean:\n\n```js\nconst y = chart.paneScale('rsi').y(70)     // where 70 sits in the RSI pane\nconst band = chart.paneRect('rsi')         // { x, y, w, h }\n```\n\nOne difference worth knowing: `chart.plot` is a live rect mutated in place, so\na reference held across a resize stays correct. `paneRect()` returns a copy.\n\n---\n\n## Annotations\n\nThree independent collections, each replaced wholesale. Zones paint behind the\ncandles; price lines and markers paint in front.\n\n```js\nchart.setMarkers([\n  { time: 1717070400000, shape: 'arrowUp',   text: 'BUY 120',\n    data: { orderId: 'A-7741' } },\n  { time: 1717074000000, shape: 'flag',      text: 'Earnings', color: '#c084fc' },\n  { time: 1717077600000, shape: 'arrowDown', text: 'SELL 160' },\n])\n\nchart.setPriceLines([\n  { price: 148.20, title: 'target', color: '#26a69a' },\n  { price: 141.05, title: 'stop', lineStyle: 'dotted' },\n])\n\nchart.setZones([\n  { from: 143.5, to: 145.9, label: 'value area' },\n])\n\nchart.subscribe('markerClick', (m) => openTicket(m.data.orderId))\n```\n\n### Markers\n\nA marker is pinned to a **timestamp**, not a bar index, and resolves to the\nnearest bar. Load an older page of history and every marker re-resolves, so\nnothing drifts off its candle.\n\nSupply your own `id` if you have one. A generated id is derived from the\nmarker's own identity rather than its array position, so passing the same\nmarkers to `setMarkers()` twice yields the same ids and an id captured for\n`removeMarker()` stays valid.\n\nA marker more than one timeframe outside the loaded range is **hidden**, not\nclamped to the end bar. A trade from six months before the loaded window is\nnot an event that happened at the left edge of the chart, and drawing it there\nis worse than not drawing it at all. Page that history in and it appears.\n\n| Field | Default | Notes |\n|---|---|---|\n| `time` | *required* | ms since epoch, snapped to the closest bar |\n| `id` | derived | Stable across calls — see below |\n| `id` | generated | Needed for `removeMarker(id)` |\n| `shape` | `'circle'` | See the list below |\n| `position` | shape-dependent | `'aboveBar'`, `'belowBar'`, `'inBar'`, `'atPrice'` |\n| `price` | — | Only used when `position` is `'atPrice'` |\n| `color` | `theme.up` / `theme.down` | Down-pointing shapes default to the down colour |\n| `text` | — | Short caption. For `'label'` it is drawn inside the pill |\n| `textColor` | theme | Caption colour |\n| `size` | `1` | Scale factor |\n| `data` | — | Anything. Handed straight back on hover and click |\n\nShapes: `arrowUp`, `arrowDown`, `triangleUp`, `triangleDown`, `circle`,\n`square`, `diamond`, `flag`, `label`.\n\nPosition defaults follow the trading convention: up-pointing shapes sit\n*below* the bar, down-pointing shapes *above* it, everything else above.\n\n**When `index` is resolved.** `getMarkers()` hands back the normalised\nmarkers, but time→index resolution happens in the render frame, not in\n`setMarkers()`. Call them back to back and every `index` is still `-1`; it is\npopulated after the next frame. `-1` also means *deliberately hidden* — a\nmarker more than one timeframe outside the loaded range resolves to `-1`\nrather than clamping onto an end bar — so treat it as \"not drawn\", not as\n\"not yet known\".\n\n**Ids.** Supply your own, or let one be derived from the marker's identity\n(time, shape, and which duplicate it is). Derived ids are stable across\n`setMarkers()` calls, page loads and two charts showing the same data, so an\nid captured for `removeMarker()` stays valid.\n\n**Overlap and density.** Markers sharing a bar are stacked rather than drawn on\ntop of each other. Once a candle body is 3px wide or less — around 5.6px per\nbar, since a body is 72% of the slot — dense runs thin to roughly one marker\nper 4px — a thousand trades stay legible and stay fast. A marker on the\nforming candle anchors to the animated values, so it flows with the live bar.\n\n### Price lines\n\n| Field | Default | Notes |\n|---|---|---|\n| `price` | *required* | |\n| `color` | `theme.textStrong` | |\n| `lineStyle` | `'dashed'` | `'solid'`, `'dashed'`, `'dotted'` |\n| `lineWidth` | `1` | |\n| `lineVisible` | `true` | `false` keeps the title pill and axis tag but draws no rule |\n| `title` | — | Pill drawn at the left end |\n| `axisLabel` | `true` | Price tag on the axis |\n\n### Zones\n\nSupply `from`/`to` for a **price band** spanning the full width, or\n`fromTime`/`toTime` for a **time band** spanning the full height.\n\n| Field | Default | Notes |\n|---|---|---|\n| `from` / `to` | — | Price band bounds. Non-finite values are skipped silently |\n| `fromTime` / `toTime` | — | Time band bounds, ms epoch, resolved to the nearest bar |\n| `color` | theme-derived | Fill |\n| `border` | — | Stroke around the band; omitted when unset |\n| `label` | — | Drawn at the top-left corner of the band |\n\n```js\nchart.setZones([\n  { from: 143.5, to: 145.9, label: 'value area' },\n  { fromTime: 1717070400000, toTime: 1717074000000,\n    color: 'rgba(239,83,80,0.07)', border: 'rgba(239,83,80,0.3)' },\n])\n```\n\nAutoscale fits the **bars**, not the annotations — a price line far outside the\ndata range is simply off-screen. Derive extreme values from the visible range\nif you need them guaranteed visible.\n\n---\n\n## Time zones\n\nAxis labels and the crosshair read in the browser's local zone by default.\nPass a zone when the instrument's session is defined somewhere else:\n\n```js\nconst chart = createChart(el, { timeZone: 'Asia/Kolkata' })\nchart.setTimeZone('UTC')   // or change it later\n```\n\nAn NSE chart then opens at 09:15 whoever is reading it. This is **display\nonly** — bar times, the crosshair payload, `visibleRange()` and marker times\nstay in the ms epochs you supplied.\n\nThe first label of each new day shows the date rather than the time, in the\nsame zone. Without that, a multi-day intraday chart is a wall of times with no\nindication of where one session ends — a day boundary is only midnight for\ninstruments that trade through it, which intraday ones do not.\n\n---\n\n## Fitting the view\n\n```js\nchart.setData(bars)\nchart.fitContent()\n```\n\nThe opening move for a finished dataset — a backtest, a replay tape — where\nthe useful first view is the whole run rather than the last hundred bars at\nthe default zoom. It is deliberately **not** animated: easing 4,000 bars from\n9px each down to 0.2 reads as a glitch, not as polish.\n\nFitting is allowed to zoom out past `timeScale.minSpacing` and lowers it to\nmatch. That bound exists to stop a wheel gesture burying the chart in mush; an\nexplicit \"show me everything\" is a different intent, and clamping it would\nboth hide part of the dataset and make the next zoom-in jump back up to the\nold floor.\n\n### A window of it, instead\n\n```js\nchart.setData(bars)                            // all 29,105 of them\nchart.setVisibleRange({ from: 0, to: 99 })     // open on the first hundred\n```\n\nFor a run you mean to read **forward**. Fitting a finished backtest whole is\nthe honest view of the dataset and a useless first impression: 29,000 bars\nacross an 832px plot is 0.03px each, every series collapses onto every other,\nand the trade markers thin to one per four pixels. The rest of the run stays\nloaded and pannable — this is a view, not a filter.\n\nInclusive bar indices, `to` at the right edge. Ends outside the loaded data\nclamp, a reversed pair is swapped, and a one-bar window widens to two; `false`\ncomes back only when there is no window to set at all — a destroyed chart,\nfewer than two bars loaded, or ends that are not numbers. So a call that raced\nthe data load is loud rather than quietly showing some other window.\n\nThe chart stops following new bars unless `to` is the newest one. A window\npinned at the start of a live feed would otherwise be re-targeted by the very\nnext candle, which on a 29,000-bar set moves it thousands of bars on the first\nframe.\n\nZooming *in* never reaches `minSpacing`, so unlike `fitContent()` this\nnormally leaves the interactive floor alone. A window **wider** than that\nfloor allows still lowers it, for the same reason fitContent does: clamping\nwould show a different window from the one you named and still report success.\n\nThere is one floor it will not go below, and one case it therefore cannot\nhonour exactly: a window needing less than 0.02px per bar — wider than about\n41,600 bars on an 832px plot — is truncated from the left and still returns\n`true`. `fitContent()` on a dataset that size does the same thing, and a\nwindow that wide has nothing legible in it either way.\n\n> Reading the window back is not the identity of setting it. `visibleRange()`\n> reports every bar with any pixel on screen, so it answers a bar or two wider\n> than the window you set — save what you *set*, not what you read.\n\n---\n\n## Interaction\n\n| Input | Action |\n|---|---|\n| Drag in any pane | Pan, in both axes — time for every pane, price for the pane under the pointer (inertia on release is horizontal only) |\n| Wheel | Zoom, anchored on the cursor |\n| Two-finger pinch | Zoom |\n| Drag price axis | Stretch the price scale of the pane beside the pointer |\n| Drag time axis | Zoom the time scale |\n| Double-click in a pane | Reset both: default zoom, every pane's scale back to autoscale, snap to realtime |\n| Double-click an axis | Reset just that one — the price gutter returns its own pane to autoscale, the time axis resets the time scale |\n| `←` / `→` | Pan (hold `Shift` for a bigger step) |\n| `+` / `-` | Zoom |\n\nThe container gets `tabindex=\"0\"` if it has none, so keyboard nav works\nwithout extra markup.\n\n### Touch\n\nA finger cannot hover. On a mouse the crosshair tracks a pointer that is\nmerely *over* the chart and panning needs a button held, so the two gestures\nnever collide; on touch the only way to move the pointer at all is to be\ntouching, which is also the pan gesture. Emberwick separates them in time\ninstead:\n\n| Gesture | Action |\n|---|---|\n| Tap | Place the crosshair there. It stays after the finger lifts |\n| Long-press, then drag | Scrub — the crosshair follows the finger and the chart does not pan |\n| Drag straight away | Pan, exactly as a mouse drag does. The crosshair is hidden for the gesture |\n| Two-finger pinch | Zoom, and dismiss the crosshair |\n\nA crosshair placed by tap or long-press is *sticky*: it outlives the gesture,\nbecause a reader who taps a bar wants to read it after lifting their finger.\nDismiss it with a pan, a pinch, or `chart.hideCrosshair()`.\n\n```js\ncreateChart(el, {\n  touchCrosshair: true,      // default. false restores one-finger pan-and-track\n  touchCrosshairDelay: 350,  // ms a finger must rest before a drag scrubs\n})\n```\n\nMovement under 10px is treated as a tap rather than a pan, since a resting\nfinger drifts. A long press on the price or time gutter is still an axis\ndrag — the crosshair has nothing to say out there. Stylus input hovers, so\n`pointerType: 'pen'` follows the mouse path, not this one.\n\n---\n\n## Theming\n\nPass any subset of the theme keys; the rest fall back to `defaultTheme`.\n\n```js\nimport { defaultTheme, lightTheme } from 'emberwick'\n\nchart.setTheme(lightTheme)\nchart.setTheme({ up: '#00d68f', down: '#ff5c5c', background: '#0b0e14' })\n```\n\nAvailable keys: `background`, `grid`, `axisLine`, `text`, `textStrong`, `up`,\n`down`, `upFill`, `downFill`, `wickUp`, `wickDown`, `volumeUp`, `volumeDown`,\n`crosshair`, `labelBg`, `labelText`, `tagText`, `font`, `priceAxisWidth`,\n`timeAxisHeight`.\n\n---\n\n## Framework integration\n\n### React — the bundled adapter\n\n```jsx\nimport { EmberwickChart } from 'emberwick/react'\nimport { RandomFeed } from 'emberwick'\nimport { useMemo, useRef } from 'react'\n\nexport function Chart() {\n  // Memoise the feed — a new instance re-loads history.\n  const feed = useMemo(() => new RandomFeed({ timeframe: 60_000, speed: 60 }), [])\n  const ref = useRef(null)\n\n  return (\n    <div style={{ height: 480 }}>\n      <EmberwickChart\n        ref={ref}\n        feed={feed}\n        priceMode=\"linear\"\n        theme={{ up: '#00d68f' }}\n        onCrosshair={(p) => p && console.log(p.bar)}\n      />\n      <button onClick={() => ref.current.chart.snapToRealtime()}>Realtime</button>\n    </div>\n  )\n}\n```\n\nProps: `data`, `feed`, `options`, `theme`, `priceMode`, `animate`, `magnet`,\n`onCrosshair`, `className`, `style`. Any other prop is spread onto the host\n`<div>`. The ref exposes `{ chart }` for imperative calls.\n\nThe component creates the chart **once** and drives it through its methods on\nprop changes — it never rebuilds the canvas, so pan/zoom position and animation\nstate survive re-renders. `data` is compared by **content**, not identity, so\npassing an inline array literal is safe: an unchanged array is ignored, a moved\nlast bar is merged as a tick, and bars appended to the same history are\nappended rather than re-anchoring the view. Only a genuinely different dataset\nsnaps back to the right edge.\n\n`options` is read once, when the chart is created. Change `theme`, `priceMode`,\n`animate` or `magnet` through their own props instead. `destroy()` runs on unmount, so React 18 StrictMode\ndouble-mounting is safe.\n\n### React — by hand\n\nThe adapter is ~100 lines of `useEffect`; doing it yourself is fine:\n\n```jsx\nimport { useEffect, useRef } from 'react'\nimport { createChart, RandomFeed } from 'emberwick'\n\nexport function Chart() {\n  const hostRef = useRef(null)\n\n  useEffect(() => {\n    const chart = createChart(hostRef.current)\n    const feed = new RandomFeed({ timeframe: 60_000 })\n    chart.setFeed(feed)\n    return () => { feed.destroy(); chart.destroy() }\n  }, [])\n\n  return <div ref={hostRef} style={{ width: '100%', height: 480 }} />\n}\n```\n\n### Web Component — works in any framework\n\n```html\n<script type=\"module\">\n  import 'emberwick/webcomponent'\n  import { RandomFeed } from 'emberwick'\n\n  const el = document.querySelector('emberwick-chart')\n  el.feed = new RandomFeed({ timeframe: 60000, speed: 60 })\n  el.addEventListener('crosshair', (e) => console.log(e.detail))\n</script>\n\n<emberwick-chart theme=\"dark\" style=\"height: 480px\"></emberwick-chart>\n```\n\n| | |\n|---|---|\n| Attributes | `theme=\"dark\\|light\"`, `animate=\"false\"`, `magnet=\"false\"` |\n| Properties | `feed`, `data`, `chart` (read-only) |\n| Events | `crosshair` — `event.detail` is the payload or `null` |\n\nThe element renders into a shadow root, so host-page CSS can't reposition the\nstacked canvases. Assigning `feed`/`data` before the element upgrades is safe.\nThis is the path for Vue, Svelte, Angular or server-rendered templates without\na framework-specific wrapper.\n\n### Vue 3\n\nA chart is created once and driven imperatively — there is no Vue adapter\nbecause there is nothing for one to do. `createChart()` in `onMounted`,\n`destroy()` in `onBeforeUnmount`, and the instance is the API.\n\nStore it in a plain variable or a `shallowRef`, never a `ref()`. A Chart\ndeclares Vue's `__v_skip`, so Vue will not deep-proxy it even if it lands in\nreactive state — but the **bar array you pass in** is still yours to protect.\nDeep reactivity over tens of thousands of bars, on an object repainting at\n60fps, is the one performance cliff worth knowing about here.\n\n```vue\n<script setup>\nimport { onMounted, onBeforeUnmount, ref } from 'vue'\nimport { createChart, RandomFeed } from 'emberwick'\n\nconst host = ref(null)\nlet chart, feed\n\nonMounted(() => {\n  chart = createChart(host.value)\n  feed = new RandomFeed({ timeframe: 60_000 })\n  chart.setFeed(feed)\n})\nonBeforeUnmount(() => { feed?.destroy(); chart?.destroy() })\n</script>\n\n<template><div ref=\"host\" style=\"width: 100%; height: 480px\" /></template>\n```\n\n### Plain HTML\n\n```html\n<div id=\"chart\" style=\"height: 480px\"></div>\n<script type=\"module\">\n  import { createChart, RandomFeed } from 'emberwick'\n  const chart = createChart(document.getElementById('chart'))\n  chart.setFeed(new RandomFeed({ timeframe: 60_000 }))\n</script>\n```\n\n---\n\n## `RandomFeed` — synthetic data for development\n\nBundled so you can build UI before your backend exists. It's an ordinary\n`DataFeed` implementation with no special privileges.\n\n```js\nnew RandomFeed({\n  symbol: 'EMBR',\n  timeframe: 60_000,\n  seed: 7,              // deterministic: same seed → same chart\n  start: 100,           // starting price\n  volatility: 0.0022,\n  drift: 0.00002,\n  ticksPerSecond: 8,    // live update rate\n  speed: 1,             // time multiplier; 60 = one candle per second\n})\n```\n\nRuntime controls: `setSpeed(n)`, `setTicksPerSecond(n)`, `setPaused(bool)`,\n`paused` (getter), `stop()`, `destroy()`.\n\nSet `speed: 60` to see the flowing motion immediately instead of waiting a\nminute per candle.\n\n---\n\n## Exports\n\n```js\nimport {\n  createChart, Chart,           // entry point\n  DataFeed, RandomFeed,         // data layer\n  defaultTheme, lightTheme,     // themes\n  TimeScale, PriceScale,        // scales (advanced)\n  Smoothed, Tween, Inertia,     // motion primitives\n  LiveCandle,\n  Replay, MIN_SPEED, MAX_SPEED, // bar-by-bar playback\n  easeOutCubic, easeInOutCubic,\n  mulberry32,                   // seeded PRNG\n  version,\n} from 'emberwick'\n```\n\n---\n\n## How the motion works\n\nThree independent mechanisms, which is why it reads as smooth rather than\nmerely animated:\n\n1. **Live candle** — each of O/H/L/C eases toward the incoming tick over\n   ~55ms, with the wick clamped so it can't invert mid-chase. A brand new\n   candle plays a short grow-from-centre animation as it scrolls in.\n2. **Price axis** — autoscale bounds are smoothed, so a spike glides the axis\n   instead of jolting it and losing the reader's place.\n3. **Time axis** — `spacing` (zoom) and `right` (edge position) are smoothed,\n   so wheel zoom eases and new bars slide in. **Dragging deliberately does\n   not ease** — easing a drag feels like lag, not polish.\n\nAll of it runs through `Smoothed`, a frame-rate-independent exponential\nsmoother: the same visual speed at 30fps and 144fps. The render loop returns\nwhether anything is still animating, so a static chart idles at zero CPU.\n\nRendering is split across three stacked canvases — `base` (grid + axes),\n`main` (candles + volume), `overlay` (crosshair) — so moving the pointer\nrepaints only the crosshair, never the candles underneath. All contexts are\npre-scaled by `devicePixelRatio`, so drawing code works in CSS pixels and\noutput stays crisp on retina.\n\n---\n\n## Building the package\n\nThe repo is both the library and its playground. The playground is an ordinary\nVite app (`npm run dev` / `npm run build`); the library has its own builds.\n\n```bash\nnpm run build:lib    # ESM, multi-entry  -> dist-lib/{index,react,webcomponent}.js\nnpm run build:umd    # minified UMD      -> dist-lib/umd/emberwick.umd.js\nnpm run pack:lib     # manifest + README + .d.ts into dist-lib/\nnpm run size         # gzipped size budget check\nnpm run release      # all four, in order\nnpm publish ./dist-lib   # publish the assembled directory — note the ./\n```\n\n> The leading `./` is required. `npm publish dist-lib` makes npm look for a\n> *registry package* named `dist-lib` and fail with `E404`.\n\nPublishing from `dist-lib/` keeps the playground, the build configs and the\napp's private `package.json` out of the artifact. `package.lib.json` is the\nmanifest that becomes the published `package.json`.\n\nReact is an **optional peer dependency**, external in every build — importing\n`emberwick` never pulls React in.\n\nSource layout:\n\n```\nsrc/chart/                  the library core (zero deps, no framework)\n  core/      Chart, Layers, Loop, TimeScale, PriceScale, palette, formatters\n  render/    grid, candles, crosshair, annotations\n  motion/    Tween (Smoothed), Inertia, LiveCandle\n  overlays/  annotations (normalise, resolve, collision layout)\n  replay/    Replay (bar-by-bar playback)\n  data/      DataFeed (the seam), RandomFeed\n  index.js   public API surface   index.d.ts  types\nsrc/adapters/react/         <EmberwickChart /> + dataPlan (framework-agnostic)\nsrc/adapters/webcomponent/  <emberwick-chart>\nsrc/pages/, src/App.jsx, src/styles.css   the playground (not published)\ntest/                       node --test, no jsdom (not published)\n```\n\n---\n\n## Known gaps\n\nHonest list of what isn't there yet:\n\n- **No OHLCV legend in the package.** `subscribe('crosshair', fn)` gives you\n  the hovered bar and the pane it is in; rendering the readout is still yours\n  to do.\n- **Markers are not draggable.** They are hit-tested for hover and click, but\n  there is no drag-to-move or editing interaction.\n- **No indicator maths.** Emberwick draws the line you hand it — see\n  [Series](#series) and [Panes](#panes) — but computing SMA/EMA/RSI/MACD is\n  yours. Drawing tools (trendlines, Fib) are not implemented.\n- **Panes are not resizable or reorderable.** Heights come from `weight` and\n  `minHeight` and are fixed at layout; there is no drag handle between bands,\n  and no way to reweight or move a pane short of `removePane()` and adding it\n  again — which drops every series routed to it.\n- **Annotations live on the price pane.** Markers, price lines and zones take\n  a time and a price and draw against the candles; there is no `pane` option\n  that would put a level at RSI 70.\n- **Candlesticks only, as a price type.** No Heikin-Ashi, and no area or\n  baseline fills — a series is a stroked line.\n- **No session awareness.** The time axis is indexed by bar, not by clock, so\n  weekends and overnight closes collapse to an ordinary bar step — which is\n  usually what you want. What is missing is the deliberate half: sessions are\n  never collapsed *on purpose*, and there are no session bounds to fit or snap\n  to. (Session boundaries are at least legible: the first axis label of each\n  new day shows the date, in the configured zone.)\n- **`RandomFeed` deep history is per-page coherent, not one continuous walk** —\n  each page re-seeds from its own start time and opens near the feed's `start`\n  price rather than at the neighbouring page's close, so paging far left can\n  show a visible seam. Real feeds don't have this artifact.\n- **Types are hand-written**, not generated from source, and nothing in CI\n  checks them against the implementation — so they can drift.\n- **No `require()`.** The manifest declares an `import` condition and no\n  `require` one, so CommonJS gets `No \"exports\" main defined`. Use\n  `await import('emberwick')`, or the UMD build — which is a real script-tag\n  bundle, just not an import specifier. See [Installing](#installing).\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}