chartai 0.0.8 → 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"chart-library.d.ts","sourceRoot":"","sources":["../src/chart-library.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AACnD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,CAAC,EAAE,MAAM,EAAE,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,sGAAsG;IACtG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,WAAW,CAAC;IAChB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3C,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;IACH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IACtD,wCAAwC;IACxC,SAAS,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvC,qFAAqF;IACrF,UAAU,CAAC,CAAC,GAAG,EAAE,wBAAwB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvE,mFAAmF;IACnF,SAAS,CAAC,CAAC,GAAG,EAAE,wBAAwB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CACvE;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAIxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,UAAU,IAAI,SAAS,WAAW,EAAE,CAEnD;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAEjD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA6B;IAEpD,MAAM,CAAC,QAAQ,CAAC,MAAM;;;;;MAA+C;IACrE,MAAM,CAAC,QAAQ,CAAC,qBAAqB,MAAM;IAC3C,MAAM,CAAC,QAAQ,CAAC,QAAQ,OAAO;IAC/B,MAAM,CAAC,QAAQ,CAAC,QAAQ,YAAY;IACpC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,MAAM;IACxC,MAAM,CAAC,QAAQ,CAAC,YAAY,4EAC6C;IAEzE,OAAO,CAAC,MAAM,CAAC,YAAY;IAc3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,cAAc,CAAiB;IAEvC,OAAO;IAkDP,MAAM,CAAC,WAAW,IAAI,YAAY;IAOlC,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAoB9B,OAAO,CAAC,mBAAmB;IAiD3B,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IA+KnC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAmBzB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI;IA8ErD,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAU5C,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAU3D,QAAQ,CACN,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GACA,IAAI;IA2BP,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAK7C,aAAa,IAAI,MAAM;IAIvB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ;IAIjC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIjC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAQ7B,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAQ5C,QAAQ,IAAI,UAAU;IAItB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAkC3B,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAW7C,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAuBzC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CA2BtC"}
1
+ {"version":3,"file":"chart-library.d.ts","sourceRoot":"","sources":["../src/chart-library.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,MAAM,GAAG,KAAK,CAAC;AACnD,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE7D,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,CAAC,EAAE,MAAM,EAAE,CAAC;IACZ,CAAC,EAAE,MAAM,EAAE,CAAC;CACb;AAED,MAAM,WAAW,SAAS;IACxB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,SAAS,EAAE,WAAW,CAAC;IACvB,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,sGAAsG;IACtG,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,WAAW,CAAC;IACpB,EAAE,EAAE,WAAW,CAAC;IAChB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAC9B,4EAA4E;IAC5E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,CAAC;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE;YAAE,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QAC3C,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,IAAI,EAAE,MAAM,EAAE,CAAC;KAChB,CAAC,CAAC;IACH,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,IAAI,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IACnE,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2EAA2E;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,+DAA+D;IAC/D,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,SAAS,GAAG,IAAI,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,OAAO,CAAC,CAAC,KAAK,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,GAAG,IAAI,CAAC;IACtD,wCAAwC;IACxC,SAAS,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvC,qFAAqF;IACrF,UAAU,CAAC,CAAC,GAAG,EAAE,wBAAwB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;IACvE,mFAAmF;IACnF,SAAS,CAAC,CAAC,GAAG,EAAE,wBAAwB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI,CAAC;CACvE;AAID,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAIxD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGnD;AAED,wBAAgB,UAAU,IAAI,SAAS,WAAW,EAAE,CAEnD;AAED,KAAK,aAAa,GAAG,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;AAEjD,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAA6B;IAEpD,MAAM,CAAC,QAAQ,CAAC,MAAM;;;;;MAA+C;IACrE,MAAM,CAAC,QAAQ,CAAC,qBAAqB,MAAM;IAC3C,MAAM,CAAC,QAAQ,CAAC,QAAQ,OAAO;IAC/B,MAAM,CAAC,QAAQ,CAAC,QAAQ,YAAY;IACpC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,MAAM;IACxC,MAAM,CAAC,QAAQ,CAAC,YAAY,4EAC6C;IAEzE,OAAO,CAAC,MAAM,CAAC,YAAY;IAc3B,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,MAAM,CAAoC;IAClD,OAAO,CAAC,cAAc,CAAK;IAC3B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,YAAY,CAKlB;IAEF,OAAO,CAAC,kBAAkB,CAAuB;IACjD,OAAO,CAAC,cAAc,CAAiB;IAEvC,OAAO;IAkDP,MAAM,CAAC,WAAW,IAAI,YAAY;IAOlC,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,IAAI,SAAS,IAAI,OAAO,CAEvB;IAEK,IAAI,IAAI,OAAO,CAAC,OAAO,CAAC;IAwB9B,OAAO,CAAC,mBAAmB;IAiD3B,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM;IA+KnC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAmBzB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI;IA8ErD,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAU5C,qBAAqB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAU3D,QAAQ,CACN,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QACL,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,GACA,IAAI;IA2BP,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,IAAI;IAK7C,aAAa,IAAI,MAAM;IAIvB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,QAAQ;IAIjC,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAIjC,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;IAQ7B,OAAO,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,IAAI;IAQ5C,QAAQ,IAAI,UAAU;IAItB,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAkC3B,iBAAiB,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAW7C,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI;IAuBzC,SAAS,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;CA2BtC"}
@@ -14,7 +14,7 @@ var exports_worker_inline = {};
14
14
  __export(exports_worker_inline, {
15
15
  WORKER_CODE: () => WORKER_CODE
16
16
  });
17
- var WORKER_CODE = 'var a=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",r="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var W="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var C=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${r}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var L=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var D=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${r}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,_,v=new Map,w=!1,p={},g={},s=0,B=0,N=!1,U=null,R=new ArrayBuffer(112),j=new Float32Array(R),F=new Uint32Array(R),P,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},O=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(w?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([w?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,R)},E=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});g[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),g[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),_=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,E("line",C,y,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),E("box",D,H,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:L});g.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:W});g.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:_}]},primitive:{topology:"triangle-strip"}}),P=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){if(!t){postMessage({type:"error",message:`Cannot create chart ${e}: GPU device not available`});return}let x=i.getContext("webgpu");if(!x){postMessage({type:"error",message:`Cannot create chart ${e}: Failed to get WebGPU context`});return}try{x.configure({device:t,format:_,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: configure failed - ${M}`});return}let f=i.width||800,Y=i.height||400,d=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),m={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:d,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:f,height:Y,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{A(m)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,m),postMessage({type:"chart-registered",id:e})}function A(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:P}]})}function $(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{A(e);for(let l=0;l<e.series.length;l++)$(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)$(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),m=Math.PI*e.pointSize*e.pointSize;if(d*m>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)O(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/a),m=Math.min(d,65535),M=Math.ceil(d/65535),V=new Uint32Array([m*a]);t.queue.writeBuffer(e.uniformBuffer,72,V);let I=n.beginComputePass();I.setPipeline(g.scatterCompute),I.setBindGroup(0,f.computeBindGroup),I.dispatchWorkgroups(m,M),I.end()}else{O(e,f,x);let Y=e.type==="line"?g.lineCompute:g.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/a)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?g.lineRender:g.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let m=e.series[d];if(m.pointCount===0)continue;Y.setBindGroup(0,m.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(g.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function S(){if(!N)N=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)S()}function T(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)S()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(U!==null)return;U=setInterval(()=>{postMessage({type:"stats",fps:s,renderMs:B,totalCharts:v.size,activeCharts:c()}),s=0},1000)}function ee(){N=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;B=performance.now()-e,s++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(w=n.isDark||!1,await J())h();break;case"theme":w=n.isDark,T();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)S()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}S();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;T();break}};\n';
17
+ var WORKER_CODE = 'var m=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",w="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var C="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${w}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,L=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var D=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${w}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,U=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,R,v=new Map,S=!1,p={},a={},N=0,P=0,_=!1,O=null,W=new ArrayBuffer(112),j=new Float32Array(W),F=new Uint32Array(W),A,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},E=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(S?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([S?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,W)},T=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});a[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),a[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),R=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,T("line",y,L,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),T("box",H,U,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:D});a.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:C});a.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:R}]},primitive:{topology:"triangle-strip"}}),A=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){let x=t?i.getContext("webgpu"):null;if(!x){postMessage({type:"error",message:`Failed to initialize WebGPU context: ${e}`});return}try{x.configure({device:t,format:R,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Failed to configure WebGPU context: ${e}`,err:M.toString()});return}let f=t.limits.maxTextureDimension2D,Y=Math.min(Math.floor(Number(i.width)||800),f),d=Math.min(Math.floor(Number(i.height)||400),f),g=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),I={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:g,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:Y,height:d,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{$(I)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,I),postMessage({type:"chart-registered",id:e})}function $(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:A}]})}function V(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{$(e);for(let l=0;l<e.series.length;l++)V(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)V(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),g=Math.PI*e.pointSize*e.pointSize;if(d*g>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)E(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/m),g=Math.min(d,65535),I=Math.ceil(d/65535),M=new Uint32Array([g*m]);t.queue.writeBuffer(e.uniformBuffer,72,M);let r=n.beginComputePass();r.setPipeline(a.scatterCompute),r.setBindGroup(0,f.computeBindGroup),r.dispatchWorkgroups(g,I),r.end()}else{E(e,f,x);let Y=e.type==="line"?a.lineCompute:a.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/m)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?a.lineRender:a.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let g=e.series[d];if(g.pointCount===0)continue;Y.setBindGroup(0,g.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(a.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function s(){if(!_)_=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)s()}function B(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)s()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(O!==null)return;O=setInterval(()=>{postMessage({type:"stats",fps:N,renderMs:P,totalCharts:v.size,activeCharts:c()}),N=0},1000)}function ee(){_=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;P=performance.now()-e,N++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(S=n.isDark||!1,await J())h();break;case"theme":S=n.isDark,B();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)s()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}s();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;B();break}};\n';
18
18
 
19
19
  // src/chart-library.ts
20
20
  var globalPlugins = [];
@@ -124,7 +124,9 @@ class ChartManager {
124
124
  return true;
125
125
  return new Promise((resolve) => {
126
126
  Promise.resolve().then(() => exports_worker_inline).then(({ WORKER_CODE: WORKER_CODE2 }) => {
127
- const blob = new Blob([WORKER_CODE2], { type: "application/javascript" });
127
+ const blob = new Blob([WORKER_CODE2], {
128
+ type: "application/javascript"
129
+ });
128
130
  const workerUrl = URL.createObjectURL(blob);
129
131
  this.worker = new Worker(workerUrl, { type: "module" });
130
132
  this.setupWorkerHandlers(resolve);
@@ -1 +1 @@
1
- var W=Object.defineProperty;var H=(t,e)=>{for(var i in e)W(t,i,{get:e[i],enumerable:!0,configurable:!0,set:(r)=>e[i]=()=>r})};var O={};H(O,{WORKER_CODE:()=>k});var k='var a=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",r="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var W="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var C=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${r}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var L=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var D=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${r}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,_,v=new Map,w=!1,p={},g={},s=0,B=0,N=!1,U=null,R=new ArrayBuffer(112),j=new Float32Array(R),F=new Uint32Array(R),P,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},O=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(w?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([w?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,R)},E=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});g[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),g[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),_=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,E("line",C,y,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),E("box",D,H,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:L});g.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:W});g.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:_}]},primitive:{topology:"triangle-strip"}}),P=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){if(!t){postMessage({type:"error",message:`Cannot create chart ${e}: GPU device not available`});return}let x=i.getContext("webgpu");if(!x){postMessage({type:"error",message:`Cannot create chart ${e}: Failed to get WebGPU context`});return}try{x.configure({device:t,format:_,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: configure failed - ${M}`});return}let f=i.width||800,Y=i.height||400,d=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),m={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:d,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:f,height:Y,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{A(m)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,m),postMessage({type:"chart-registered",id:e})}function A(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:P}]})}function $(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{A(e);for(let l=0;l<e.series.length;l++)$(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)$(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),m=Math.PI*e.pointSize*e.pointSize;if(d*m>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)O(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/a),m=Math.min(d,65535),M=Math.ceil(d/65535),V=new Uint32Array([m*a]);t.queue.writeBuffer(e.uniformBuffer,72,V);let I=n.beginComputePass();I.setPipeline(g.scatterCompute),I.setBindGroup(0,f.computeBindGroup),I.dispatchWorkgroups(m,M),I.end()}else{O(e,f,x);let Y=e.type==="line"?g.lineCompute:g.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/a)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?g.lineRender:g.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let m=e.series[d];if(m.pointCount===0)continue;Y.setBindGroup(0,m.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(g.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function S(){if(!N)N=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)S()}function T(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)S()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(U!==null)return;U=setInterval(()=>{postMessage({type:"stats",fps:s,renderMs:B,totalCharts:v.size,activeCharts:c()}),s=0},1000)}function ee(){N=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;B=performance.now()-e,s++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(w=n.isDark||!1,await J())h();break;case"theme":w=n.isDark,T();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)S()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}S();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;T();break}};\n';var m=[];function Z(t){if(!m.some((e)=>e.name===t.name))m.push(t)}function ee(t){let e=m.findIndex((i)=>i.name===t);if(e>=0)m.splice(e,1)}function te(){return m}class x{static instance=null;static MARGIN={left:55,right:10,top:8,bottom:45};static HOVER_MAX_DISTANCE_PX=50;static MIN_ZOOM=0.1;static MAX_ZOOM=1e7;static DEFAULT_LABEL_SIZE=12;static DEFAULT_FONT='-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';static resizeCanvas(t,e,i){let r=devicePixelRatio||1;if(t.width=Math.round(e*r),t.height=Math.round(i*r),t instanceof HTMLCanvasElement)t.style.width=`${e}px`,t.style.height=`${i}px`}worker=null;charts=new Map;chartIdCounter=0;_syncViews=!1;_isDark=!1;statsCallbacks=[];currentStats={fps:0,renderMs:0,total:0,active:0};visibilityObserver;resizeObserver;constructor(){this._isDark=document.documentElement.classList.contains("dark"),this.visibilityObserver=new IntersectionObserver((t)=>{for(let e of t){let i=e.target.dataset.chartId;if(i){let r=this.charts.get(i);if(r)r.visible=e.isIntersecting,this.worker?.postMessage({type:"set-visibility",id:i,visible:e.isIntersecting})}}},{threshold:0.01}),this.resizeObserver=new ResizeObserver((t)=>{for(let e of t){let i=e.target.dataset.chartId;if(!i)continue;let r=this.charts.get(i);if(!r)continue;let{width:a,height:u}=e.contentRect;if(a<=0||u<=0)continue;r.width=a,r.height=u;let o=devicePixelRatio||1;this.worker?.postMessage({type:"resize",id:i,width:Math.round(a*o),height:Math.round(u*o)}),x.resizeCanvas(r.backCanvas,a,u),x.resizeCanvas(r.axisCanvas,a,u),this.drawChart(r)}})}static getInstance(){if(!x.instance)x.instance=new x;return x.instance}get isDark(){return this._isDark}get syncViews(){return this._syncViews}async init(){if(this.worker)return!0;return new Promise((t)=>{Promise.resolve().then(() => O).then(({WORKER_CODE:e})=>{let i=new Blob([e],{type:"application/javascript"}),r=URL.createObjectURL(i);this.worker=new Worker(r,{type:"module"}),this.setupWorkerHandlers(t)}).catch(()=>{let e=new URL("./gpu-worker.js",import.meta.url);this.worker=new Worker(e,{type:"module"}),this.setupWorkerHandlers(t)})})}setupWorkerHandlers(t){if(!this.worker)return;this.worker.onmessage=(e)=>{let{type:i,...r}=e.data;switch(i){case"gpu-ready":t(!0);break;case"error":console.error("ChartManager GPU Error:",r.message),t(!1);break;case"stats":this.currentStats={fps:r.fps,renderMs:r.renderMs,total:r.totalCharts,active:r.activeCharts};for(let a of this.statsCallbacks)a(this.currentStats);break;case"bounds-update":{let a=this.charts.get(r.id);if(a)a.bounds={minX:r.minX,maxX:r.maxX,minY:r.minY,maxY:r.maxY},this.drawChart(a);break}default:break}},this.worker.onerror=(e)=>{console.error("ChartManager Worker Error:",e),t(!1)},this.worker.postMessage({type:"init",isDark:this._isDark})}create(t){if(!this.worker)throw new Error("ChartManager not initialized. Call init() first.");let e=`chart-${++this.chartIdCounter}`,i=document.createElement("div");i.className="gpu-chart",i.dataset.chartId=e;let r=document.createElement("div");r.className="gpu-chart-canvas-wrap",r.dataset.chartId=e;let a=document.createElement("canvas");a.className="gpu-chart-back-canvas";let u=document.createElement("canvas");u.className="gpu-chart-canvas";let o=document.createElement("canvas");o.className="gpu-chart-axis-canvas",r.appendChild(a),r.appendChild(u),r.appendChild(o),i.appendChild(r),t.container.appendChild(i);let p;try{p=u.transferControlToOffscreen()}catch(d){throw console.error(`ChartManager: Failed to create offscreen canvas for ${e}:`,d),new Error(`Failed to create chart ${e}: ${d}`)}let g=r.getBoundingClientRect(),l=g.width||400,c=g.height||200;if(x.resizeCanvas(p,l,c),x.resizeCanvas(a,l,c),x.resizeCanvas(o,l,c),t.bgColor){let[d,s,v]=t.bgColor;r.style.background=`rgb(${Math.round(d*255)},${Math.round(s*255)},${Math.round(v*255)})`}let n={id:e,config:t,el:i,backCanvas:a,axisCanvas:o,width:l,height:c,series:[],bounds:{minX:0,maxX:1,minY:0,maxY:1},view:{panX:0,panY:0,zoomX:1,zoomY:1},zoomMode:t.zoomMode||"both",visible:!0,dragging:!1,bgColor:t.bgColor,textColor:t.textColor,gridColor:t.gridColor,fontFamily:t.fontFamily,momentum:null,findNearestPoint(d,s,v,_){if(this.series.length===0)return null;let z=d/v,L=s/_,h=this.bounds.maxX-this.bounds.minX,R=this.bounds.maxY-this.bounds.minY,T=h/this.view.zoomX,A=R/this.view.zoomY,C=this.bounds.minX+this.view.panX*h,V=this.bounds.minY+this.view.panY*R,M=C+z*T,$=V+(1-L)*A,w=-1,S=-1,I=1/0,E=1/0;for(let P=0;P<this.series.length;P++){let y=this.series[P],N=y.rawX.length;if(N===0)continue;let b=0,U=N-1;while(b<U){let Y=b+U>>1;if(y.rawX[Y]<M)b=Y+1;else U=Y}let B=b;if(b>0){let Y=Math.abs(y.rawX[b]-M);if(Math.abs(y.rawX[b-1]-M)<Y)B=b-1}let G=Math.abs(y.rawX[B]-M),D=Math.abs(y.rawY[B]-$);if(G<I||G===I&&D<E)I=G,E=D,w=P,S=B}if(w===-1)return null;let X=this.series[w],F=(X.rawX[S]-C)/T*v;if(Math.abs(F-d)>x.HOVER_MAX_DISTANCE_PX)return null;return{x:X.rawX[S],y:X.rawY[S],index:S,screenX:d,screenY:s,seriesIndex:w,seriesLabel:X.label}}};this.charts.set(e,n);let f=t.type==="bar"?"box":t.type;this.worker.postMessage({type:"register-chart",id:e,canvas:p,chartType:f,pointSize:t.pointSize??3,maxSamplesPerPixel:t.maxSamplesPerPixel??1e4,bgColor:t.bgColor??null},[p]),this.visibilityObserver.observe(i),this.resizeObserver.observe(r);for(let d of m)d.install?.(n,r);return this.updateSeries(e,t.series),e}destroy(t){let e=this.charts.get(t);if(!e)return;for(let r of m)r.uninstall?.(e);if(e.momentum)cancelAnimationFrame(e.momentum);this.visibilityObserver.unobserve(e.el);let i=e.el.querySelector(".gpu-chart-canvas-wrap");if(i)this.resizeObserver.unobserve(i);e.el.remove(),this.worker?.postMessage({type:"unregister-chart",id:t}),this.charts.delete(t)}updateSeries(t,e){let i=this.charts.get(t);if(!i||!this.worker)return;if(e.length===0)return;i.series=e.map((n)=>{let f=n.x.length;if(f===0)return{label:n.label,color:n.color,rawX:[],rawY:[]};let d=Array.from({length:f},(s,v)=>v);return d.sort((s,v)=>n.x[s]-n.x[v]),{label:n.label,color:n.color,rawX:d.map((s)=>n.x[s]),rawY:d.map((s)=>n.y[s])}});let r=1/0,a=-1/0,u=1/0,o=-1/0;for(let n of i.series)for(let f=0;f<n.rawX.length;f++){if(n.rawX[f]<r)r=n.rawX[f];if(n.rawX[f]>a)a=n.rawX[f];if(n.rawY[f]<u)u=n.rawY[f];if(n.rawY[f]>o)o=n.rawY[f]}let p=(a-r)*0.05||1,g=(o-u)*0.1||1;r-=p,a+=p,u-=g,o+=g;let l=i.config.defaultBounds;if(l){if(l.minX!==void 0)r=l.minX;if(l.maxX!==void 0)a=l.maxX;if(l.minY!==void 0)u=l.minY;if(l.maxY!==void 0)o=l.maxY}i.bounds={minX:r,maxX:a,minY:u,maxY:o};let c=i.series.map((n)=>({label:n.label,colorR:n.color.r,colorG:n.color.g,colorB:n.color.b,dataX:new Float32Array(n.rawX),dataY:new Float32Array(n.rawY)}));this.worker.postMessage({type:"update-series",id:t,series:c,bounds:i.bounds},c.flatMap((n)=>[n.dataX.buffer,n.dataY.buffer])),this.sendViewTransform(i),this.drawChart(i)}setPointSize(t,e){if(!this.charts.get(t))return;this.worker?.postMessage({type:"set-point-size",id:t,pointSize:Math.max(1,Math.min(8,Math.round(e)))})}setMaxSamplesPerPixel(t,e){if(!this.charts.get(t))return;this.worker?.postMessage({type:"set-max-samples",id:t,maxSamplesPerPixel:Math.max(0,e|0)})}setStyle(t,e){let i=this.charts.get(t);if(!i)return;if(e.bgColor!==void 0)i.bgColor=e.bgColor;if(e.textColor!==void 0)i.textColor=e.textColor;if(e.gridColor!==void 0)i.gridColor=e.gridColor;if(e.fontFamily!==void 0)i.fontFamily=e.fontFamily;if(e.bgColor!==void 0){let r=i.el.querySelector(".gpu-chart-canvas-wrap");if(r){let[a,u,o]=e.bgColor;r.style.background=`rgb(${Math.round(a*255)},${Math.round(u*255)},${Math.round(o*255)})`}this.worker?.postMessage({type:"set-style",id:t,bgColor:e.bgColor})}this.drawChart(i)}setZoomMode(t,e){let i=this.charts.get(t);if(i)i.zoomMode=e}getChartCount(){return this.charts.size}getZoomMode(t){return this.charts.get(t)?.zoomMode||"both"}setSyncViews(t){this._syncViews=t}setTheme(t){this._isDark=t,this.worker?.postMessage({type:"theme",isDark:t});for(let e of this.charts.values())this.drawChart(e)}onStats(t){return this.statsCallbacks.push(t),()=>{let e=this.statsCallbacks.indexOf(t);if(e>=0)this.statsCallbacks.splice(e,1)}}getStats(){return{...this.currentStats}}resetView(t){let e=this.charts.get(t);if(!e)return;if(e.momentum)cancelAnimationFrame(e.momentum),e.momentum=null;let i=e.view.panX,r=e.view.panY,a=e.view.zoomX,u=e.view.zoomY,o=performance.now(),p=()=>{let g=Math.min(1,(performance.now()-o)/300),l=1-Math.pow(1-g,3);if(e.view.panX=i*(1-l),e.view.panY=r*(1-l),e.view.zoomX=a+(1-a)*l,e.view.zoomY=u+(1-u)*l,this.sendViewTransform(e),this.drawChart(e),this._syncViews)this.syncAllViews(e);if(g<1)requestAnimationFrame(p)};requestAnimationFrame(p)}sendViewTransform(t){this.worker?.postMessage({type:"view-transform",id:t.id,panX:t.view.panX,panY:t.view.panY,zoomX:t.view.zoomX,zoomY:t.view.zoomY})}syncAllViews(t){let e=[];for(let i of this.charts.values())if(i.id!==t.id)i.view={...t.view},e.push({id:i.id}),this.drawChart(i);if(e.length>0)this.worker?.postMessage({type:"batch-view-transform",panX:t.view.panX,panY:t.view.panY,zoomX:t.view.zoomX,zoomY:t.view.zoomY,transforms:e})}drawChart(t){if(!t.visible)return;let e=devicePixelRatio||1,i=t.backCanvas.getContext("2d");if(i){i.clearRect(0,0,t.backCanvas.width,t.backCanvas.height),i.save(),i.scale(e,e);for(let a of m)a.beforeDraw?.(i,t);i.restore()}let r=t.axisCanvas.getContext("2d");if(r){r.clearRect(0,0,t.axisCanvas.width,t.axisCanvas.height),r.save(),r.scale(e,e);for(let a of m)a.afterDraw?.(r,t);r.restore()}}}export{ee as unregisterPlugin,Z as registerPlugin,te as getPlugins,x as ChartManager};
1
+ var F=Object.defineProperty;var H=(t,e)=>{for(var i in e)F(t,i,{get:e[i],enumerable:!0,configurable:!0,set:(r)=>e[i]=()=>r})};var O={};H(O,{WORKER_CODE:()=>k});var k='var m=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",w="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var C="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${w}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,L=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var D=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${w}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,U=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,R,v=new Map,S=!1,p={},a={},N=0,P=0,_=!1,O=null,W=new ArrayBuffer(112),j=new Float32Array(W),F=new Uint32Array(W),A,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},E=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(S?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([S?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,W)},T=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});a[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),a[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),R=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,T("line",y,L,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),T("box",H,U,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:D});a.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:C});a.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:R}]},primitive:{topology:"triangle-strip"}}),A=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){let x=t?i.getContext("webgpu"):null;if(!x){postMessage({type:"error",message:`Failed to initialize WebGPU context: ${e}`});return}try{x.configure({device:t,format:R,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Failed to configure WebGPU context: ${e}`,err:M.toString()});return}let f=t.limits.maxTextureDimension2D,Y=Math.min(Math.floor(Number(i.width)||800),f),d=Math.min(Math.floor(Number(i.height)||400),f),g=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),I={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:g,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:Y,height:d,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{$(I)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,I),postMessage({type:"chart-registered",id:e})}function $(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:A}]})}function V(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{$(e);for(let l=0;l<e.series.length;l++)V(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)V(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),g=Math.PI*e.pointSize*e.pointSize;if(d*g>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)E(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/m),g=Math.min(d,65535),I=Math.ceil(d/65535),M=new Uint32Array([g*m]);t.queue.writeBuffer(e.uniformBuffer,72,M);let r=n.beginComputePass();r.setPipeline(a.scatterCompute),r.setBindGroup(0,f.computeBindGroup),r.dispatchWorkgroups(g,I),r.end()}else{E(e,f,x);let Y=e.type==="line"?a.lineCompute:a.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/m)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?a.lineRender:a.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let g=e.series[d];if(g.pointCount===0)continue;Y.setBindGroup(0,g.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(a.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function s(){if(!_)_=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)s()}function B(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)s()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(O!==null)return;O=setInterval(()=>{postMessage({type:"stats",fps:N,renderMs:P,totalCharts:v.size,activeCharts:c()}),N=0},1000)}function ee(){_=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;P=performance.now()-e,N++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(S=n.isDark||!1,await J())h();break;case"theme":S=n.isDark,B();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)s()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}s();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;B();break}};\n';var m=[];function Z(t){if(!m.some((e)=>e.name===t.name))m.push(t)}function ee(t){let e=m.findIndex((i)=>i.name===t);if(e>=0)m.splice(e,1)}function te(){return m}class x{static instance=null;static MARGIN={left:55,right:10,top:8,bottom:45};static HOVER_MAX_DISTANCE_PX=50;static MIN_ZOOM=0.1;static MAX_ZOOM=1e7;static DEFAULT_LABEL_SIZE=12;static DEFAULT_FONT='-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif';static resizeCanvas(t,e,i){let r=devicePixelRatio||1;if(t.width=Math.round(e*r),t.height=Math.round(i*r),t instanceof HTMLCanvasElement)t.style.width=`${e}px`,t.style.height=`${i}px`}worker=null;charts=new Map;chartIdCounter=0;_syncViews=!1;_isDark=!1;statsCallbacks=[];currentStats={fps:0,renderMs:0,total:0,active:0};visibilityObserver;resizeObserver;constructor(){this._isDark=document.documentElement.classList.contains("dark"),this.visibilityObserver=new IntersectionObserver((t)=>{for(let e of t){let i=e.target.dataset.chartId;if(i){let r=this.charts.get(i);if(r)r.visible=e.isIntersecting,this.worker?.postMessage({type:"set-visibility",id:i,visible:e.isIntersecting})}}},{threshold:0.01}),this.resizeObserver=new ResizeObserver((t)=>{for(let e of t){let i=e.target.dataset.chartId;if(!i)continue;let r=this.charts.get(i);if(!r)continue;let{width:a,height:u}=e.contentRect;if(a<=0||u<=0)continue;r.width=a,r.height=u;let o=devicePixelRatio||1;this.worker?.postMessage({type:"resize",id:i,width:Math.round(a*o),height:Math.round(u*o)}),x.resizeCanvas(r.backCanvas,a,u),x.resizeCanvas(r.axisCanvas,a,u),this.drawChart(r)}})}static getInstance(){if(!x.instance)x.instance=new x;return x.instance}get isDark(){return this._isDark}get syncViews(){return this._syncViews}async init(){if(this.worker)return!0;return new Promise((t)=>{Promise.resolve().then(() => O).then(({WORKER_CODE:e})=>{let i=new Blob([e],{type:"application/javascript"}),r=URL.createObjectURL(i);this.worker=new Worker(r,{type:"module"}),this.setupWorkerHandlers(t)}).catch(()=>{let e=new URL("./gpu-worker.js",import.meta.url);this.worker=new Worker(e,{type:"module"}),this.setupWorkerHandlers(t)})})}setupWorkerHandlers(t){if(!this.worker)return;this.worker.onmessage=(e)=>{let{type:i,...r}=e.data;switch(i){case"gpu-ready":t(!0);break;case"error":console.error("ChartManager GPU Error:",r.message),t(!1);break;case"stats":this.currentStats={fps:r.fps,renderMs:r.renderMs,total:r.totalCharts,active:r.activeCharts};for(let a of this.statsCallbacks)a(this.currentStats);break;case"bounds-update":{let a=this.charts.get(r.id);if(a)a.bounds={minX:r.minX,maxX:r.maxX,minY:r.minY,maxY:r.maxY},this.drawChart(a);break}default:break}},this.worker.onerror=(e)=>{console.error("ChartManager Worker Error:",e),t(!1)},this.worker.postMessage({type:"init",isDark:this._isDark})}create(t){if(!this.worker)throw new Error("ChartManager not initialized. Call init() first.");let e=`chart-${++this.chartIdCounter}`,i=document.createElement("div");i.className="gpu-chart",i.dataset.chartId=e;let r=document.createElement("div");r.className="gpu-chart-canvas-wrap",r.dataset.chartId=e;let a=document.createElement("canvas");a.className="gpu-chart-back-canvas";let u=document.createElement("canvas");u.className="gpu-chart-canvas";let o=document.createElement("canvas");o.className="gpu-chart-axis-canvas",r.appendChild(a),r.appendChild(u),r.appendChild(o),i.appendChild(r),t.container.appendChild(i);let p;try{p=u.transferControlToOffscreen()}catch(d){throw console.error(`ChartManager: Failed to create offscreen canvas for ${e}:`,d),new Error(`Failed to create chart ${e}: ${d}`)}let v=r.getBoundingClientRect(),l=v.width||400,c=v.height||200;if(x.resizeCanvas(p,l,c),x.resizeCanvas(a,l,c),x.resizeCanvas(o,l,c),t.bgColor){let[d,s,g]=t.bgColor;r.style.background=`rgb(${Math.round(d*255)},${Math.round(s*255)},${Math.round(g*255)})`}let n={id:e,config:t,el:i,backCanvas:a,axisCanvas:o,width:l,height:c,series:[],bounds:{minX:0,maxX:1,minY:0,maxY:1},view:{panX:0,panY:0,zoomX:1,zoomY:1},zoomMode:t.zoomMode||"both",visible:!0,dragging:!1,bgColor:t.bgColor,textColor:t.textColor,gridColor:t.gridColor,fontFamily:t.fontFamily,momentum:null,findNearestPoint(d,s,g,_){if(this.series.length===0)return null;let z=d/g,L=s/_,G=this.bounds.maxX-this.bounds.minX,R=this.bounds.maxY-this.bounds.minY,T=G/this.view.zoomX,A=R/this.view.zoomY,C=this.bounds.minX+this.view.panX*G,V=this.bounds.minY+this.view.panY*R,M=C+z*T,W=V+(1-L)*A,w=-1,S=-1,I=1/0,N=1/0;for(let P=0;P<this.series.length;P++){let y=this.series[P],E=y.rawX.length;if(E===0)continue;let b=0,U=E-1;while(b<U){let Y=b+U>>1;if(y.rawX[Y]<M)b=Y+1;else U=Y}let B=b;if(b>0){let Y=Math.abs(y.rawX[b]-M);if(Math.abs(y.rawX[b-1]-M)<Y)B=b-1}let h=Math.abs(y.rawX[B]-M),D=Math.abs(y.rawY[B]-W);if(h<I||h===I&&D<N)I=h,N=D,w=P,S=B}if(w===-1)return null;let X=this.series[w],$=(X.rawX[S]-C)/T*g;if(Math.abs($-d)>x.HOVER_MAX_DISTANCE_PX)return null;return{x:X.rawX[S],y:X.rawY[S],index:S,screenX:d,screenY:s,seriesIndex:w,seriesLabel:X.label}}};this.charts.set(e,n);let f=t.type==="bar"?"box":t.type;this.worker.postMessage({type:"register-chart",id:e,canvas:p,chartType:f,pointSize:t.pointSize??3,maxSamplesPerPixel:t.maxSamplesPerPixel??1e4,bgColor:t.bgColor??null},[p]),this.visibilityObserver.observe(i),this.resizeObserver.observe(r);for(let d of m)d.install?.(n,r);return this.updateSeries(e,t.series),e}destroy(t){let e=this.charts.get(t);if(!e)return;for(let r of m)r.uninstall?.(e);if(e.momentum)cancelAnimationFrame(e.momentum);this.visibilityObserver.unobserve(e.el);let i=e.el.querySelector(".gpu-chart-canvas-wrap");if(i)this.resizeObserver.unobserve(i);e.el.remove(),this.worker?.postMessage({type:"unregister-chart",id:t}),this.charts.delete(t)}updateSeries(t,e){let i=this.charts.get(t);if(!i||!this.worker)return;if(e.length===0)return;i.series=e.map((n)=>{let f=n.x.length;if(f===0)return{label:n.label,color:n.color,rawX:[],rawY:[]};let d=Array.from({length:f},(s,g)=>g);return d.sort((s,g)=>n.x[s]-n.x[g]),{label:n.label,color:n.color,rawX:d.map((s)=>n.x[s]),rawY:d.map((s)=>n.y[s])}});let r=1/0,a=-1/0,u=1/0,o=-1/0;for(let n of i.series)for(let f=0;f<n.rawX.length;f++){if(n.rawX[f]<r)r=n.rawX[f];if(n.rawX[f]>a)a=n.rawX[f];if(n.rawY[f]<u)u=n.rawY[f];if(n.rawY[f]>o)o=n.rawY[f]}let p=(a-r)*0.05||1,v=(o-u)*0.1||1;r-=p,a+=p,u-=v,o+=v;let l=i.config.defaultBounds;if(l){if(l.minX!==void 0)r=l.minX;if(l.maxX!==void 0)a=l.maxX;if(l.minY!==void 0)u=l.minY;if(l.maxY!==void 0)o=l.maxY}i.bounds={minX:r,maxX:a,minY:u,maxY:o};let c=i.series.map((n)=>({label:n.label,colorR:n.color.r,colorG:n.color.g,colorB:n.color.b,dataX:new Float32Array(n.rawX),dataY:new Float32Array(n.rawY)}));this.worker.postMessage({type:"update-series",id:t,series:c,bounds:i.bounds},c.flatMap((n)=>[n.dataX.buffer,n.dataY.buffer])),this.sendViewTransform(i),this.drawChart(i)}setPointSize(t,e){if(!this.charts.get(t))return;this.worker?.postMessage({type:"set-point-size",id:t,pointSize:Math.max(1,Math.min(8,Math.round(e)))})}setMaxSamplesPerPixel(t,e){if(!this.charts.get(t))return;this.worker?.postMessage({type:"set-max-samples",id:t,maxSamplesPerPixel:Math.max(0,e|0)})}setStyle(t,e){let i=this.charts.get(t);if(!i)return;if(e.bgColor!==void 0)i.bgColor=e.bgColor;if(e.textColor!==void 0)i.textColor=e.textColor;if(e.gridColor!==void 0)i.gridColor=e.gridColor;if(e.fontFamily!==void 0)i.fontFamily=e.fontFamily;if(e.bgColor!==void 0){let r=i.el.querySelector(".gpu-chart-canvas-wrap");if(r){let[a,u,o]=e.bgColor;r.style.background=`rgb(${Math.round(a*255)},${Math.round(u*255)},${Math.round(o*255)})`}this.worker?.postMessage({type:"set-style",id:t,bgColor:e.bgColor})}this.drawChart(i)}setZoomMode(t,e){let i=this.charts.get(t);if(i)i.zoomMode=e}getChartCount(){return this.charts.size}getZoomMode(t){return this.charts.get(t)?.zoomMode||"both"}setSyncViews(t){this._syncViews=t}setTheme(t){this._isDark=t,this.worker?.postMessage({type:"theme",isDark:t});for(let e of this.charts.values())this.drawChart(e)}onStats(t){return this.statsCallbacks.push(t),()=>{let e=this.statsCallbacks.indexOf(t);if(e>=0)this.statsCallbacks.splice(e,1)}}getStats(){return{...this.currentStats}}resetView(t){let e=this.charts.get(t);if(!e)return;if(e.momentum)cancelAnimationFrame(e.momentum),e.momentum=null;let i=e.view.panX,r=e.view.panY,a=e.view.zoomX,u=e.view.zoomY,o=performance.now(),p=()=>{let v=Math.min(1,(performance.now()-o)/300),l=1-Math.pow(1-v,3);if(e.view.panX=i*(1-l),e.view.panY=r*(1-l),e.view.zoomX=a+(1-a)*l,e.view.zoomY=u+(1-u)*l,this.sendViewTransform(e),this.drawChart(e),this._syncViews)this.syncAllViews(e);if(v<1)requestAnimationFrame(p)};requestAnimationFrame(p)}sendViewTransform(t){this.worker?.postMessage({type:"view-transform",id:t.id,panX:t.view.panX,panY:t.view.panY,zoomX:t.view.zoomX,zoomY:t.view.zoomY})}syncAllViews(t){let e=[];for(let i of this.charts.values())if(i.id!==t.id)i.view={...t.view},e.push({id:i.id}),this.drawChart(i);if(e.length>0)this.worker?.postMessage({type:"batch-view-transform",panX:t.view.panX,panY:t.view.panY,zoomX:t.view.zoomX,zoomY:t.view.zoomY,transforms:e})}drawChart(t){if(!t.visible)return;let e=devicePixelRatio||1,i=t.backCanvas.getContext("2d");if(i){i.clearRect(0,0,t.backCanvas.width,t.backCanvas.height),i.save(),i.scale(e,e);for(let a of m)a.beforeDraw?.(i,t);i.restore()}let r=t.axisCanvas.getContext("2d");if(r){r.clearRect(0,0,t.axisCanvas.width,t.axisCanvas.height),r.save(),r.scale(e,e);for(let a of m)a.afterDraw?.(r,t);r.restore()}}}export{ee as unregisterPlugin,Z as registerPlugin,te as getPlugins,x as ChartManager};
@@ -303,18 +303,11 @@ function createPipelines() {
303
303
  });
304
304
  }
305
305
  function createChart(id, canvas, type, pointSize = 3, maxSamplesPerPixel = 0, bgColor = null) {
306
- if (!device) {
307
- postMessage({
308
- type: "error",
309
- message: `Cannot create chart ${id}: GPU device not available`
310
- });
311
- return;
312
- }
313
- const ctx = canvas.getContext("webgpu");
306
+ const ctx = device ? canvas.getContext("webgpu") : null;
314
307
  if (!ctx) {
315
308
  postMessage({
316
309
  type: "error",
317
- message: `Cannot create chart ${id}: Failed to get WebGPU context`
310
+ message: `Failed to initialize WebGPU context: ${id}`
318
311
  });
319
312
  return;
320
313
  }
@@ -323,12 +316,14 @@ function createChart(id, canvas, type, pointSize = 3, maxSamplesPerPixel = 0, bg
323
316
  } catch (e) {
324
317
  postMessage({
325
318
  type: "error",
326
- message: `Cannot create chart ${id}: configure failed - ${e}`
319
+ message: `Failed to configure WebGPU context: ${id}`,
320
+ err: e.toString()
327
321
  });
328
322
  return;
329
323
  }
330
- const width = canvas.width || 800;
331
- const height = canvas.height || 400;
324
+ const limit = device.limits.maxTextureDimension2D;
325
+ const width = Math.min(Math.floor(Number(canvas.width) || 800), limit);
326
+ const height = Math.min(Math.floor(Number(canvas.height) || 400), limit);
332
327
  const uniformBuffer = device.createBuffer({
333
328
  size: 112,
334
329
  usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
@@ -1 +1 @@
1
- import"./chunk-cj3zanvs.js";var a=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",r="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var W="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var C=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${r}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var L=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var D=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${r}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,_,v=new Map,w=!1,p={},g={},s=0,B=0,N=!1,U=null,R=new ArrayBuffer(112),j=new Float32Array(R),F=new Uint32Array(R),P,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},O=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(w?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([w?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,R)},E=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});g[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),g[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),_=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,E("line",C,y,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),E("box",D,H,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:L});g.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:W});g.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:_}]},primitive:{topology:"triangle-strip"}}),P=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){if(!t){postMessage({type:"error",message:`Cannot create chart ${e}: GPU device not available`});return}let x=i.getContext("webgpu");if(!x){postMessage({type:"error",message:`Cannot create chart ${e}: Failed to get WebGPU context`});return}try{x.configure({device:t,format:_,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: configure failed - ${M}`});return}let f=i.width||800,Y=i.height||400,d=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),m={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:d,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:f,height:Y,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{A(m)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,m),postMessage({type:"chart-registered",id:e})}function A(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:P}]})}function $(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{A(e);for(let l=0;l<e.series.length;l++)$(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)$(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),m=Math.PI*e.pointSize*e.pointSize;if(d*m>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)O(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/a),m=Math.min(d,65535),M=Math.ceil(d/65535),V=new Uint32Array([m*a]);t.queue.writeBuffer(e.uniformBuffer,72,V);let I=n.beginComputePass();I.setPipeline(g.scatterCompute),I.setBindGroup(0,f.computeBindGroup),I.dispatchWorkgroups(m,M),I.end()}else{O(e,f,x);let Y=e.type==="line"?g.lineCompute:g.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/a)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?g.lineRender:g.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let m=e.series[d];if(m.pointCount===0)continue;Y.setBindGroup(0,m.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(g.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function S(){if(!N)N=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)S()}function T(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)S()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(U!==null)return;U=setInterval(()=>{postMessage({type:"stats",fps:s,renderMs:B,totalCharts:v.size,activeCharts:c()}),s=0},1000)}function ee(){N=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;B=performance.now()-e,s++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(w=n.isDark||!1,await J())h();break;case"theme":w=n.isDark,T();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)S()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}S();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;T();break}};
1
+ import"./chunk-cj3zanvs.js";var m=256,X="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};",w="fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}";var C="struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}";var y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${w}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,L=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var D=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${w}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,U=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,R,v=new Map,S=!1,p={},a={},N=0,P=0,_=!1,O=null,W=new ArrayBuffer(112),j=new Float32Array(W),F=new Uint32Array(W),A,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},E=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(S?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([S?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,W)},T=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});a[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:"main"}}),a[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:"vs"},fragment:{module:x,entryPoint:"fs",targets:[{format:"rgba8unorm",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:"error",message:"WebGPU not supported"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:"error",message:"No GPU adapter found"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),R=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:"error",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:"gpu-ready"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:"write-only",format:"rgba8unorm"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"float"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}}]}),p.boxRender=p.lineRender,T("line",y,L,"line-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}}),T("box",H,U,"triangle-list",{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}});let e=t.createShaderModule({code:D});a.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:"main"}});let i=t.createShaderModule({code:C});a.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:"vs"},fragment:{module:i,entryPoint:"fs",targets:[{format:R}]},primitive:{topology:"triangle-strip"}}),A=t.createSampler({magFilter:"linear",minFilter:"linear"})}function Q(e,i,n,l=3,u=0,o=null){let x=t?i.getContext("webgpu"):null;if(!x){postMessage({type:"error",message:`Failed to initialize WebGPU context: ${e}`});return}try{x.configure({device:t,format:R,alphaMode:"premultiplied"})}catch(M){postMessage({type:"error",message:`Failed to configure WebGPU context: ${e}`,err:M.toString()});return}let f=t.limits.maxTextureDimension2D,Y=Math.min(Math.floor(Number(i.width)||800),f),d=Math.min(Math.floor(Number(i.height)||400),f),g=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),I={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:g,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:Y,height:d,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{$(I)}catch(M){postMessage({type:"error",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,I),postMessage({type:"chart-registered",id:e})}function $(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type==="scatter"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:"rgba8unorm",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:A}]})}function V(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type==="scatter"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type==="line"?p.lineCompute:p.boxCompute,u=e.type==="line"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type==="box"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type==="box"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{$(e);for(let l=0;l<e.series.length;l++)V(e,e.series[l],l)}catch(l){postMessage({type:"error",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:"error",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)V(l,l.series[u],u);postMessage({type:"bounds-update",id:e,...n})}catch(u){postMessage({type:"error",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type==="scatter"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),g=Math.PI*e.pointSize*e.pointSize;if(d*g>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)E(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type==="scatter"){let d=Math.ceil(f.visibleCount/m),g=Math.min(d,65535),I=Math.ceil(d/65535),M=new Uint32Array([g*m]);t.queue.writeBuffer(e.uniformBuffer,72,M);let r=n.beginComputePass();r.setPipeline(a.scatterCompute),r.setBindGroup(0,f.computeBindGroup),r.dispatchWorkgroups(g,I),r.end()}else{E(e,f,x);let Y=e.type==="line"?a.lineCompute:a.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/m)),d.end()}}if(e.type!=="scatter"){let x=e.type==="line"?a.lineRender:a.boxRender,f=e.type==="line"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:"load",storeOp:"store"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let g=e.series[d];if(g.pointCount===0)continue;Y.setBindGroup(0,g.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:"clear",storeOp:"store",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(a.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function s(){if(!_)_=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)s()}function B(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)s()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(O!==null)return;O=setInterval(()=>{postMessage({type:"stats",fps:N,renderMs:P,totalCharts:v.size,activeCharts:c()}),N=0},1000)}function ee(){_=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;P=performance.now()-e,N++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case"init":if(S=n.isDark||!1,await J())h();break;case"theme":S=n.isDark,B();break;case"register-chart":Q(n.id,n.canvas,n.chartType||"scatter",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case"unregister-chart":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:"chart-unregistered",id:n.id});break}case"set-point-size":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case"set-max-samples":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case"set-style":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case"update-series":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case"set-visibility":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)s()}break}case"view-transform":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case"resize":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case"batch-view-transform":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}s();break}case"sync-view":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;B();break}};
@@ -1,2 +1,2 @@
1
- export declare const WORKER_CODE = "var a=256,X=\"struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};\",r=\"fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}\";var W=\"struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}\";var C=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${r}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var L=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var D=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${r}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${a})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,_,v=new Map,w=!1,p={},g={},s=0,B=0,N=!1,U=null,R=new ArrayBuffer(112),j=new Float32Array(R),F=new Uint32Array(R),P,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},O=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(w?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([w?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,R)},E=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});g[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:\"main\"}}),g[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:\"vs\"},fragment:{module:x,entryPoint:\"fs\",targets:[{format:\"rgba8unorm\",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:\"error\",message:\"WebGPU not supported\"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:\"error\",message:\"No GPU adapter found\"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),_=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:\"error\",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:\"gpu-ready\"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"storage\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:\"read-only-storage\"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:\"write-only\",format:\"rgba8unorm\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:\"float\"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"storage\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}}]}),p.boxRender=p.lineRender,E(\"line\",C,y,\"line-list\",{color:{srcFactor:\"src-alpha\",dstFactor:\"one-minus-src-alpha\"},alpha:{srcFactor:\"one\",dstFactor:\"one-minus-src-alpha\"}}),E(\"box\",D,H,\"triangle-list\",{color:{srcFactor:\"src-alpha\",dstFactor:\"one-minus-src-alpha\"},alpha:{srcFactor:\"one\",dstFactor:\"one-minus-src-alpha\"}});let e=t.createShaderModule({code:L});g.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:\"main\"}});let i=t.createShaderModule({code:W});g.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:\"vs\"},fragment:{module:i,entryPoint:\"fs\",targets:[{format:_}]},primitive:{topology:\"triangle-strip\"}}),P=t.createSampler({magFilter:\"linear\",minFilter:\"linear\"})}function Q(e,i,n,l=3,u=0,o=null){if(!t){postMessage({type:\"error\",message:`Cannot create chart ${e}: GPU device not available`});return}let x=i.getContext(\"webgpu\");if(!x){postMessage({type:\"error\",message:`Cannot create chart ${e}: Failed to get WebGPU context`});return}try{x.configure({device:t,format:_,alphaMode:\"premultiplied\"})}catch(M){postMessage({type:\"error\",message:`Cannot create chart ${e}: configure failed - ${M}`});return}let f=i.width||800,Y=i.height||400,d=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),m={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:d,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:f,height:Y,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{A(m)}catch(M){postMessage({type:\"error\",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,m),postMessage({type:\"chart-registered\",id:e})}function A(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type===\"scatter\"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:\"rgba8unorm\",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:P}]})}function $(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type===\"scatter\"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type===\"line\"?p.lineCompute:p.boxCompute,u=e.type===\"line\"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type===\"box\"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type===\"box\"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{A(e);for(let l=0;l<e.series.length;l++)$(e,e.series[l],l)}catch(l){postMessage({type:\"error\",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:\"error\",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)$(l,l.series[u],u);postMessage({type:\"bounds-update\",id:e,...n})}catch(u){postMessage({type:\"error\",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type===\"scatter\"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),m=Math.PI*e.pointSize*e.pointSize;if(d*m>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)O(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:\"clear\",storeOp:\"store\",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type===\"scatter\"){let d=Math.ceil(f.visibleCount/a),m=Math.min(d,65535),M=Math.ceil(d/65535),V=new Uint32Array([m*a]);t.queue.writeBuffer(e.uniformBuffer,72,V);let I=n.beginComputePass();I.setPipeline(g.scatterCompute),I.setBindGroup(0,f.computeBindGroup),I.dispatchWorkgroups(m,M),I.end()}else{O(e,f,x);let Y=e.type===\"line\"?g.lineCompute:g.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/a)),d.end()}}if(e.type!==\"scatter\"){let x=e.type===\"line\"?g.lineRender:g.boxRender,f=e.type===\"line\"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:\"load\",storeOp:\"store\"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let m=e.series[d];if(m.pointCount===0)continue;Y.setBindGroup(0,m.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:\"clear\",storeOp:\"store\",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(g.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function S(){if(!N)N=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)S()}function T(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)S()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(U!==null)return;U=setInterval(()=>{postMessage({type:\"stats\",fps:s,renderMs:B,totalCharts:v.size,activeCharts:c()}),s=0},1000)}function ee(){N=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;B=performance.now()-e,s++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case\"init\":if(w=n.isDark||!1,await J())h();break;case\"theme\":w=n.isDark,T();break;case\"register-chart\":Q(n.id,n.canvas,n.chartType||\"scatter\",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case\"unregister-chart\":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:\"chart-unregistered\",id:n.id});break}case\"set-point-size\":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case\"set-max-samples\":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case\"set-style\":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case\"update-series\":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case\"set-visibility\":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)S()}break}case\"view-transform\":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case\"resize\":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case\"batch-view-transform\":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}S();break}case\"sync-view\":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;T();break}};\n";
1
+ export declare const WORKER_CODE = "var m=256,X=\"struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};\",w=\"fn lowerBound(val: f32,count: u32)-> u32{var lo = 0u;var hi = count;while(lo < hi){let mid =(lo + hi)/ 2u;if(dataX[mid] < val){lo = mid + 1u;}else{hi = mid;}}return lo;}\";var C=\"struct Uniforms{width: f32,height: f32,viewMinX: f32,viewMaxX: f32,viewMinY: f32,viewMaxY: f32,pointCount: u32,isDark: f32,bgR: f32,bgG: f32,bgB: f32,pointRadius: f32,dataMinY: f32,dataMaxY: f32,dataMinX: f32,dataMaxX: f32,visibleStart: u32,visibleCount: u32,dispatchXCount: u32,maxSamplesPerPixel: u32,seriesCount: u32,_pad2: u32,_pad3: u32,_pad4: u32,};struct SeriesInfo{color: vec4f,visibleRange: vec2u,pointSize: f32,_pad: f32,};struct SeriesIndex{index: u32,_pad0: u32,_pad1: u32,_pad2: u32,};fn l(c:vec4f)->f32{return dot(c.rgb,vec3f(.299,.587,.114))+c.a*.25;}fn fxaa(u:vec2f,t:texture_2d<f32>,s:sampler)->vec4f{let r=1./vec2f(textureDimensions(t));let rM=textureSampleLevel(t,s,u,0.);let rN=textureSampleLevel(t,s,u+vec2f(0.,-r.y),0.);let rS=textureSampleLevel(t,s,u+vec2f(0.,r.y),0.);let rE=textureSampleLevel(t,s,u+vec2f(r.x,0.),0.);let rW=textureSampleLevel(t,s,u+vec2f(-r.x,0.),0.);let lM=l(rM);let lN=l(rN);let lS=l(rS);let lE=l(rE);let lW=l(rW);let mi=min(lM,min(min(lN,lS),min(lE,lW)));let ma=max(lM,max(max(lN,lS),max(lE,lW)));let ra=ma-mi;if(ra<max(.0833,ma*.166)){return rM;}let lNW=l(textureSampleLevel(t,s,u+vec2f(-r.x,-r.y),0.));let lNE=l(textureSampleLevel(t,s,u+vec2f(r.x,-r.y),0.));let lSW=l(textureSampleLevel(t,s,u+vec2f(-r.x,r.y),0.));let lSE=l(textureSampleLevel(t,s,u+vec2f(r.x,r.y),0.));let sB=min(.35,max(0.,abs((lN+lS+lE+lW)*.25-lM)/ra-.25)*1.33);let iH=abs(lNW+lNE-2.*lN)+abs(lW+lE-2.*lM)*2.+abs(lSW+lSE-2.*lS)>=abs(lNW+lSW-2.*lW)+abs(lN+lS-2.*lM)*2.+abs(lNE+lSE-2.*lE);let l1=select(lW,lN,iH);let l2=select(lE,lS,iH);let pD=abs(l2-lM)>abs(l1-lM);let sL=select(r.x,r.y,iH);let lA=.5*(select(l1,l2,pD)+lM);let gS=max(abs(l1-lM),abs(l2-lM))*.25;var eU=u;if(iH){eU.y+=select(-.5,.5,pD)*sL;}else{eU.x+=select(-.5,.5,pD)*sL;}let eS=select(vec2f(r.x,0.),vec2f(0.,r.y),iH);var uN=eU-eS;var uP=eU+eS;var eN=l(textureSampleLevel(t,s,uN,0.))-lA;var eP=l(textureSampleLevel(t,s,uP,0.))-lA;var dN=abs(eN)>=gS;var dP=abs(eP)>=gS;for(var i=1;i<8;i++){if(!dN){uN-=eS*1.5;eN=l(textureSampleLevel(t,s,uN,0.))-lA;dN=abs(eN)>=gS;}if(!dP){uP+=eS*1.5;eP=l(textureSampleLevel(t,s,uP,0.))-lA;dP=abs(eP)>=gS;}if(dN&&dP){break;}}let dtN=select(u.x-uN.x,u.y-uN.y,iH);let dtP=select(uP.x-u.x,uP.y-u.y,iH);let eB=select(0.,.5-min(dtN,dtP)/(dtN+dtP),(lM-lA<0.)!=(select(eP<0.,eN<0.,dtN<dtP)));var fU=u;let fL=max(eB,sB);if(iH){fU.y+=select(-1.,1.,pD)*fL*sL;}else{fU.x+=select(-1.,1.,pD)*fL*sL;}return textureSampleLevel(t,s,fU,0.);}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var inputTex: texture_2d<f32>;@group(0)@binding(2)var samp: sampler;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)uv: vec2f,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var positions = array<vec2f,4>(vec2f(-1.0,-1.0),vec2f(1.0,-1.0),vec2f(-1.0,1.0),vec2f(1.0,1.0));var uvs = array<vec2f,4>(vec2f(0.0,1.0),vec2f(1.0,1.0),vec2f(0.0,0.0),vec2f(1.0,0.0));var out: VertexOutput;out.pos = vec4f(positions[vi],0.0,1.0);out.uv = uvs[vi];return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{return fxaa(in.uv,inputTex,samp);}\";var y=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> lineData: array<LineData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;${w}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){lineData[outputIdx] = LineData(-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let normY =(y - u.viewMinY)/ viewRangeY;let screenY = 1.0 - normY;let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let screenX = normX;lineData[outputIdx] = LineData(screenX,screenY,screenY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let screenX = normX;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let minScreenY = 1.0 - normMaxY;let maxScreenY = 1.0 - normMinY;lineData[outputIdx] = LineData(screenX,minScreenY,maxScreenY,1.0);}`,L=`${X}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx < maxCols){let d = lineData[segIdx];let y = select(d.maxScreenY,d.minScreenY,endpoint == 0u);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - y * 2.0,0.0,d.valid);out.alpha = d.valid;}else{let connIdx = segIdx - maxCols;if(connIdx + 1u >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let d0 = lineData[connIdx];let d1 = lineData[connIdx + 1u];let segValid = min(d0.valid,d1.valid);if(endpoint == 0u){let midY =(d0.minScreenY + d0.maxScreenY)* 0.5;out.pos = vec4f(d0.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}else{let midY =(d1.minScreenY + d1.maxScreenY)* 0.5;out.pos = vec4f(d1.screenX * 2.0 - 1.0,1.0 - midY * 2.0,0.0,segValid);}out.alpha = segValid;}return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var D=`${X}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * u.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let y = dataY[idx];if(y < u.viewMinY || y > u.viewMaxY){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let screenX = normX;let screenY = 1.0 - normY;let pixelX = i32(screenX * f32(width));let pixelY = i32(screenY * f32(height));if(idx > visStart){let prevX = dataX[idx - 1u];let prevY = dataY[idx - 1u];let prevNormX =(prevX - u.viewMinX)/ rangeX;let prevNormY =(prevY - u.viewMinY)/ rangeY;let prevPx = i32(prevNormX * f32(width));let prevPy = i32((1.0 - prevNormY)* f32(height));if(pixelX == prevPx && pixelY == prevPy){return;}}let iWidth = i32(width);let iHeight = i32(height);if(pixelX < 0 || pixelX >= iWidth){return;}if(pixelY < 0 || pixelY >= iHeight){return;}let color = series.color;let radius = i32(series.pointSize);for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){if(dx * dx + dy * dy > radius * radius){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){textureStore(outputTex,vec2i(px,py),color);}}}}`;var H=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> barData: array<BarData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;${w}fn barHalfWidth(idx: u32,count: u32)-> f32{if(count <= 1u){return(u.viewMaxX - u.viewMinX)* 0.4;}var spacing: f32;if(idx == 0u){spacing = dataX[1u] - dataX[0u];}else if(idx >= count - 1u){spacing = dataX[count - 1u] - dataX[count - 2u];}else{spacing = min(dataX[idx + 1u] - dataX[idx],dataX[idx] - dataX[idx - 1u]);}let seriesCount = max(1u,u.seriesCount);return(spacing * 0.4)/ f32(seriesCount);}@compute @workgroup_size(${m})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;let onePixel = 1.0 / u.width;if(startIdx >= endIdx){var hit = false;var bestX: f32 = 0.0;var bestY: f32 = 0.0;var bestHW: f32 = 0.0;var bestDist: f32 = 1e10;if(startIdx < count){let bx = dataX[startIdx];let hw = barHalfWidth(startIdx,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);bestX = bx;bestY = dataY[startIdx];bestHW = hw;bestDist = d;hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = barHalfWidth(prev,count);if(pixelMinX < bx + hw && pixelMaxX > bx - hw){let d = abs(bx - centerX);if(d < bestDist){bestX = bx;bestY = dataY[prev];bestHW = hw;bestDist = d;}hit = true;}}if(!hit){barData[outputIdx] = BarData(0.0,0.0,0.0,0.0);return;}let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(bestHW * 2.0);let offsetX = bestX + barOffset;let normX =(offsetX - u.viewMinX)/ viewRangeX;let fullWidth = bestHW * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);barData[outputIdx] = BarData(normX,bestY,bestY,bw);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = u.maxSamplesPerPixel;if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);}}let hw = barHalfWidth(startIdx,count);let fullWidth = hw * 2.0 / viewRangeX;let gapSize = max(onePixel,fullWidth * 0.05);let bw = max(fullWidth - gapSize,onePixel);let seriesCount = max(1u,u.seriesCount);let barOffset =(f32(seriesIdx.index)- f32(seriesCount - 1u)* 0.5)*(hw * 2.0);let dataX_centered = dataX[startIdx] + barOffset;let normX =(dataX_centered - u.viewMinX)/ viewRangeX;barData[outputIdx] = BarData(normX,dataMinY,dataMaxY,bw);}`,U=`${X}struct BarData{screenX: f32,minY: f32,maxY: f32,barWidth: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> barData: array<BarData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)normY: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;let maxCols = u32(u.width);let colIdx = vi / 6u;let vertexType = vi % 6u;if(colIdx >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let bd = barData[colIdx];if(bd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.normY = 0.0;return out;}let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let normMinY =(min(bd.minY,0.0)- u.viewMinY)/ safeRangeY;let normMaxY =(max(bd.maxY,0.0)- u.viewMinY)/ safeRangeY;let top = 1.0 - normMaxY;let bottom = 1.0 - normMinY;let halfW = bd.barWidth * 0.5;let left = bd.screenX - halfW;let right = bd.screenX + halfW;var positions = array<vec2f,6>(vec2f(left,bottom),vec2f(right,bottom),vec2f(left,top),vec2f(left,top),vec2f(right,bottom),vec2f(right,top));let screenPos = positions[vertexType];let clipX = screenPos.x * 2.0 - 1.0;let clipY = 1.0 - screenPos.y * 2.0;out.pos = vec4f(clipX,clipY,0.0,1.0);out.normY = normMaxY;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,0.85);}`;var t,R,v=new Map,S=!1,p={},a={},N=0,P=0,_=!1,O=null,W=new ArrayBuffer(112),j=new Float32Array(W),F=new Uint32Array(W),A,q=(e,i)=>{if(!e.seriesStorageBuffer||e.series.length===0)return;let n=new Float32Array(e.series.length*8),l=new Uint32Array(n.buffer);for(let u=0;u<e.series.length;u++){let o=e.series[u],x=u*8;n[x+0]=o.colorR,n[x+1]=o.colorG,n[x+2]=o.colorB,n[x+3]=1,l[x+4]=o.visibleStart,l[x+5]=o.visibleCount,n[x+6]=i?.[u]??e.pointSize,n[x+7]=0}t.queue.writeBuffer(e.seriesStorageBuffer,0,n)},E=(e,i,n,l)=>{let u=j,o=F,x=e.maxX-e.minX,f=e.maxY-e.minY,Y=e.bgColor??(S?[0.11,0.11,0.12]:[0.98,0.98,0.98]);u.set([e.width,e.height,e.minX+e.panX*x,e.minX+e.panX*x+x/e.zoomX,e.minY+e.panY*f,e.minY+e.panY*f+f/e.zoomY],0),o[6]=i.pointCount,u.set([S?1:0,...Y,l??e.pointSize,e.minY,e.maxY,e.minX,e.maxX],7),o[16]=i.visibleStart,o[17]=i.visibleCount,o[18]=0,o[19]=e.maxSamplesPerPixel,o[20]=e.series.length,t.queue.writeBuffer(e.uniformBuffer,0,W)},T=(e,i,n,l,u)=>{let o=t.createShaderModule({code:i}),x=t.createShaderModule({code:n});a[`${e}Compute`]=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Compute`]]}),compute:{module:o,entryPoint:\"main\"}}),a[`${e}Render`]=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p[`${e}Render`]]}),vertex:{module:x,entryPoint:\"vs\"},fragment:{module:x,entryPoint:\"fs\",targets:[{format:\"rgba8unorm\",blend:u}]},primitive:{topology:l}})};async function J(){if(t)return!0;if(!navigator.gpu)return postMessage({type:\"error\",message:\"WebGPU not supported\"}),!1;let e=await navigator.gpu.requestAdapter();if(!e)return postMessage({type:\"error\",message:\"No GPU adapter found\"}),!1;return t=await e.requestDevice({requiredLimits:{maxBufferSize:e.limits.maxBufferSize,maxStorageBufferBindingSize:e.limits.maxStorageBufferBindingSize}}),R=navigator.gpu.getPreferredCanvasFormat(),t.lost.then((i)=>{postMessage({type:\"error\",message:`GPU device lost: ${i.reason} - ${i.message}`})}),K(),postMessage({type:\"gpu-ready\"}),!0}function K(){p.lineCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"storage\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}}]}),p.lineRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.VERTEX,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:\"read-only-storage\"}}]}),p.scatterCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,storageTexture:{access:\"write-only\",format:\"rgba8unorm\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}}]}),p.fxaaRender=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX|GPUShaderStage.FRAGMENT,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:\"float\"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,sampler:{}}]}),p.boxCompute=t.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"storage\"}},{binding:4,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"read-only-storage\"}},{binding:5,visibility:GPUShaderStage.COMPUTE,buffer:{type:\"uniform\"}}]}),p.boxRender=p.lineRender,T(\"line\",y,L,\"line-list\",{color:{srcFactor:\"src-alpha\",dstFactor:\"one-minus-src-alpha\"},alpha:{srcFactor:\"one\",dstFactor:\"one-minus-src-alpha\"}}),T(\"box\",H,U,\"triangle-list\",{color:{srcFactor:\"src-alpha\",dstFactor:\"one-minus-src-alpha\"},alpha:{srcFactor:\"one\",dstFactor:\"one-minus-src-alpha\"}});let e=t.createShaderModule({code:D});a.scatterCompute=t.createComputePipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.scatterCompute]}),compute:{module:e,entryPoint:\"main\"}});let i=t.createShaderModule({code:C});a.fxaaRender=t.createRenderPipeline({layout:t.createPipelineLayout({bindGroupLayouts:[p.fxaaRender]}),vertex:{module:i,entryPoint:\"vs\"},fragment:{module:i,entryPoint:\"fs\",targets:[{format:R}]},primitive:{topology:\"triangle-strip\"}}),A=t.createSampler({magFilter:\"linear\",minFilter:\"linear\"})}function Q(e,i,n,l=3,u=0,o=null){let x=t?i.getContext(\"webgpu\"):null;if(!x){postMessage({type:\"error\",message:`Failed to initialize WebGPU context: ${e}`});return}try{x.configure({device:t,format:R,alphaMode:\"premultiplied\"})}catch(M){postMessage({type:\"error\",message:`Failed to configure WebGPU context: ${e}`,err:M.toString()});return}let f=t.limits.maxTextureDimension2D,Y=Math.min(Math.floor(Number(i.width)||800),f),d=Math.min(Math.floor(Number(i.height)||400),f),g=t.createBuffer({size:112,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),I={id:e,canvas:i,ctx:x,type:n,visible:!0,pointSize:l,maxSamplesPerPixel:u,series:[],uniformBuffer:g,seriesStorageBuffer:null,outputTexture:null,outputTextureView:null,fxaaBindGroup:null,width:Y,height:d,panX:0,panY:0,zoomX:1,zoomY:1,minX:0,maxX:1,minY:0,maxY:1,bgColor:o,dirty:!0};try{$(I)}catch(M){postMessage({type:\"error\",message:`Cannot create chart ${e}: resource creation failed - ${M}`});return}v.set(e,I),postMessage({type:\"chart-registered\",id:e})}function $(e){if(e.outputTexture)e.outputTexture.destroy();let i=Math.max(1,e.width),n=Math.max(1,e.height),l=e.type===\"scatter\"?GPUTextureUsage.STORAGE_BINDING|GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.RENDER_ATTACHMENT;e.outputTexture=t.createTexture({size:[i,n],format:\"rgba8unorm\",usage:l}),e.outputTextureView=e.outputTexture.createView(),e.fxaaBindGroup=t.createBindGroup({layout:p.fxaaRender,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:e.outputTextureView},{binding:2,resource:A}]})}function V(e,i,n){if(!e.seriesStorageBuffer)return;if(e.type===\"scatter\"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let l=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,l),i.computeBindGroup=t.createBindGroup({layout:p.scatterCompute,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:e.outputTextureView},{binding:4,resource:{buffer:e.seriesStorageBuffer}},{binding:5,resource:{buffer:i.seriesIndexBuffer}}]})}else{let l=e.type===\"line\"?p.lineCompute:p.boxCompute,u=e.type===\"line\"?p.lineRender:p.boxRender;if(i.lineBuffer)i.lineBuffer.destroy();if(i.lineBuffer=t.createBuffer({size:e.width*16,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX}),e.type===\"box\"){if(i.seriesIndexBuffer)i.seriesIndexBuffer.destroy();i.seriesIndexBuffer=t.createBuffer({size:16,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST});let x=new Uint32Array([n,0,0,0]);t.queue.writeBuffer(i.seriesIndexBuffer,0,x)}let o=[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.dataX}},{binding:2,resource:{buffer:i.dataY}},{binding:3,resource:{buffer:i.lineBuffer}},{binding:4,resource:{buffer:e.seriesStorageBuffer}}];if(e.type===\"box\"&&i.seriesIndexBuffer)o.push({binding:5,resource:{buffer:i.seriesIndexBuffer}});i.computeBindGroup=t.createBindGroup({layout:l,entries:o}),i.renderBindGroup=t.createBindGroup({layout:u,entries:[{binding:0,resource:{buffer:e.uniformBuffer}},{binding:1,resource:{buffer:i.lineBuffer}},{binding:2,resource:{buffer:e.seriesStorageBuffer}}]})}}function Z(e,i,n){if(i===e.width&&n===e.height)return;if(i<=0||n<=0)return;e.width=i,e.height=n,e.canvas.width=i,e.canvas.height=n;try{$(e);for(let l=0;l<e.series.length;l++)V(e,e.series[l],l)}catch(l){postMessage({type:\"error\",message:`resize failed for chart ${e.id}: ${l}`})}}function G(e,i,n){let l=v.get(e);if(!l||!t){if(!l)postMessage({type:\"error\",message:`update-series failed: chart ${e} not found`});return}try{l.minX=n.minX,l.maxX=n.maxX,l.minY=n.minY,l.maxY=n.maxY;for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}if(l.series=[],l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(i.length>0)l.seriesStorageBuffer=t.createBuffer({size:Math.max(32,i.length*32),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});for(let u of i){let o=t.createBuffer({size:Math.max(16,u.dataX.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),x=t.createBuffer({size:Math.max(16,u.dataY.byteLength),usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});t.queue.writeBuffer(o,0,u.dataX),t.queue.writeBuffer(x,0,u.dataY);let f={label:u.label,colorR:u.colorR,colorG:u.colorG,colorB:u.colorB,dataX:o,dataY:x,lineBuffer:null,seriesIndexBuffer:null,pointCount:u.dataX.length,visibleStart:0,visibleCount:u.dataX.length,computeBindGroup:null,renderBindGroup:null};l.series.push(f)}for(let u=0;u<l.series.length;u++)V(l,l.series[u],u);postMessage({type:\"bounds-update\",id:e,...n})}catch(u){postMessage({type:\"error\",message:`update-series failed for chart ${e}: ${u}`})}}function z(e){if(!e.ctx)return;if(e.width===0||e.height===0)return;if(e.series.length===0)return;let i;try{i=e.ctx.getCurrentTexture().createView()}catch{return}k(e,i)}function k(e,i){let n=t.createCommandEncoder(),l;if(e.type===\"scatter\"){let f=e.width*e.height*4;l=e.series.map((Y)=>{let d=Math.max(1,Y.visibleCount),g=Math.PI*e.pointSize*e.pointSize;if(d*g>f)return Math.max(1,Math.sqrt(f/(d*Math.PI)));return e.pointSize})}if(q(e,l),e.series.length>0)E(e,e.series[0],0);n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:\"clear\",storeOp:\"store\",clearValue:{r:0,g:0,b:0,a:0}}]}).end();for(let x=0;x<e.series.length;x++){let f=e.series[x];if(f.pointCount===0)continue;if(e.type===\"scatter\"){let d=Math.ceil(f.visibleCount/m),g=Math.min(d,65535),I=Math.ceil(d/65535),M=new Uint32Array([g*m]);t.queue.writeBuffer(e.uniformBuffer,72,M);let r=n.beginComputePass();r.setPipeline(a.scatterCompute),r.setBindGroup(0,f.computeBindGroup),r.dispatchWorkgroups(g,I),r.end()}else{E(e,f,x);let Y=e.type===\"line\"?a.lineCompute:a.boxCompute,d=n.beginComputePass();d.setPipeline(Y),d.setBindGroup(0,f.computeBindGroup),d.dispatchWorkgroups(Math.ceil(e.width/m)),d.end()}}if(e.type!==\"scatter\"){let x=e.type===\"line\"?a.lineRender:a.boxRender,f=e.type===\"line\"?Math.max(0,e.width*4-2):e.width*6,Y=n.beginRenderPass({colorAttachments:[{view:e.outputTextureView,loadOp:\"load\",storeOp:\"store\"}]});Y.setPipeline(x);for(let d=0;d<e.series.length;d++){let g=e.series[d];if(g.pointCount===0)continue;Y.setBindGroup(0,g.renderBindGroup),Y.draw(f,1,0,d)}Y.end()}let o=n.beginRenderPass({colorAttachments:[{view:i,loadOp:\"clear\",storeOp:\"store\",clearValue:{r:0,g:0,b:0,a:0}}]});if(o.setPipeline(a.fxaaRender),e.fxaaBindGroup)o.setBindGroup(0,e.fxaaBindGroup);o.draw(4),o.end(),t.queue.submit([n.finish()])}function s(){if(!_)_=!0,requestAnimationFrame(ee)}function b(e){if(e.dirty=!0,e.visible)s()}function B(){let e=!1;for(let i of v.values())if(i.dirty=!0,i.visible)e=!0;if(e)s()}function c(){let e=0;for(let i of v.values())if(i.visible&&i.width>0)e++;return e}function h(){if(O!==null)return;O=setInterval(()=>{postMessage({type:\"stats\",fps:N,renderMs:P,totalCharts:v.size,activeCharts:c()}),N=0},1000)}function ee(){_=!1;let e=performance.now();for(let i of v.values())if(i.visible&&i.dirty&&i.width>0)z(i),i.dirty=!1;P=performance.now()-e,N++}self.onmessage=async(e)=>{let{type:i,...n}=e.data;switch(i){case\"init\":if(S=n.isDark||!1,await J())h();break;case\"theme\":S=n.isDark,B();break;case\"register-chart\":Q(n.id,n.canvas,n.chartType||\"scatter\",n.pointSize??3,n.maxSamplesPerPixel??100,n.bgColor??null);{let l=v.get(n.id);if(l)b(l)}break;case\"unregister-chart\":{let l=v.get(n.id);if(l){try{l.ctx.unconfigure()}catch{}if(l.uniformBuffer.destroy(),l.seriesStorageBuffer)l.seriesStorageBuffer.destroy();if(l.outputTexture)l.outputTexture.destroy();for(let u of l.series){if(u.dataX.destroy(),u.dataY.destroy(),u.lineBuffer)u.lineBuffer.destroy();if(u.seriesIndexBuffer)u.seriesIndexBuffer.destroy()}v.delete(n.id)}postMessage({type:\"chart-unregistered\",id:n.id});break}case\"set-point-size\":{let l=v.get(n.id);if(l)l.pointSize=Math.max(1,Math.min(8,n.pointSize)),b(l);break}case\"set-max-samples\":{let l=v.get(n.id);if(l)l.maxSamplesPerPixel=Math.max(0,n.maxSamplesPerPixel|0),b(l);break}case\"set-style\":{let l=v.get(n.id);if(l){if(n.bgColor!==void 0)l.bgColor=n.bgColor;b(l)}break}case\"update-series\":{G(n.id,n.series,n.bounds);let l=v.get(n.id);if(l)b(l);break}case\"set-visibility\":{let l=v.get(n.id);if(l){if(l.visible=n.visible,n.visible&&l.dirty)s()}break}case\"view-transform\":{let l=v.get(n.id);if(l)l.panX=n.panX,l.panY=n.panY,l.zoomX=Math.max(0.1,Math.min(1e6,n.zoomX)),l.zoomY=Math.max(0.1,Math.min(1e6,n.zoomY)),b(l);break}case\"resize\":{let l=v.get(n.id);if(l&&n.width>0&&n.height>0)Z(l,n.width,n.height),b(l);break}case\"batch-view-transform\":{let l=Math.max(0.1,Math.min(1e6,n.zoomX)),u=Math.max(0.1,Math.min(1e6,n.zoomY));for(let o of n.transforms){let x=v.get(o.id);if(x)x.panX=n.panX,x.panY=n.panY,x.zoomX=l,x.zoomY=u,x.dirty=!0}s();break}case\"sync-view\":for(let l of v.values())l.panX=n.panX,l.panY=n.panY,l.zoomX=n.zoomX,l.zoomY=n.zoomY;B();break}};\n";
2
2
  //# sourceMappingURL=worker-inline.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"worker-inline.d.ts","sourceRoot":"","sources":["../src/worker-inline.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,oo5BAAoo5B,CAAC"}
1
+ {"version":3,"file":"worker-inline.d.ts","sourceRoot":"","sources":["../src/worker-inline.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,8n5BAA8n5B,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chartai",
3
- "version": "0.0.8",
3
+ "version": "0.0.9",
4
4
  "description": "tiny gpu powered charts",
5
5
  "type": "module",
6
6
  "main": "./dist/chart-library.js",