@chartgpu/chartgpu 0.2.5
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.
- package/LICENSE +21 -0
- package/README.md +208 -0
- package/dist/ChartGPU.d.ts +146 -0
- package/dist/ChartGPU.d.ts.map +1 -0
- package/dist/components/createAnnotationConfigDialog.d.ts +24 -0
- package/dist/components/createAnnotationConfigDialog.d.ts.map +1 -0
- package/dist/components/createDataZoomSlider.d.ts +14 -0
- package/dist/components/createDataZoomSlider.d.ts.map +1 -0
- package/dist/components/createLegend.d.ts +9 -0
- package/dist/components/createLegend.d.ts.map +1 -0
- package/dist/components/createTextOverlay.d.ts +17 -0
- package/dist/components/createTextOverlay.d.ts.map +1 -0
- package/dist/components/createTooltip.d.ts +12 -0
- package/dist/components/createTooltip.d.ts.map +1 -0
- package/dist/components/formatTooltip.d.ts +19 -0
- package/dist/components/formatTooltip.d.ts.map +1 -0
- package/dist/config/OptionResolver.d.ts +137 -0
- package/dist/config/OptionResolver.d.ts.map +1 -0
- package/dist/config/defaults.d.ts +56 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/types.d.ts +553 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/core/GPUContext.d.ts +242 -0
- package/dist/core/GPUContext.d.ts.map +1 -0
- package/dist/core/RenderScheduler.d.ts +174 -0
- package/dist/core/RenderScheduler.d.ts.map +1 -0
- package/dist/core/createAnimationController.d.ts +15 -0
- package/dist/core/createAnimationController.d.ts.map +1 -0
- package/dist/core/createRenderCoordinator.d.ts +78 -0
- package/dist/core/createRenderCoordinator.d.ts.map +1 -0
- package/dist/core/renderCoordinator/animation/animationHelpers.d.ts +183 -0
- package/dist/core/renderCoordinator/animation/animationHelpers.d.ts.map +1 -0
- package/dist/core/renderCoordinator/annotations/processAnnotations.d.ts +88 -0
- package/dist/core/renderCoordinator/annotations/processAnnotations.d.ts.map +1 -0
- package/dist/core/renderCoordinator/axis/axisLabelHelpers.d.ts +91 -0
- package/dist/core/renderCoordinator/axis/axisLabelHelpers.d.ts.map +1 -0
- package/dist/core/renderCoordinator/axis/computeAxisTicks.d.ts +53 -0
- package/dist/core/renderCoordinator/axis/computeAxisTicks.d.ts.map +1 -0
- package/dist/core/renderCoordinator/data/computeVisibleSlice.d.ts +66 -0
- package/dist/core/renderCoordinator/data/computeVisibleSlice.d.ts.map +1 -0
- package/dist/core/renderCoordinator/gpu/textureManager.d.ts +69 -0
- package/dist/core/renderCoordinator/gpu/textureManager.d.ts.map +1 -0
- package/dist/core/renderCoordinator/interaction/interactionHelpers.d.ts +160 -0
- package/dist/core/renderCoordinator/interaction/interactionHelpers.d.ts.map +1 -0
- package/dist/core/renderCoordinator/render/renderAnnotationLabels.d.ts +36 -0
- package/dist/core/renderCoordinator/render/renderAnnotationLabels.d.ts.map +1 -0
- package/dist/core/renderCoordinator/render/renderAxisLabels.d.ts +40 -0
- package/dist/core/renderCoordinator/render/renderAxisLabels.d.ts.map +1 -0
- package/dist/core/renderCoordinator/render/renderOverlays.d.ts +70 -0
- package/dist/core/renderCoordinator/render/renderOverlays.d.ts.map +1 -0
- package/dist/core/renderCoordinator/render/renderSeries.d.ts +146 -0
- package/dist/core/renderCoordinator/render/renderSeries.d.ts.map +1 -0
- package/dist/core/renderCoordinator/renderers/rendererPool.d.ts +112 -0
- package/dist/core/renderCoordinator/renderers/rendererPool.d.ts.map +1 -0
- package/dist/core/renderCoordinator/types.d.ts +19 -0
- package/dist/core/renderCoordinator/types.d.ts.map +1 -0
- package/dist/core/renderCoordinator/ui/tooltipLegendHelpers.d.ts +104 -0
- package/dist/core/renderCoordinator/ui/tooltipLegendHelpers.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/axisUtils.d.ts +122 -0
- package/dist/core/renderCoordinator/utils/axisUtils.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/boundsComputation.d.ts +69 -0
- package/dist/core/renderCoordinator/utils/boundsComputation.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/canvasUtils.d.ts +52 -0
- package/dist/core/renderCoordinator/utils/canvasUtils.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/dataPointUtils.d.ts +71 -0
- package/dist/core/renderCoordinator/utils/dataPointUtils.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/index.d.ts +12 -0
- package/dist/core/renderCoordinator/utils/index.d.ts.map +1 -0
- package/dist/core/renderCoordinator/utils/timeAxisUtils.d.ts +149 -0
- package/dist/core/renderCoordinator/utils/timeAxisUtils.d.ts.map +1 -0
- package/dist/core/renderCoordinator/zoom/zoomHelpers.d.ts +129 -0
- package/dist/core/renderCoordinator/zoom/zoomHelpers.d.ts.map +1 -0
- package/dist/data/cartesianData.d.ts +72 -0
- package/dist/data/cartesianData.d.ts.map +1 -0
- package/dist/data/createDataStore.d.ts +27 -0
- package/dist/data/createDataStore.d.ts.map +1 -0
- package/dist/data/createStreamBuffer.d.ts +20 -0
- package/dist/data/createStreamBuffer.d.ts.map +1 -0
- package/dist/data/lttbSample.d.ts +5 -0
- package/dist/data/lttbSample.d.ts.map +1 -0
- package/dist/data/ohlcSample.d.ts +21 -0
- package/dist/data/ohlcSample.d.ts.map +1 -0
- package/dist/data/packDataPoints.d.ts +65 -0
- package/dist/data/packDataPoints.d.ts.map +1 -0
- package/dist/data/sampleSeries.d.ts +20 -0
- package/dist/data/sampleSeries.d.ts.map +1 -0
- package/dist/esm/ChartGPUWorkerController-B50J-8sx.js +772 -0
- package/dist/esm/ChartGPUWorkerController-B50J-8sx.js.map +1 -0
- package/dist/esm/OptionResolver-R_gJDRSD.js +7150 -0
- package/dist/esm/OptionResolver-R_gJDRSD.js.map +1 -0
- package/dist/esm/assets/worker-entry-Wg897auv.js +779 -0
- package/dist/esm/assets/worker-entry-Wg897auv.js.map +1 -0
- package/dist/esm/createChartInWorker-C4fEeJL8.js +1224 -0
- package/dist/esm/createChartInWorker-C4fEeJL8.js.map +1 -0
- package/dist/esm/index.js +795 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/index.cjs +1270 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10504 -0
- package/dist/index.js.map +1 -0
- package/dist/interaction/createAnnotationAuthoring.d.ts +115 -0
- package/dist/interaction/createAnnotationAuthoring.d.ts.map +1 -0
- package/dist/interaction/createAnnotationDragHandler.d.ts +28 -0
- package/dist/interaction/createAnnotationDragHandler.d.ts.map +1 -0
- package/dist/interaction/createAnnotationHitTester.d.ts +32 -0
- package/dist/interaction/createAnnotationHitTester.d.ts.map +1 -0
- package/dist/interaction/createChartSync.d.ts +27 -0
- package/dist/interaction/createChartSync.d.ts.map +1 -0
- package/dist/interaction/createEventManager.d.ts +24 -0
- package/dist/interaction/createEventManager.d.ts.map +1 -0
- package/dist/interaction/createHoverState.d.ts +20 -0
- package/dist/interaction/createHoverState.d.ts.map +1 -0
- package/dist/interaction/createInsideZoom.d.ts +14 -0
- package/dist/interaction/createInsideZoom.d.ts.map +1 -0
- package/dist/interaction/createZoomState.d.ts +63 -0
- package/dist/interaction/createZoomState.d.ts.map +1 -0
- package/dist/interaction/findCandlestick.d.ts +41 -0
- package/dist/interaction/findCandlestick.d.ts.map +1 -0
- package/dist/interaction/findNearestPoint.d.ts +61 -0
- package/dist/interaction/findNearestPoint.d.ts.map +1 -0
- package/dist/interaction/findPieSlice.d.ts +36 -0
- package/dist/interaction/findPieSlice.d.ts.map +1 -0
- package/dist/interaction/findPointsAtX.d.ts +37 -0
- package/dist/interaction/findPointsAtX.d.ts.map +1 -0
- package/dist/renderers/createAnnotationMarkerRenderer.d.ts +58 -0
- package/dist/renderers/createAnnotationMarkerRenderer.d.ts.map +1 -0
- package/dist/renderers/createAreaRenderer.d.ts +19 -0
- package/dist/renderers/createAreaRenderer.d.ts.map +1 -0
- package/dist/renderers/createAxisRenderer.d.ts +19 -0
- package/dist/renderers/createAxisRenderer.d.ts.map +1 -0
- package/dist/renderers/createBarRenderer.d.ts +20 -0
- package/dist/renderers/createBarRenderer.d.ts.map +1 -0
- package/dist/renderers/createCandlestickRenderer.d.ts +19 -0
- package/dist/renderers/createCandlestickRenderer.d.ts.map +1 -0
- package/dist/renderers/createCrosshairRenderer.d.ts +43 -0
- package/dist/renderers/createCrosshairRenderer.d.ts.map +1 -0
- package/dist/renderers/createGridRenderer.d.ts +45 -0
- package/dist/renderers/createGridRenderer.d.ts.map +1 -0
- package/dist/renderers/createHighlightRenderer.d.ts +41 -0
- package/dist/renderers/createHighlightRenderer.d.ts.map +1 -0
- package/dist/renderers/createLineRenderer.d.ts +18 -0
- package/dist/renderers/createLineRenderer.d.ts.map +1 -0
- package/dist/renderers/createPieRenderer.d.ts +18 -0
- package/dist/renderers/createPieRenderer.d.ts.map +1 -0
- package/dist/renderers/createReferenceLineRenderer.d.ts +81 -0
- package/dist/renderers/createReferenceLineRenderer.d.ts.map +1 -0
- package/dist/renderers/createScatterDensityRenderer.d.ts +14 -0
- package/dist/renderers/createScatterDensityRenderer.d.ts.map +1 -0
- package/dist/renderers/createScatterRenderer.d.ts +20 -0
- package/dist/renderers/createScatterRenderer.d.ts.map +1 -0
- package/dist/renderers/rendererUtils.d.ts +100 -0
- package/dist/renderers/rendererUtils.d.ts.map +1 -0
- package/dist/themes/darkTheme.d.ts +11 -0
- package/dist/themes/darkTheme.d.ts.map +1 -0
- package/dist/themes/index.d.ts +8 -0
- package/dist/themes/index.d.ts.map +1 -0
- package/dist/themes/lightTheme.d.ts +11 -0
- package/dist/themes/lightTheme.d.ts.map +1 -0
- package/dist/themes/types.d.ts +14 -0
- package/dist/themes/types.d.ts.map +1 -0
- package/dist/types/ChartGPU.d.ts +99 -0
- package/dist/types/ChartGPU.d.ts.map +1 -0
- package/dist/types/components/createDataZoomSlider.d.ts +14 -0
- package/dist/types/components/createDataZoomSlider.d.ts.map +1 -0
- package/dist/types/components/createLegend.d.ts +9 -0
- package/dist/types/components/createLegend.d.ts.map +1 -0
- package/dist/types/components/createTextOverlay.d.ts +17 -0
- package/dist/types/components/createTextOverlay.d.ts.map +1 -0
- package/dist/types/components/createTooltip.d.ts +12 -0
- package/dist/types/components/createTooltip.d.ts.map +1 -0
- package/dist/types/components/formatTooltip.d.ts +19 -0
- package/dist/types/components/formatTooltip.d.ts.map +1 -0
- package/dist/types/config/OptionResolver.d.ts +134 -0
- package/dist/types/config/OptionResolver.d.ts.map +1 -0
- package/dist/types/config/defaults.d.ts +55 -0
- package/dist/types/config/defaults.d.ts.map +1 -0
- package/dist/types/config/types.d.ts +485 -0
- package/dist/types/config/types.d.ts.map +1 -0
- package/dist/types/core/GPUContext.d.ts +242 -0
- package/dist/types/core/GPUContext.d.ts.map +1 -0
- package/dist/types/core/RenderScheduler.d.ts +174 -0
- package/dist/types/core/RenderScheduler.d.ts.map +1 -0
- package/dist/types/core/createAnimationController.d.ts +15 -0
- package/dist/types/core/createAnimationController.d.ts.map +1 -0
- package/dist/types/core/createRenderCoordinator.d.ts +129 -0
- package/dist/types/core/createRenderCoordinator.d.ts.map +1 -0
- package/dist/types/data/createDataStore.d.ts +33 -0
- package/dist/types/data/createDataStore.d.ts.map +1 -0
- package/dist/types/data/createStreamBuffer.d.ts +20 -0
- package/dist/types/data/createStreamBuffer.d.ts.map +1 -0
- package/dist/types/data/lttbSample.d.ts +5 -0
- package/dist/types/data/lttbSample.d.ts.map +1 -0
- package/dist/types/data/ohlcSample.d.ts +21 -0
- package/dist/types/data/ohlcSample.d.ts.map +1 -0
- package/dist/types/data/packDataPoints.d.ts +79 -0
- package/dist/types/data/packDataPoints.d.ts.map +1 -0
- package/dist/types/data/sampleSeries.d.ts +3 -0
- package/dist/types/data/sampleSeries.d.ts.map +1 -0
- package/dist/types/index.d.ts +35 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/interaction/createChartSync.d.ts +12 -0
- package/dist/types/interaction/createChartSync.d.ts.map +1 -0
- package/dist/types/interaction/createEventManager.d.ts +24 -0
- package/dist/types/interaction/createEventManager.d.ts.map +1 -0
- package/dist/types/interaction/createHoverState.d.ts +20 -0
- package/dist/types/interaction/createHoverState.d.ts.map +1 -0
- package/dist/types/interaction/createInsideZoom.d.ts +14 -0
- package/dist/types/interaction/createInsideZoom.d.ts.map +1 -0
- package/dist/types/interaction/createZoomState.d.ts +63 -0
- package/dist/types/interaction/createZoomState.d.ts.map +1 -0
- package/dist/types/interaction/findCandlestick.d.ts +41 -0
- package/dist/types/interaction/findCandlestick.d.ts.map +1 -0
- package/dist/types/interaction/findNearestPoint.d.ts +61 -0
- package/dist/types/interaction/findNearestPoint.d.ts.map +1 -0
- package/dist/types/interaction/findPieSlice.d.ts +36 -0
- package/dist/types/interaction/findPieSlice.d.ts.map +1 -0
- package/dist/types/interaction/findPointsAtX.d.ts +37 -0
- package/dist/types/interaction/findPointsAtX.d.ts.map +1 -0
- package/dist/types/renderers/createAreaRenderer.d.ts +18 -0
- package/dist/types/renderers/createAreaRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createAxisRenderer.d.ts +19 -0
- package/dist/types/renderers/createAxisRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createBarRenderer.d.ts +20 -0
- package/dist/types/renderers/createBarRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createCandlestickRenderer.d.ts +19 -0
- package/dist/types/renderers/createCandlestickRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createCrosshairRenderer.d.ts +43 -0
- package/dist/types/renderers/createCrosshairRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createGridRenderer.d.ts +45 -0
- package/dist/types/renderers/createGridRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createHighlightRenderer.d.ts +41 -0
- package/dist/types/renderers/createHighlightRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createLineRenderer.d.ts +18 -0
- package/dist/types/renderers/createLineRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createPieRenderer.d.ts +18 -0
- package/dist/types/renderers/createPieRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createScatterDensityRenderer.d.ts +14 -0
- package/dist/types/renderers/createScatterDensityRenderer.d.ts.map +1 -0
- package/dist/types/renderers/createScatterRenderer.d.ts +19 -0
- package/dist/types/renderers/createScatterRenderer.d.ts.map +1 -0
- package/dist/types/renderers/rendererUtils.d.ts +100 -0
- package/dist/types/renderers/rendererUtils.d.ts.map +1 -0
- package/dist/types/themes/darkTheme.d.ts +11 -0
- package/dist/types/themes/darkTheme.d.ts.map +1 -0
- package/dist/types/themes/index.d.ts +8 -0
- package/dist/types/themes/index.d.ts.map +1 -0
- package/dist/types/themes/lightTheme.d.ts +11 -0
- package/dist/types/themes/lightTheme.d.ts.map +1 -0
- package/dist/types/themes/types.d.ts +14 -0
- package/dist/types/themes/types.d.ts.map +1 -0
- package/dist/types/utils/axisLabelStyling.d.ts +27 -0
- package/dist/types/utils/axisLabelStyling.d.ts.map +1 -0
- package/dist/types/utils/checkWebGPU.d.ts +39 -0
- package/dist/types/utils/checkWebGPU.d.ts.map +1 -0
- package/dist/types/utils/colors.d.ts +14 -0
- package/dist/types/utils/colors.d.ts.map +1 -0
- package/dist/types/utils/easing.d.ts +9 -0
- package/dist/types/utils/easing.d.ts.map +1 -0
- package/dist/types/utils/scales.d.ts +79 -0
- package/dist/types/utils/scales.d.ts.map +1 -0
- package/dist/utils/axisLabelStyling.d.ts +20 -0
- package/dist/utils/axisLabelStyling.d.ts.map +1 -0
- package/dist/utils/checkWebGPU.d.ts +39 -0
- package/dist/utils/checkWebGPU.d.ts.map +1 -0
- package/dist/utils/colors.d.ts +14 -0
- package/dist/utils/colors.d.ts.map +1 -0
- package/dist/utils/easing.d.ts +9 -0
- package/dist/utils/easing.d.ts.map +1 -0
- package/dist/utils/scales.d.ts +79 -0
- package/dist/utils/scales.d.ts.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,779 @@
|
|
|
1
|
+
(function(){"use strict";function Ki(e){return typeof HTMLCanvasElement<"u"&&e instanceof HTMLCanvasElement}function Zs(e){if(Ki(e)){const i=e.clientWidth||e.width||0,r=e.clientHeight||e.height||0;if(!Number.isFinite(i)||!Number.isFinite(r))throw new Error(`GPUContext: Invalid canvas dimensions detected: width=${e.clientWidth||e.width}, height=${e.clientHeight||e.height}. Canvas must have finite dimensions. Ensure canvas is properly sized before initialization.`);return{width:i,height:r}}const t=e.width,n=e.height;if(!Number.isFinite(t)||!Number.isFinite(n))throw new Error(`GPUContext: Invalid OffscreenCanvas dimensions: width=${t}, height=${n}. OffscreenCanvas must be initialized with finite dimensions before GPUContext creation.`);return{width:t,height:n}}function js(e,t){const n=(t==null?void 0:t.devicePixelRatio)??(typeof window<"u"?window.devicePixelRatio:1),i=Number.isFinite(n)&&n>0?n:1,r=(t==null?void 0:t.alphaMode)??"opaque",s=(t==null?void 0:t.powerPreference)??"high-performance";return{adapter:null,device:null,initialized:!1,canvas:e||null,canvasContext:null,preferredFormat:null,devicePixelRatio:i,alphaMode:r,powerPreference:s}}async function Ks(e){var i,r;const t=Number.isFinite(e.devicePixelRatio)&&e.devicePixelRatio>0?e.devicePixelRatio:1;if(!navigator.gpu)throw new Error("WebGPU is not available in this browser. Please use a browser that supports WebGPU (Chrome 113+, Edge 113+, or Safari 18+). Ensure WebGPU is enabled in browser flags if needed.");let n=null;try{const s=await navigator.gpu.requestAdapter({powerPreference:e.powerPreference});if(!s)throw new Error("Failed to request WebGPU adapter. No compatible adapter found. This may occur if no GPU is available or WebGPU is disabled.");if(n=await s.requestDevice(),!n)throw new Error("Failed to request WebGPU device from adapter.");n.addEventListener("uncapturederror",l=>{console.error("WebGPU uncaptured error:",l.error)});let o=null,c=null;if(e.canvas){const l=e.canvas.getContext("webgpu");if(!l){try{n.destroy()}catch(F){console.warn("Error destroying device during canvas setup failure:",F)}throw new Error("Failed to get WebGPU context from canvas.")}const{width:u,height:m}=Zs(e.canvas),f=t,a=Math.floor(u*f),v=Math.floor(m*f),M=n.limits.maxTextureDimension2D,C=Math.max(1,Math.min(a,M)),p=Math.max(1,Math.min(v,M));e.canvas.width=C,e.canvas.height=p,c=((r=(i=navigator.gpu).getPreferredCanvasFormat)==null?void 0:r.call(i))||"bgra8unorm",l.configure({device:n,format:c,alphaMode:e.alphaMode}),o=l}return{adapter:s,device:n,initialized:!0,canvas:e.canvas,canvasContext:o,preferredFormat:c,devicePixelRatio:t,alphaMode:e.alphaMode,powerPreference:e.powerPreference}}catch(s){if(n)try{n.destroy()}catch(o){console.warn("Error destroying device during initialization failure:",o)}throw s instanceof Error?s:new Error(`Failed to initialize GPUContext: ${String(s)}`)}}function Js(e){if(e.device)try{e.device.destroy()}catch(t){console.warn("Error destroying GPU device:",t)}return{adapter:null,device:null,initialized:!1,canvas:e.canvas,canvasContext:null,preferredFormat:null,devicePixelRatio:e.devicePixelRatio,alphaMode:e.alphaMode,powerPreference:e.powerPreference}}function Ji(e){return Array.isArray(e)}function fi(e){if(!e)throw new TypeError("packDataPoints: points parameter is required");if(!Array.isArray(e))throw new TypeError("packDataPoints: points must be an array");if(e.length===0)return new Float32Array(0);const t=268435456;if(e.length>t)throw new RangeError(`packDataPoints: points array too large (${e.length} points). Maximum supported: ${t.toLocaleString()} points (2GB buffer limit)`);const n=new ArrayBuffer(e.length*2*4),i=new Float32Array(n);for(let r=0;r<e.length;r++){const s=e[r];if(s==null)throw new TypeError(`packDataPoints: Invalid point at index ${r}. Expected DataPoint (tuple or object), got ${s}`);const o=Ji(s)?s[0]:s.x,c=Ji(s)?s[1]:s.y;if(typeof o!="number"||typeof c!="number")throw new TypeError(`packDataPoints: Invalid coordinate values at index ${r}. Expected numbers, got x=${typeof o}, y=${typeof c}`);i[r*2+0]=o,i[r*2+1]=c}return i}const Sn=4;function mi(e){return e+3&-4}function Qs(e){if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))}function Qi(e,t){const n=Math.max(Sn,mi(t)),i=Math.max(Sn,Qs(n));return Math.max(e,i)}function er(e,t){let n=e>>>0;for(let i=0;i<t.length;i++)n^=t[i],n=Math.imul(n,16777619)>>>0;return n>>>0}function tr(e){const t=new Uint32Array(e.buffer,e.byteOffset,e.byteLength/4);return er(2166136261,t)}function eo(e){const t=new Map;let n=!1;const i=()=>{if(n)throw new Error("DataStore is disposed.")},r=a=>{i();const v=t.get(a);if(!v)throw new Error(`Series ${a} has no data. Call setSeries(${a}, data) first.`);return v};return{setSeries:(a,v)=>{i();const M=fi(v),C=v.length,p=tr(M),F=mi(M.byteLength),b=Math.max(Sn,F),x=t.get(a);if(x&&x.pointCount===C&&x.hash32===p)return;let d=(x==null?void 0:x.buffer)??null,h=(x==null?void 0:x.capacityBytes)??0;if(!d||b>h){const N=e.limits.maxBufferSize;if(b>N)throw new Error(`DataStore.setSeries(${a}): required buffer size ${b} exceeds device.limits.maxBufferSize (${N}).`);if(d)try{d.destroy()}catch{}const w=Qi(h,b);w>N?h=b:h=w,d=e.createBuffer({size:h,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST})}M.byteLength>0&&e.queue.writeBuffer(d,0,M.buffer),t.set(a,{buffer:d,capacityBytes:h,pointCount:C,hash32:p,data:v.length===0?[]:v.slice()})},appendSeries:(a,v)=>{if(i(),!v||v.length===0)return;const M=r(a),C=M.pointCount,p=C+v.length,F=fi(v),b=F.byteLength,x=mi(p*2*4),y=Math.max(Sn,x);let d=M.buffer,h=M.capacityBytes;const N=M.data;N.push(...v);const w=e.limits.maxBufferSize;if(y>h){if(y>w)throw new Error(`DataStore.appendSeries(${a}): required buffer size ${y} exceeds device.limits.maxBufferSize (${w}).`);try{d.destroy()}catch{}const P=Qi(h,y);h=P>w?y:P,d=e.createBuffer({size:h,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST});const T=fi(N);T.byteLength>0&&e.queue.writeBuffer(d,0,T.buffer),t.set(a,{buffer:d,capacityBytes:h,pointCount:p,hash32:tr(T),data:N});return}if(b>0){const P=C*2*4;e.queue.writeBuffer(d,P,F.buffer)}const I=new Uint32Array(F.buffer,F.byteOffset,F.byteLength/4),R=er(M.hash32,I);t.set(a,{buffer:d,capacityBytes:h,pointCount:p,hash32:R,data:N})},removeSeries:a=>{i();const v=t.get(a);if(v){try{v.buffer.destroy()}catch{}t.delete(a)}},getSeriesBuffer:a=>r(a).buffer,getSeriesPointCount:a=>r(a).pointCount,getSeriesData:a=>r(a).data,dispose:()=>{if(!n){n=!0;for(const a of t.values())try{a.buffer.destroy()}catch{}t.clear()}}}}function Lt(e){return Array.isArray(e)}function to(e,t){const n=e.length>>>1,i=n-1;if(t<=0||n===0)return new Int32Array(0);if(t===1)return new Int32Array([0]);if(t===2)return n>=2?new Int32Array([0,i]):new Int32Array([0]);if(n<=t){const m=new Int32Array(n);for(let f=0;f<n;f++)m[f]=f;return m}const r=new Int32Array(t);r[0]=0,r[t-1]=i;const s=(n-2)/(t-2);let o=0,c=1;const l=e[i*2+0],u=e[i*2+1];for(let m=0;m<t-2;m++){let f=Math.floor(s*m)+1,a=Math.min(Math.floor(s*(m+1))+1,i);f>=a&&(f=Math.min(f,i-1),a=Math.min(f+1,i));const v=Math.floor(s*(m+1))+1,M=Math.min(Math.floor(s*(m+2))+1,i);let C=l,p=u;if(v<M){let d=0,h=0,N=0;for(let w=v;w<M;w++)d+=e[w*2+0],h+=e[w*2+1],N++;N>0&&(C=d/N,p=h/N)}const F=e[o*2+0],b=e[o*2+1];let x=-1,y=f;for(let d=f;d<a;d++){const h=e[d*2+0],N=e[d*2+1],w=(F-C)*(N-b)-(F-h)*(p-b),I=w<0?-w:w;I>x&&(x=I,y=d)}r[c++]=y,o=y}return r}function no(e,t){const n=e.length,i=n-1;if(t<=0||n===0)return new Int32Array(0);if(t===1)return new Int32Array([0]);if(t===2)return n>=2?new Int32Array([0,i]):new Int32Array([0]);if(n<=t){const f=new Int32Array(n);for(let a=0;a<n;a++)f[a]=a;return f}const r=new Int32Array(t);r[0]=0,r[t-1]=i;const s=(n-2)/(t-2);let o=0,c=1;const l=e[i],u=Lt(l)?l[0]:l.x,m=Lt(l)?l[1]:l.y;for(let f=0;f<t-2;f++){let a=Math.floor(s*f)+1,v=Math.min(Math.floor(s*(f+1))+1,i);a>=v&&(a=Math.min(a,i-1),v=Math.min(a+1,i));const M=Math.floor(s*(f+1))+1,C=Math.min(Math.floor(s*(f+2))+1,i);let p=u,F=m;if(M<C){let N=0,w=0,I=0;for(let R=M;R<C;R++){const P=e[R],T=Lt(P)?P[0]:P.x,B=Lt(P)?P[1]:P.y;N+=T,w+=B,I++}I>0&&(p=N/I,F=w/I)}const b=e[o],x=Lt(b)?b[0]:b.x,y=Lt(b)?b[1]:b.y;let d=-1,h=a;for(let N=a;N<v;N++){const w=e[N],I=Lt(w)?w[0]:w.x,R=Lt(w)?w[1]:w.y,P=(x-p)*(R-y)-(x-I)*(F-y),T=P<0?-P:P;T>d&&(d=T,h=N)}r[c++]=h,o=h}return r}function io(e,t){const n=Math.floor(t);if(e instanceof Float32Array){const o=e.length>>>1;if(n<=0||o===0)return new Float32Array(0);if(o<=n)return e;const c=to(e,n),l=new Float32Array(c.length*2);for(let u=0;u<c.length;u++){const m=c[u];l[u*2+0]=e[m*2+0],l[u*2+1]=e[m*2+1]}return l}const i=e.length;if(n<=0||i===0)return[];if(i<=n)return e;const r=no(e,n),s=new Array(r.length);for(let o=0;o<r.length;o++)s[o]=e[r[o]];return s}function nr(e){return Array.isArray(e)}function ir(e){return nr(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y}}function ro(e){return nr(e)?e[2]:e.size}function rr(e){const t=Math.floor(e);return Number.isFinite(t)?t:0}function di(e,t,n){const i=e.length,r=rr(t);if(r<=0||i===0)return[];if(r===1)return[e[0]];if(r===2)return i>=2?[e[0],e[i-1]]:[e[0]];if(i<=r)return e;const s=i-1,o=new Array(r);o[0]=e[0],o[r-1]=e[s];const c=(i-2)/(r-2);for(let l=0;l<r-2;l++){let u=Math.floor(c*l)+1,m=Math.min(Math.floor(c*(l+1))+1,s);u>=m&&(u=Math.min(u,s-1),m=Math.min(u+1,s));let f=null;if(n==="average"){let a=0,v=0,M=0,C=0,p=0;for(let F=u;F<m;F++){const b=e[F],{x,y}=ir(b);if(!Number.isFinite(x)||!Number.isFinite(y))continue;a+=x,v+=y,C++;const d=ro(b);typeof d=="number"&&Number.isFinite(d)&&(M+=d,p++)}if(C>0){const F=a/C,b=v/C;p>0?f=[F,b,M/p]:f=[F,b]}}else{let a=n==="max"?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY;for(let v=u;v<m;v++){const M=e[v],{y:C}=ir(M);Number.isFinite(C)&&(n==="max"?C>a&&(a=C,f=M):C<a&&(a=C,f=M))}}o[l+1]=f??e[u]}return o}function tn(e,t,n){const i=rr(n);if(t==="none"||!(i>0)||e.length<=i)return e;switch(t){case"lttb":return io(e,i);case"average":return di(e,i,"average");case"max":return di(e,i,"max");case"min":return di(e,i,"min");default:return e}}function so(e){return Array.isArray(e)}function hi(e,t){const n=Math.floor(t),i=e.length;if(n<2||i<=n)return e;const r=new Array(n);if(r[0]=e[0],r[n-1]=e[i-1],n===2)return r;const s=so(e[0]),o=(i-2)/(n-2);if(s){const c=e;for(let l=0;l<n-2;l++){let u=Math.floor(o*l)+1,m=Math.min(Math.floor(o*(l+1))+1,i-1);u>=m&&(u=Math.min(u,i-2),m=Math.min(u+1,i-1));const f=c[u],a=c[m-1],v=f[0],M=f[1],C=a[2];let p=-1/0,F=1/0;for(let b=u;b<m;b++){const x=c[b],y=x[3],d=x[4];d>p&&(p=d),y<F&&(F=y)}r[l+1]=[v,M,C,F,p]}}else{const c=e;for(let l=0;l<n-2;l++){let u=Math.floor(o*l)+1,m=Math.min(Math.floor(o*(l+1))+1,i-1);u>=m&&(u=Math.min(u,i-2),m=Math.min(u+1,i-1));const f=c[u],a=c[m-1],v=f.timestamp,M=f.open,C=a.close;let p=-1/0,F=1/0;for(let b=u;b<m;b++){const x=c[b],y=x.high,d=x.low;y>p&&(p=y),d<F&&(F=d)}r[l+1]={timestamp:v,open:M,close:C,low:F,high:p}}}return r}var Cn=`// grid.wgsl
|
|
2
|
+
// Minimal grid line shader:
|
|
3
|
+
// - Vertex input: vec2<f32> position in clip-space coordinates
|
|
4
|
+
// - Uniforms: identity transform + solid RGBA color
|
|
5
|
+
|
|
6
|
+
struct VSUniforms {
|
|
7
|
+
transform: mat4x4<f32>,
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
11
|
+
|
|
12
|
+
struct FSUniforms {
|
|
13
|
+
color: vec4<f32>,
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;
|
|
17
|
+
|
|
18
|
+
struct VSIn {
|
|
19
|
+
@location(0) position: vec2<f32>,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
struct VSOut {
|
|
23
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
@vertex
|
|
27
|
+
fn vsMain(in: VSIn) -> VSOut {
|
|
28
|
+
var out: VSOut;
|
|
29
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);
|
|
30
|
+
return out;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@fragment
|
|
34
|
+
fn fsMain() -> @location(0) vec4<f32> {
|
|
35
|
+
return fsUniforms.color;
|
|
36
|
+
}
|
|
37
|
+
`;const oo="vsMain",ao="fsMain",co=e=>Number.isInteger(e)&&e>0&&(e&e-1)===0,lo=(e,t)=>{if(!Number.isFinite(e)||e<0)throw new Error(`alignTo(value): value must be a finite non-negative number. Received: ${String(e)}`);if(!co(t))throw new Error(`alignTo(alignment): alignment must be a positive power of two. Received: ${String(t)}`);return Math.floor(e)+t-1&~(t-1)},sr=(e,t)=>"module"in t?{module:t.module,entryPoint:t.entryPoint||"",constants:t.constants}:{module:or(e,t.code,t.label),entryPoint:t.entryPoint||"",constants:t.constants};function or(e,t,n){if(typeof t!="string"||t.length===0)throw new Error("createShaderModule(code): WGSL code must be a non-empty string.");return e.createShaderModule({code:t,label:n})}function lt(e,t){const n=t.layout??(t.bindGroupLayouts?e.createPipelineLayout({bindGroupLayouts:[...t.bindGroupLayouts]}):"auto"),i=sr(e,t.vertex),r=i.entryPoint||oo;let s;if(t.fragment){const l=sr(e,t.fragment),u=l.entryPoint||ao;let m=t.fragment.targets;if(!m){const f=t.fragment.formats;if(!f)throw new Error("createRenderPipeline(fragment): provide either `fragment.targets` or `fragment.formats` when a fragment stage is present.");m=(Array.isArray(f)?f:[f]).map(v=>({format:v,blend:t.fragment.blend,writeMask:t.fragment.writeMask}))}s={module:l.module,entryPoint:u,targets:[...m],constants:l.constants}}const o=t.primitive??{topology:"triangle-list"},c=t.multisample??{count:1};return e.createRenderPipeline({label:t.label,layout:n,vertex:{module:i.module,entryPoint:r,buffers:t.vertex.buffers?[...t.vertex.buffers]:[],constants:i.constants},fragment:s,primitive:o,depthStencil:t.depthStencil,multisample:c})}function Ve(e,t,n){if(!Number.isFinite(t)||t<=0)throw new Error(`createUniformBuffer(size): size must be a positive number. Received: ${String(t)}`);const i=(n==null?void 0:n.alignment)??16,r=lo(t,Math.max(4,i)),s=e.limits.maxUniformBufferBindingSize;if(r>s)throw new Error(`createUniformBuffer(size): requested size ${r} exceeds device.limits.maxUniformBufferBindingSize (${s}).`);return e.createBuffer({label:n==null?void 0:n.label,size:r,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST})}function Ge(e,t,n){const i=n instanceof ArrayBuffer?{arrayBuffer:n,offset:0,size:n.byteLength}:{arrayBuffer:n.buffer,offset:n.byteOffset,size:n.byteLength};if(i.size!==0){if(i.offset&3||i.size&3)throw new Error(`writeUniformBuffer(data): data byteOffset (${i.offset}) and byteLength (${i.size}) must be multiples of 4 for queue.writeBuffer().`);if(i.size>t.size)throw new Error(`writeUniformBuffer(data): data byteLength (${i.size}) exceeds buffer.size (${t.size}).`);e.queue.writeBuffer(t,0,i.arrayBuffer,i.offset,i.size)}}const ar=e=>Math.min(1,Math.max(0,e)),cr=e=>Math.min(255,Math.max(0,e)),kt=e=>{const t=Number.parseInt(e,16);return Number.isFinite(t)?t:0},Vt=e=>{const t=Number.parseInt(e,16);return Number.isFinite(t)?t:0},uo=e=>{const t=e.trim();if(!t.startsWith("#"))return null;const n=t.slice(1);if(n.length===3){const i=kt(n[0]),r=kt(n[1]),s=kt(n[2]);return[i*17/255,r*17/255,s*17/255,1]}if(n.length===4){const i=kt(n[0]),r=kt(n[1]),s=kt(n[2]),o=kt(n[3]);return[i*17/255,r*17/255,s*17/255,o*17/255]}if(n.length===6){const i=Vt(n.slice(0,2)),r=Vt(n.slice(2,4)),s=Vt(n.slice(4,6));return[i/255,r/255,s/255,1]}if(n.length===8){const i=Vt(n.slice(0,2)),r=Vt(n.slice(2,4)),s=Vt(n.slice(4,6)),o=Vt(n.slice(6,8));return[i/255,r/255,s/255,o/255]}return null},nn=e=>{const t=e.trim();if(t.length===0)return null;if(t.endsWith("%")){const i=Number.parseFloat(t.slice(0,-1));return Number.isFinite(i)?cr(i/100*255):null}const n=Number.parseFloat(t);return Number.isFinite(n)?cr(n):null},fo=e=>{const t=e.trim();if(t.length===0)return null;if(t.endsWith("%")){const i=Number.parseFloat(t.slice(0,-1));return Number.isFinite(i)?ar(i/100):null}const n=Number.parseFloat(t);return Number.isFinite(n)?ar(n):null},mo=e=>{const t=e.trim(),n=/^(rgba?|RGBA?)\(\s*([^\)]*)\s*\)$/.exec(t);if(!n)return null;const i=n[1].toLowerCase(),s=n[2].split(",").map(o=>o.trim());if(i==="rgb"){if(s.length!==3)return null;const o=nn(s[0]),c=nn(s[1]),l=nn(s[2]);return o==null||c==null||l==null?null:[o/255,c/255,l/255,1]}if(i==="rgba"){if(s.length!==4)return null;const o=nn(s[0]),c=nn(s[1]),l=nn(s[2]),u=fo(s[3]);return o==null||c==null||l==null||u==null?null:[o/255,c/255,l/255,u]}return null},Ke=e=>{if(typeof e!="string")return null;const t=e.trim();if(t.length===0)return null;const n=uo(t);if(n)return n;const i=mo(t);return i||null},ho=(e,t={r:0,g:0,b:0,a:1})=>{const n=Ke(e);if(!n)return t;const[i,r,s,o]=n;return{r:i,g:r,b:s,a:o}},po="bgra8unorm",bo=5,go=6,yo=[1,1,1,.8],xo=()=>{const e=new ArrayBuffer(64);return new Float32Array(e).set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),e},vo=e=>Number.isFinite(e.left)&&Number.isFinite(e.right)&&Number.isFinite(e.top)&&Number.isFinite(e.bottom)&&Number.isFinite(e.canvasWidth)&&Number.isFinite(e.canvasHeight),lr=e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,wo=(e,t)=>{let n=e,i=t;if((!Number.isFinite(n)||!Number.isFinite(i))&&(n=0,i=1),n===i)i=n+1;else if(n>i){const r=n;n=i,i=r}return{min:n,max:i}},Fo=(e,t,n,i,r)=>{const{left:s,right:o,top:c,bottom:l,canvasWidth:u,canvasHeight:m}=i,f=Number.isFinite(i.devicePixelRatio)&&i.devicePixelRatio>0?i.devicePixelRatio:1;if(!vo(i))throw new Error("AxisRenderer.prepare: gridArea dimensions must be finite numbers.");if(u<=0||m<=0)throw new Error("AxisRenderer.prepare: canvas dimensions must be positive.");if(s<0||o<0||c<0||l<0)throw new Error("AxisRenderer.prepare: gridArea margins must be non-negative.");const a=s*f,v=u-o*f,M=c*f,C=m-l*f,p=a/u*2-1,F=v/u*2-1,b=1-M/m*2,x=1-C/m*2,y=e.tickLength??go;if(!Number.isFinite(y)||y<0)throw new Error("AxisRenderer.prepare: tickLength must be a finite non-negative number.");const d=r??bo,h=Math.max(1,Math.floor(d));if(!Number.isFinite(d)||h<1)throw new Error("AxisRenderer.prepare: tickCount must be a finite number >= 1.");const N=y*f,w=N/u*2,I=N/m*2,R=lr(e.min)??(n==="x"?t.invert(p):t.invert(x)),P=lr(e.max)??(n==="x"?t.invert(F):t.invert(b)),T=wo(R,P),B=T.min,U=T.max,G=1+h,D=new Float32Array(G*2*2);let _=0;if(n==="x"){D[_++]=p,D[_++]=x,D[_++]=F,D[_++]=x;const X=x,Z=X-I;for(let V=0;V<h;V++){const re=h===1?.5:V/(h-1),ce=B+re*(U-B),Y=t.scale(ce);D[_++]=Y,D[_++]=X,D[_++]=Y,D[_++]=Z}}else{D[_++]=p,D[_++]=x,D[_++]=p,D[_++]=b;const X=p,Z=X-w;for(let V=0;V<h;V++){const re=h===1?.5:V/(h-1),ce=B+re*(U-B),Y=t.scale(ce);D[_++]=X,D[_++]=Y,D[_++]=Z,D[_++]=Y}}return D};function ur(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??po,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),s=Ve(e,64,{label:"axisRenderer/vsUniforms"}),o=Ve(e,16,{label:"axisRenderer/fsUniformsLine"}),c=Ve(e,16,{label:"axisRenderer/fsUniformsTick"}),l=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:o}}]}),u=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:c}}]}),m=lt(e,{label:"axisRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:Cn,label:"grid.wgsl",buffers:[{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:0,format:"float32x2",offset:0}]}]},fragment:{code:Cn,label:"grid.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"line-list",cullMode:"none"},multisample:{count:1}});let f=null,a=0;const v=()=>{if(n)throw new Error("AxisRenderer is disposed.")};return{prepare:(F,b,x,y,d,h,N)=>{if(v(),x!=="x"&&x!=="y")throw new Error("AxisRenderer.prepare: orientation must be 'x' or 'y'.");const w=Fo(F,b,x,y,N),I=w.byteLength,R=Math.max(4,I);if(!f||f.size<R){if(f)try{f.destroy()}catch{}f=e.createBuffer({label:"axisRenderer/vertexBuffer",size:R,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}e.queue.writeBuffer(f,0,w.buffer,0,w.byteLength),a=w.length/2,Ge(e,s,xo());const P=d??"rgba(255,255,255,0.8)",T=h??P,B=Ke(P)??yo,U=Ke(T)??B,G=new ArrayBuffer(4*4);new Float32Array(G).set([B[0],B[1],B[2],B[3]]),Ge(e,o,G);const D=new ArrayBuffer(4*4);new Float32Array(D).set([U[0],U[1],U[2],U[3]]),Ge(e,c,D)},render:F=>{v(),!(a===0||!f)&&(F.setPipeline(m),F.setVertexBuffer(0,f),F.setBindGroup(0,l),F.draw(Math.min(2,a)),a>2&&(F.setBindGroup(0,u),F.draw(a-2,1,2,0)))},dispose:()=>{if(!n){n=!0;try{s.destroy()}catch{}try{o.destroy()}catch{}try{c.destroy()}catch{}if(f)try{f.destroy()}catch{}f=null,a=0}}}}const No="bgra8unorm",Mo=5,So=6,Co="rgba(255,255,255,0.15)",Io=[1,1,1,.15],To=()=>{const e=new ArrayBuffer(64);return new Float32Array(e).set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),e},Po=(e,t,n)=>{const{left:i,right:r,top:s,bottom:o,canvasWidth:c,canvasHeight:l}=e,u=Number.isFinite(e.devicePixelRatio)&&e.devicePixelRatio>0?e.devicePixelRatio:1,m=i*u,f=c-r*u,a=s*u,v=l-o*u,M=f-m,C=v-a,p=t+n,F=new Float32Array(p*2*2);let b=0;for(let x=0;x<t;x++){const y=t===1?.5:x/(t-1),d=a+y*C,h=m/c*2-1,N=f/c*2-1,w=1-d/l*2;F[b++]=h,F[b++]=w,F[b++]=N,F[b++]=w}for(let x=0;x<n;x++){const y=n===1?.5:x/(n-1),h=(m+y*M)/c*2-1,N=1-a/l*2,w=1-v/l*2;F[b++]=h,F[b++]=N,F[b++]=h,F[b++]=w}return F};function Ro(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??No,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),s=Ve(e,64,{label:"gridRenderer/vsUniforms"}),o=Ve(e,16,{label:"gridRenderer/fsUniforms"}),c=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:o}}]}),l=lt(e,{label:"gridRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:Cn,label:"grid.wgsl",buffers:[{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:0,format:"float32x2",offset:0}]}]},fragment:{code:Cn,label:"grid.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"line-list",cullMode:"none"},multisample:{count:1}});let u=null,m=0;const f=()=>{if(n)throw new Error("GridRenderer is disposed.")};return{prepare:(C,p)=>{f();const F=p!=null&&typeof p=="object"&&("lineCount"in p||"color"in p),b=F?p:void 0,x=F?b==null?void 0:b.lineCount:p,y=(x==null?void 0:x.horizontal)??Mo,d=(x==null?void 0:x.vertical)??So,h=(b==null?void 0:b.color)??Co;if(y<0||d<0)throw new Error("GridRenderer.prepare: line counts must be non-negative.");if(!Number.isFinite(C.left)||!Number.isFinite(C.right)||!Number.isFinite(C.top)||!Number.isFinite(C.bottom)||!Number.isFinite(C.canvasWidth)||!Number.isFinite(C.canvasHeight))throw new Error("GridRenderer.prepare: gridArea dimensions must be finite numbers.");if(C.canvasWidth<=0||C.canvasHeight<=0)throw new Error("GridRenderer.prepare: canvas dimensions must be positive.");if(y===0&&d===0){m=0;return}const N=Po(C,y,d),w=N.byteLength,I=Math.max(4,w);if(!u||u.size<I){if(u)try{u.destroy()}catch{}u=e.createBuffer({label:"gridRenderer/vertexBuffer",size:I,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}e.queue.writeBuffer(u,0,N.buffer,0,N.byteLength),m=(y+d)*2;const R=To();Ge(e,s,R);const P=Ke(h)??Io,T=new ArrayBuffer(4*4);new Float32Array(T).set([P[0],P[1],P[2],P[3]]),Ge(e,o,T)},render:C=>{f(),!(m===0||!u)&&(C.setPipeline(l),C.setBindGroup(0,c),C.setVertexBuffer(0,u),C.draw(m))},dispose:()=>{if(!n){n=!0;try{s.destroy()}catch{}try{o.destroy()}catch{}if(u)try{u.destroy()}catch{}u=null,m=0}}}}var fr=`// area.wgsl
|
|
38
|
+
// Minimal area-fill shader (triangle-strip):
|
|
39
|
+
// - Vertex input: vec2<f32> position in data coords
|
|
40
|
+
// - Uniforms: clip-space transform + baseline value + solid RGBA color
|
|
41
|
+
// - Topology: triangle-strip
|
|
42
|
+
// - CPU duplicates vertices as p0,p0,p1,p1,... and we use vertex_index parity:
|
|
43
|
+
// even index -> "top" vertex (original y)
|
|
44
|
+
// odd index -> "baseline" vertex (uniform baseline)
|
|
45
|
+
|
|
46
|
+
struct VSUniforms {
|
|
47
|
+
transform: mat4x4<f32>,
|
|
48
|
+
baseline: f32,
|
|
49
|
+
// Pad to 16-byte multiple (uniform buffer layout requirements).
|
|
50
|
+
_pad0: vec3<f32>,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
54
|
+
|
|
55
|
+
struct FSUniforms {
|
|
56
|
+
color: vec4<f32>,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;
|
|
60
|
+
|
|
61
|
+
struct VSIn {
|
|
62
|
+
@location(0) position: vec2<f32>,
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
struct VSOut {
|
|
66
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
@vertex
|
|
70
|
+
fn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
71
|
+
var out: VSOut;
|
|
72
|
+
let useBaseline = (vertexIndex & 1u) == 1u;
|
|
73
|
+
let y = select(in.position.y, vsUniforms.baseline, useBaseline);
|
|
74
|
+
let pos = vec2<f32>(in.position.x, y);
|
|
75
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(pos, 0.0, 1.0);
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
@fragment
|
|
80
|
+
fn fsMain() -> @location(0) vec4<f32> {
|
|
81
|
+
return fsUniforms.color;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
`;const Ao="bgra8unorm",mr=e=>Math.min(1,Math.max(0,e)),Bo=e=>Ke(e)??[0,0,0,1],Eo=e=>Array.isArray(e),dr=e=>Eo(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},Do=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;for(let s=0;s<e.length;s++){const{x:o,y:c}=dr(e[s]);!Number.isFinite(o)||!Number.isFinite(c)||(o<t&&(t=o),o>n&&(n=o),c<i&&(i=c),c>r&&(r=c))}return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)?{xMin:0,xMax:1,yMin:0,yMax:1}:(t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r})},hr=(e,t,n)=>{const i=e.scale(t),r=e.scale(n);if(!Number.isFinite(t)||!Number.isFinite(n)||t===n||!Number.isFinite(i)||!Number.isFinite(r))return{a:0,b:Number.isFinite(i)?i:0};const s=(r-i)/(n-t),o=i-s*t;return{a:Number.isFinite(s)?s:0,b:Number.isFinite(o)?o:0}},Uo=(e,t,n,i,r)=>{e[0]=t,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=n,e[13]=r,e[14]=0,e[15]=1},Lo=e=>{const t=e.length,n=new Float32Array(t*2*2);let i=0;for(let r=0;r<t;r++){const{x:s,y:o}=dr(e[r]);n[i++]=s,n[i++]=o,n[i++]=s,n[i++]=o}return n};function _o(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??Ao,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),s=Ve(e,96,{label:"areaRenderer/vsUniforms"}),o=Ve(e,16,{label:"areaRenderer/fsUniforms"}),c=new ArrayBuffer(96),l=new Float32Array(c),u=new Float32Array(4),m=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:o}}]}),f=lt(e,{label:"areaRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:fr,label:"area.wgsl",buffers:[{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:0,format:"float32x2",offset:0}]}]},fragment:{code:fr,label:"area.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-strip",cullMode:"none"},multisample:{count:1}});let a=null,v=0;const M=()=>{if(n)throw new Error("AreaRenderer is disposed.")},C=(x,y,d,h,N)=>{Uo(l,x,y,d,h),l[16]=N,l[17]=0,l[18]=0,l[19]=0,l[20]=0,l[21]=0,l[22]=0,l[23]=0,Ge(e,s,c)};return{prepare:(x,y,d,h,N)=>{M();const w=Lo(y),I=w.byteLength,R=Math.max(4,I);if(!a||a.size<R){if(a)try{a.destroy()}catch{}a=e.createBuffer({label:"areaRenderer/vertexBuffer",size:R,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}w.byteLength>0&&e.queue.writeBuffer(a,0,w.buffer,0,w.byteLength),v=w.length/2;const{xMin:P,xMax:T,yMin:B,yMax:U}=Do(y),{a:G,b:D}=hr(d,P,T),{a:_,b:X}=hr(h,B,U),Z=Number.isFinite(N??Number.NaN)?N:Number.isFinite(B)?B:0;C(G,D,_,X,Z);const[V,re,ce,Y]=Bo(x.areaStyle.color),ne=mr(x.areaStyle.opacity);u[0]=V,u[1]=re,u[2]=ce,u[3]=mr(Y*ne),Ge(e,o,u)},render:x=>{M(),!(!a||v<4)&&(x.setPipeline(f),x.setBindGroup(0,m),x.setVertexBuffer(0,a),x.draw(v))},dispose:()=>{if(!n){if(n=!0,a)try{a.destroy()}catch{}a=null,v=0;try{s.destroy()}catch{}try{o.destroy()}catch{}}}}}var pr=`// line.wgsl
|
|
85
|
+
// Minimal line-strip shader:
|
|
86
|
+
// - Vertex input: vec2<f32> position in data coords
|
|
87
|
+
// - Uniforms: clip-space transform + solid RGBA color
|
|
88
|
+
|
|
89
|
+
struct VSUniforms {
|
|
90
|
+
transform: mat4x4<f32>,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
94
|
+
|
|
95
|
+
struct FSUniforms {
|
|
96
|
+
color: vec4<f32>,
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;
|
|
100
|
+
|
|
101
|
+
struct VSIn {
|
|
102
|
+
@location(0) position: vec2<f32>,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
struct VSOut {
|
|
106
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
@vertex
|
|
110
|
+
fn vsMain(in: VSIn) -> VSOut {
|
|
111
|
+
var out: VSOut;
|
|
112
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
@fragment
|
|
117
|
+
fn fsMain() -> @location(0) vec4<f32> {
|
|
118
|
+
return fsUniforms.color;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
`;const Go="bgra8unorm",br=e=>Math.min(1,Math.max(0,e)),Wo=e=>Ke(e)??[0,0,0,1],$o=e=>Array.isArray(e),Oo=e=>$o(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},ko=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;for(let s=0;s<e.length;s++){const{x:o,y:c}=Oo(e[s]);!Number.isFinite(o)||!Number.isFinite(c)||(o<t&&(t=o),o>n&&(n=o),c<i&&(i=c),c>r&&(r=c))}return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)?{xMin:0,xMax:1,yMin:0,yMax:1}:(t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r})},gr=(e,t,n)=>{const i=e.scale(t),r=e.scale(n);if(!Number.isFinite(t)||!Number.isFinite(n)||t===n||!Number.isFinite(i)||!Number.isFinite(r))return{a:0,b:Number.isFinite(i)?i:0};const s=(r-i)/(n-t),o=i-s*t;return{a:Number.isFinite(s)?s:0,b:Number.isFinite(o)?o:0}},Vo=(e,t,n,i,r)=>{e[0]=t,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=n,e[13]=r,e[14]=0,e[15]=1};function zo(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??Go,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),s=Ve(e,64,{label:"lineRenderer/vsUniforms"}),o=Ve(e,16,{label:"lineRenderer/fsUniforms"}),c=new ArrayBuffer(64),l=new Float32Array(c),u=new Float32Array(4),m=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:o}}]}),f=lt(e,{label:"lineRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:pr,label:"line.wgsl",buffers:[{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:0,format:"float32x2",offset:0}]}]},fragment:{code:pr,label:"line.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"line-strip",cullMode:"none"},multisample:{count:1}});let a=null,v=0;const M=()=>{if(n)throw new Error("LineRenderer is disposed.")};return{prepare:(b,x,y,d)=>{M(),a=x,v=b.data.length;const{xMin:h,xMax:N,yMin:w,yMax:I}=ko(b.data),{a:R,b:P}=gr(y,h,N),{a:T,b:B}=gr(d,w,I);Vo(l,R,P,T,B),Ge(e,s,c);const[U,G,D,_]=Wo(b.color),X=br(b.lineStyle.opacity);u[0]=U,u[1]=G,u[2]=D,u[3]=br(_*X),Ge(e,o,u)},render:b=>{M(),!(!a||v<2)&&(b.setPipeline(f),b.setBindGroup(0,m),b.setVertexBuffer(0,a),b.draw(v))},dispose:()=>{if(!n){n=!0,a=null,v=0;try{s.destroy()}catch{}try{o.destroy()}catch{}}}}}var yr=`// bar.wgsl
|
|
122
|
+
// Instanced bar/rect shader:
|
|
123
|
+
// - Per-instance vertex input:
|
|
124
|
+
// - rect = vec4<f32>(x, y, width, height) in CLIP space
|
|
125
|
+
// - color = vec4<f32>(r, g, b, a) in [0..1]
|
|
126
|
+
// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS
|
|
127
|
+
// - Uniforms:
|
|
128
|
+
// - @group(0) @binding(0): VSUniforms { transform }
|
|
129
|
+
|
|
130
|
+
struct VSUniforms {
|
|
131
|
+
transform: mat4x4<f32>,
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
135
|
+
|
|
136
|
+
struct VSIn {
|
|
137
|
+
// rect.xy = origin, rect.zw = size (width, height)
|
|
138
|
+
@location(0) rect: vec4<f32>,
|
|
139
|
+
@location(1) color: vec4<f32>,
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
struct VSOut {
|
|
143
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
144
|
+
@location(0) color: vec4<f32>,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
@vertex
|
|
148
|
+
fn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
149
|
+
// Fixed local corners for 2 triangles (triangle-list).
|
|
150
|
+
let corners = array<vec2<f32>, 6>(
|
|
151
|
+
vec2<f32>(0.0, 0.0),
|
|
152
|
+
vec2<f32>(1.0, 0.0),
|
|
153
|
+
vec2<f32>(0.0, 1.0),
|
|
154
|
+
vec2<f32>(0.0, 1.0),
|
|
155
|
+
vec2<f32>(1.0, 0.0),
|
|
156
|
+
vec2<f32>(1.0, 1.0)
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Normalize negative width/height by computing min/max extents.
|
|
160
|
+
let p0 = in.rect.xy;
|
|
161
|
+
let p1 = in.rect.xy + in.rect.zw;
|
|
162
|
+
let rectMin = min(p0, p1);
|
|
163
|
+
let rectMax = max(p0, p1);
|
|
164
|
+
let rectSize = rectMax - rectMin;
|
|
165
|
+
|
|
166
|
+
let corner = corners[vertexIndex];
|
|
167
|
+
let pos = rectMin + corner * rectSize;
|
|
168
|
+
|
|
169
|
+
var out: VSOut;
|
|
170
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(pos, 0.0, 1.0);
|
|
171
|
+
out.color = in.color;
|
|
172
|
+
return out;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@fragment
|
|
176
|
+
fn fsMain(in: VSOut) -> @location(0) vec4<f32> {
|
|
177
|
+
return in.color;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
`;const Xo="bgra8unorm",Ho=.01,Yo=.2,In=32,pi=In/4,bi=e=>Math.min(1,Math.max(0,e)),qo=e=>Ke(e)??[0,0,0,1],xr=e=>{if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))},Zo=()=>{const e=new ArrayBuffer(64);return new Float32Array(e).set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),e},jo=e=>{const t=e.trim().match(/^(\d+(?:\.\d+)?)%$/);if(!t)return null;const n=Number(t[1])/100;return Number.isFinite(n)?n:null},vr=e=>{if(typeof e!="string")return"";const t=e.trim();return t.length>0?t:""},Ko=e=>Array.isArray(e),gi=e=>Ko(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},Jo=e=>{const t=e.devicePixelRatio;if(!(t>0))return null;const n=e.canvasWidth/t,i=e.canvasHeight/t,r=n-e.left-e.right,s=i-e.top-e.bottom;return!(r>0)||!(s>0)?null:{plotWidthCss:r,plotHeightCss:s}},Qo=e=>{const{left:t,right:n,top:i,bottom:r,canvasWidth:s,canvasHeight:o,devicePixelRatio:c}=e,l=t*c,u=s-n*c,m=i*c,f=o-r*c,a=l/s*2-1,v=u/s*2-1,M=1-m/o*2,C=1-f/o*2;return{left:a,right:v,top:M,bottom:C}},ea=(e,t,n,i)=>{if(Number.isFinite(t)&&t>0){const c=e.scale(0),l=e.scale(0+t),u=Math.abs(l-c);if(Number.isFinite(u)&&u>0)return u}const r=Math.abs(n.right-n.left);if(!(r>0))return 0;const s=Math.max(1,Math.floor(i));return r/s};function ta(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??Xo,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}}]}),s=Ve(e,64,{label:"barRenderer/vsUniforms"});Ge(e,s,Zo());const o=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}}]}),c=lt(e,{label:"barRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:yr,label:"bar.wgsl",buffers:[{arrayStride:In,stepMode:"instance",attributes:[{shaderLocation:0,format:"float32x4",offset:0},{shaderLocation:1,format:"float32x4",offset:16}]}]},fragment:{code:yr,label:"bar.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let l=null,u=0,m=new ArrayBuffer(0),f=new Float32Array(m);const a=[],v=()=>{if(n)throw new Error("BarRenderer is disposed.")},M=h=>{if(h<=f.length)return;const N=Math.max(8,xr(h));m=new ArrayBuffer(N*4),f=new Float32Array(m)},C=h=>{a.length=0;for(let w=0;w<h.length;w++){const I=h[w].data;for(let R=0;R<I.length;R++){const{x:P}=gi(I[R]);Number.isFinite(P)&&a.push(P)}}if(a.length<2)return 1;a.sort((w,I)=>w-I);let N=Number.POSITIVE_INFINITY;for(let w=1;w<a.length;w++){const I=a[w]-a[w-1];I>0&&I<N&&(N=I)}return Number.isFinite(N)&&N>0?N:1},p=h=>{let N,w,I;for(let R=0;R<h.length;R++){const P=h[R];N===void 0&&P.barWidth!==void 0&&(N=P.barWidth),w===void 0&&P.barGap!==void 0&&(w=P.barGap),I===void 0&&P.barCategoryGap!==void 0&&(I=P.barCategoryGap)}return{barWidth:N,barGap:w,barCategoryGap:I}},F=h=>{let N=Number.POSITIVE_INFINITY,w=Number.NEGATIVE_INFINITY;for(let I=0;I<h.length;I++){const R=h[I].data;for(let P=0;P<R.length;P++){const{y:T}=gi(R[P]);Number.isFinite(T)&&(T<N&&(N=T),T>w&&(w=T))}}return!Number.isFinite(N)||!Number.isFinite(w)||N<=0&&0<=w?0:Math.abs(N)<Math.abs(w)?N:w},b=(h,N,w)=>{const I=N.invert(w.bottom),R=N.invert(w.top),P=Math.min(I,R),T=Math.max(I,R);return!Number.isFinite(P)||!Number.isFinite(T)?F(h):P<=0&&0<=T?0:P>0?P:T<0?T:F(h)};return{prepare:(h,N,w,I,R)=>{if(v(),h.length===0){u=0;return}const P=Jo(R);if(!P){u=0;return}const T=Qo(R),B=T.right-T.left,U=P.plotWidthCss>0?B/P.plotWidthCss:0,G=new Map,D=new Array(h.length);let _=0;for(let te=0;te<h.length;te++){const Re=vr(h[te].stack);if(Re!==""){const Fe=G.get(Re);if(Fe!==void 0)D[te]=Fe;else{const Ae=_++;G.set(Re,Ae),D[te]=Ae}}else D[te]=_++}_=Math.max(1,_);const X=C(h),Z=p(h),V=bi(Z.barGap??Ho),re=bi(Z.barCategoryGap??Yo);let ce=1;for(let te=0;te<h.length;te++)ce=Math.max(ce,Math.floor(h[te].data.length));const Y=ea(w,X,T,ce),ne=Math.max(0,Y*(1-re)),Se=_+Math.max(0,_-1)*V,Ce=Se>0?ne/Se:0;let fe=0;const oe=Z.barWidth;if(typeof oe=="number")fe=Math.max(0,oe)*U,fe=Math.min(fe,Ce);else if(typeof oe=="string"){const te=jo(oe);fe=te==null?0:Ce*bi(te)}fe>0||(fe=Ce);const ve=fe*V,we=_*fe+Math.max(0,_-1)*ve;let ue=b(h,I,T),se=I.scale(ue);if(!Number.isFinite(se)){const te=F(h);if(ue=te,se=I.scale(te),Number.isFinite(se)||(ue=0,se=I.scale(0)),!Number.isFinite(se)){u=0;return}}let be=0;for(let te=0;te<h.length;te++)be+=Math.max(0,h[te].data.length);M(be*pi);const K=f;let ee=0;const Ie=new Map;for(let te=0;te<h.length;te++){const Re=h[te],Fe=Re.data,[Ae,We,qe,Le]=qo(Re.color),Ne=vr(Re.stack),$e=D[te]??0;for(let Ue=0;Ue<Fe.length;Ue++){const{x:et,y:Oe}=gi(Fe[Ue]),at=w.scale(et);if(!Number.isFinite(at)||!Number.isFinite(Oe))continue;const ke=at-we/2+$e*(fe+ve);let ze=se,pt=0;if(Ne!==""){let Ze=Ie.get(Ne);Ze||(Ze=new Map,Ie.set(Ne,Ze));let st;Number.isFinite(Y)&&Y>0&&Number.isFinite(at)?st=Math.round((at-T.left)/Y):Number.isFinite(X)&&X>0?st=Math.round(et/X):st=Math.round(et*1e6);let At=Ze.get(st);At||(At={posSum:ue,negSum:ue},Ze.set(st,At));let Bt,Gt;Oe>=0?(Bt=At.posSum,Gt=Bt+Oe,At.posSum=Gt):(Bt=At.negSum,Gt=Bt+Oe,At.negSum=Gt);const vn=I.scale(Bt),an=I.scale(Gt);if(!Number.isFinite(vn)||!Number.isFinite(an))continue;ze=vn,pt=an-vn}else{const Ze=I.scale(Oe);if(!Number.isFinite(Ze))continue;pt=Ze-se}K[ee+0]=ke,K[ee+1]=ze,K[ee+2]=fe,K[ee+3]=pt,K[ee+4]=Ae,K[ee+5]=We,K[ee+6]=qe,K[ee+7]=Le,ee+=pi}}u=ee/pi;const he=Math.max(4,u*In);if(!l||l.size<he){const te=Math.max(Math.max(4,xr(he)),l?l.size:0);if(l)try{l.destroy()}catch{}l=e.createBuffer({label:"barRenderer/instanceBuffer",size:te,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}u>0&&e.queue.writeBuffer(l,0,m,0,u*In)},render:h=>{v(),!(!l||u===0)&&(h.setPipeline(c),h.setBindGroup(0,o),h.setVertexBuffer(0,l),h.draw(6,u))},dispose:()=>{if(!n){if(n=!0,l)try{l.destroy()}catch{}l=null,u=0;try{s.destroy()}catch{}}}}}var wr=`// scatter.wgsl
|
|
181
|
+
// Instanced anti-aliased circle shader (SDF):
|
|
182
|
+
// - Per-instance vertex input:
|
|
183
|
+
// - center = vec2<f32> point center (transformed by VSUniforms.transform)
|
|
184
|
+
// - radiusPx = f32 circle radius in pixels
|
|
185
|
+
// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS
|
|
186
|
+
// - Uniforms:
|
|
187
|
+
// - @group(0) @binding(0): VSUniforms { transform, viewportPx }
|
|
188
|
+
// - @group(0) @binding(1): FSUniforms { color }
|
|
189
|
+
//
|
|
190
|
+
// Notes:
|
|
191
|
+
// - \`viewportPx\` is the current render target size in pixels (width, height).
|
|
192
|
+
// - The quad is expanded in clip space using \`radiusPx\` and \`viewportPx\`.
|
|
193
|
+
|
|
194
|
+
struct VSUniforms {
|
|
195
|
+
transform: mat4x4<f32>,
|
|
196
|
+
viewportPx: vec2<f32>,
|
|
197
|
+
// Pad to 16-byte alignment (mat4x4 is 64B; vec2 adds 8B; pad to 80B).
|
|
198
|
+
_pad0: vec2<f32>,
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
202
|
+
|
|
203
|
+
struct FSUniforms {
|
|
204
|
+
color: vec4<f32>,
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;
|
|
208
|
+
|
|
209
|
+
struct VSIn {
|
|
210
|
+
@location(0) center: vec2<f32>,
|
|
211
|
+
@location(1) radiusPx: f32,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
struct VSOut {
|
|
215
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
216
|
+
@location(0) localPx: vec2<f32>,
|
|
217
|
+
@location(1) radiusPx: f32,
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
@vertex
|
|
221
|
+
fn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
222
|
+
// Fixed local corners for 2 triangles (triangle-list).
|
|
223
|
+
// \`localNdc\` is a quad in [-1, 1]^2; we convert it to pixel offsets via radiusPx.
|
|
224
|
+
let localNdc = array<vec2<f32>, 6>(
|
|
225
|
+
vec2<f32>(-1.0, -1.0),
|
|
226
|
+
vec2<f32>( 1.0, -1.0),
|
|
227
|
+
vec2<f32>(-1.0, 1.0),
|
|
228
|
+
vec2<f32>(-1.0, 1.0),
|
|
229
|
+
vec2<f32>( 1.0, -1.0),
|
|
230
|
+
vec2<f32>( 1.0, 1.0)
|
|
231
|
+
);
|
|
232
|
+
|
|
233
|
+
let corner = localNdc[vertexIndex];
|
|
234
|
+
let localPx = corner * in.radiusPx;
|
|
235
|
+
|
|
236
|
+
// Convert pixel offset to clip-space offset.
|
|
237
|
+
// Clip space spans [-1, 1] across the viewport, so px -> clip is (2 / viewportPx).
|
|
238
|
+
let localClip = localPx * (2.0 / vsUniforms.viewportPx);
|
|
239
|
+
|
|
240
|
+
let centerClip = (vsUniforms.transform * vec4<f32>(in.center, 0.0, 1.0)).xy;
|
|
241
|
+
|
|
242
|
+
var out: VSOut;
|
|
243
|
+
out.clipPosition = vec4<f32>(centerClip + localClip, 0.0, 1.0);
|
|
244
|
+
out.localPx = localPx;
|
|
245
|
+
out.radiusPx = in.radiusPx;
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
@fragment
|
|
250
|
+
fn fsMain(in: VSOut) -> @location(0) vec4<f32> {
|
|
251
|
+
// Signed distance to the circle boundary (negative inside).
|
|
252
|
+
let dist = length(in.localPx) - in.radiusPx;
|
|
253
|
+
|
|
254
|
+
// Analytic-ish AA: smooth edge based on derivative of dist in screen space.
|
|
255
|
+
let w = fwidth(dist);
|
|
256
|
+
let a = 1.0 - smoothstep(0.0, w, dist);
|
|
257
|
+
|
|
258
|
+
// Discard fully outside to avoid unnecessary blending work.
|
|
259
|
+
if (a <= 0.0) {
|
|
260
|
+
discard;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return vec4<f32>(fsUniforms.color.rgb, fsUniforms.color.a * a);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
`;const na="bgra8unorm",yi=4,Tn=16,xi=Tn/4,ia=e=>Math.min(1,Math.max(0,e)),Pn=(e,t,n)=>Math.min(n,Math.max(t,e|0)),ra=e=>Ke(e)??[0,0,0,1],Fr=e=>{if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))},vi=e=>Array.isArray(e),Nr=e=>vi(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},sa=e=>{if(vi(e)){const n=e[2];return typeof n=="number"&&Number.isFinite(n)?n:null}const t=e.size;return typeof t=="number"&&Number.isFinite(t)?t:null},oa=e=>vi(e)?e:[e.x,e.y,e.size],aa=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;for(let s=0;s<e.length;s++){const{x:o,y:c}=Nr(e[s]);!Number.isFinite(o)||!Number.isFinite(c)||(o<t&&(t=o),o>n&&(n=o),c<i&&(i=c),c>r&&(r=c))}return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)?{xMin:0,xMax:1,yMin:0,yMax:1}:(t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r})},Mr=(e,t,n)=>{const i=e.scale(t),r=e.scale(n);if(!Number.isFinite(t)||!Number.isFinite(n)||t===n||!Number.isFinite(i)||!Number.isFinite(r))return{a:0,b:Number.isFinite(i)?i:0};const s=(r-i)/(n-t),o=i-s*t;return{a:Number.isFinite(s)?s:0,b:Number.isFinite(o)?o:0}},ca=(e,t,n,i,r)=>{e[0]=t,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=n,e[13]=r,e[14]=0,e[15]=1},la=e=>{const{canvasWidth:t,canvasHeight:n,devicePixelRatio:i}=e,r=e.left*i,s=t-e.right*i,o=e.top*i,c=n-e.bottom*i,l=Pn(Math.floor(r),0,Math.max(0,t)),u=Pn(Math.floor(o),0,Math.max(0,n)),m=Pn(Math.ceil(s),0,Math.max(0,t)),f=Pn(Math.ceil(c),0,Math.max(0,n)),a=Math.max(0,m-l),v=Math.max(0,f-u);return{x:l,y:u,w:a,h:v}};function ua(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??na,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),s=Ve(e,80,{label:"scatterRenderer/vsUniforms"}),o=Ve(e,16,{label:"scatterRenderer/fsUniforms"}),c=new ArrayBuffer(80),l=new Float32Array(c),u=new Float32Array(4),m=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}},{binding:1,resource:{buffer:o}}]}),f=lt(e,{label:"scatterRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:wr,label:"scatter.wgsl",buffers:[{arrayStride:Tn,stepMode:"instance",attributes:[{shaderLocation:0,format:"float32x2",offset:0},{shaderLocation:1,format:"float32",offset:8}]}]},fragment:{code:wr,label:"scatter.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let a=null,v=0,M=new ArrayBuffer(0),C=new Float32Array(M),p=0,F=0,b=[1,1],x=null;const y=()=>{if(n)throw new Error("ScatterRenderer is disposed.")},d=R=>{if(R<=C.length)return;const P=Math.max(8,Fr(R));M=new ArrayBuffer(P*4),C=new Float32Array(M)},h=(R,P,T,B,U,G)=>{const D=Number.isFinite(U)&&U>0?U:1,_=Number.isFinite(G)&&G>0?G:1;ca(l,R,P,T,B),l[16]=D,l[17]=_,l[18]=0,l[19]=0,Ge(e,s,c),b=[D,_]};return{prepare:(R,P,T,B,U)=>{y();const{xMin:G,xMax:D,yMin:_,yMax:X}=aa(P),{a:Z,b:V}=Mr(T,G,D),{a:re,b:ce}=Mr(B,_,X);U?(p=U.canvasWidth,F=U.canvasHeight,h(Z,V,re,ce,U.canvasWidth,U.canvasHeight),x=la(U)):(h(Z,V,re,ce,b[0],b[1]),x=null);const[Y,ne,Se,Ce]=ra(R.color);u[0]=Y,u[1]=ne,u[2]=Se,u[3]=ia(Ce),Ge(e,o,u);const fe=(U==null?void 0:U.devicePixelRatio)??1,oe=fe>0&&Number.isFinite(fe),ve=R.symbolSize,we=typeof ve=="function"?K=>{const ee=ve(oa(K));return typeof ee=="number"&&Number.isFinite(ee)?ee:yi}:typeof ve=="number"&&Number.isFinite(ve)?()=>ve:()=>yi;d(P.length*xi);const ue=C;let se=0;for(let K=0;K<P.length;K++){const ee=P[K],{x:Ie,y:he}=Nr(ee);if(!Number.isFinite(Ie)||!Number.isFinite(he))continue;const te=sa(ee)??we(ee),Re=Number.isFinite(te)?Math.max(0,te):yi,Fe=oe?Re*fe:Re;Fe>0&&(ue[se+0]=Ie,ue[se+1]=he,ue[se+2]=Fe,ue[se+3]=0,se+=xi)}v=se/xi;const be=Math.max(4,v*Tn);if(!a||a.size<be){const K=Math.max(Math.max(4,Fr(be)),a?a.size:0);if(a)try{a.destroy()}catch{}a=e.createBuffer({label:"scatterRenderer/instanceBuffer",size:K,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}a&&v>0&&e.queue.writeBuffer(a,0,M,0,v*Tn)},render:R=>{y(),!(!a||v===0)&&(x&&p>0&&F>0&&R.setScissorRect(x.x,x.y,x.w,x.h),R.setPipeline(f),R.setBindGroup(0,m),R.setVertexBuffer(0,a),R.draw(6,v),x&&p>0&&F>0&&R.setScissorRect(0,0,p,F))},dispose:()=>{if(!n){if(n=!0,a)try{a.destroy()}catch{}a=null,v=0;try{s.destroy()}catch{}try{o.destroy()}catch{}p=0,F=0,b=[1,1],x=null}}}}var fa=`struct ComputeUniforms {
|
|
267
|
+
transform: mat4x4<f32>,
|
|
268
|
+
viewportPx: vec2f,
|
|
269
|
+
_pad0: vec2f,
|
|
270
|
+
plotOriginPx: vec2<u32>,
|
|
271
|
+
plotSizePx: vec2<u32>,
|
|
272
|
+
binSizePx: u32,
|
|
273
|
+
binCountX: u32,
|
|
274
|
+
binCountY: u32,
|
|
275
|
+
visibleStart: u32,
|
|
276
|
+
visibleEnd: u32,
|
|
277
|
+
normalization: u32,
|
|
278
|
+
_pad1: vec2<u32>,
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
@group(0) @binding(0) var<uniform> u: ComputeUniforms;
|
|
282
|
+
@group(0) @binding(1) var<storage, read> points: array<vec2f>;
|
|
283
|
+
@group(0) @binding(2) var<storage, read_write> bins: array<atomic<u32>>;
|
|
284
|
+
|
|
285
|
+
struct MaxBuffer {
|
|
286
|
+
value: atomic<u32>,
|
|
287
|
+
};
|
|
288
|
+
@group(0) @binding(3) var<storage, read_write> maxBuf: MaxBuffer;
|
|
289
|
+
|
|
290
|
+
fn clipToDevicePx(clip: vec2f) -> vec2f {
|
|
291
|
+
// clip in [-1,1] -> device pixel in [0, viewport]
|
|
292
|
+
return vec2f(
|
|
293
|
+
(clip.x * 0.5 + 0.5) * u.viewportPx.x,
|
|
294
|
+
(-clip.y * 0.5 + 0.5) * u.viewportPx.y
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
@compute @workgroup_size(256)
|
|
299
|
+
fn binPoints(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
300
|
+
let idx = u.visibleStart + gid.x;
|
|
301
|
+
if (idx >= u.visibleEnd) {
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
let p = points[idx];
|
|
306
|
+
let clip4 = u.transform * vec4f(p.x, p.y, 0.0, 1.0);
|
|
307
|
+
let clip = clip4.xy / max(1e-9, clip4.w);
|
|
308
|
+
let px = clipToDevicePx(clip);
|
|
309
|
+
|
|
310
|
+
// Scissor bounds in device px
|
|
311
|
+
let left = f32(u.plotOriginPx.x);
|
|
312
|
+
let top = f32(u.plotOriginPx.y);
|
|
313
|
+
let right = left + f32(u.plotSizePx.x);
|
|
314
|
+
let bottom = top + f32(u.plotSizePx.y);
|
|
315
|
+
|
|
316
|
+
if (px.x < left || px.x >= right || px.y < top || px.y >= bottom) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let localX = u32((px.x - left) / f32(u.binSizePx));
|
|
321
|
+
let localY = u32((px.y - top) / f32(u.binSizePx));
|
|
322
|
+
if (localX >= u.binCountX || localY >= u.binCountY) {
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
let binIndex = localY * u.binCountX + localX;
|
|
327
|
+
atomicAdd(&bins[binIndex], 1u);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
@compute @workgroup_size(256)
|
|
331
|
+
fn reduceMax(@builtin(global_invocation_id) gid: vec3<u32>) {
|
|
332
|
+
let binTotal = u.binCountX * u.binCountY;
|
|
333
|
+
let i = gid.x;
|
|
334
|
+
if (i >= binTotal) {
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
let v = atomicLoad(&bins[i]);
|
|
339
|
+
atomicMax(&maxBuf.value, v);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
`,Sr=`struct RenderUniforms {
|
|
343
|
+
plotOriginPx: vec2<u32>,
|
|
344
|
+
plotSizePx: vec2<u32>,
|
|
345
|
+
binSizePx: u32,
|
|
346
|
+
binCountX: u32,
|
|
347
|
+
binCountY: u32,
|
|
348
|
+
normalization: u32,
|
|
349
|
+
_pad: vec2<u32>,
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
@group(0) @binding(0) var<uniform> u: RenderUniforms;
|
|
353
|
+
@group(0) @binding(1) var<storage, read> bins: array<u32>;
|
|
354
|
+
@group(0) @binding(2) var<storage, read> maxBuf: array<u32>;
|
|
355
|
+
@group(0) @binding(3) var lutTex: texture_2d<f32>;
|
|
356
|
+
|
|
357
|
+
struct VsOut {
|
|
358
|
+
@builtin(position) position: vec4f,
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
@vertex
|
|
362
|
+
fn vsMain(@builtin(vertex_index) vid: u32) -> VsOut {
|
|
363
|
+
// Fullscreen triangle (covers clip space).
|
|
364
|
+
// (0,0)->(-1,-1), (2,0)->(3,-1), (0,2)->(-1,3)
|
|
365
|
+
var pos = array<vec2f, 3>(
|
|
366
|
+
vec2f(-1.0, -1.0),
|
|
367
|
+
vec2f(3.0, -1.0),
|
|
368
|
+
vec2f(-1.0, 3.0)
|
|
369
|
+
);
|
|
370
|
+
var out: VsOut;
|
|
371
|
+
out.position = vec4f(pos[vid], 0.0, 1.0);
|
|
372
|
+
return out;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
fn applyNormalization(count: f32, maxCount: f32, mode: u32) -> f32 {
|
|
376
|
+
if (maxCount <= 0.0) {
|
|
377
|
+
return 0.0;
|
|
378
|
+
}
|
|
379
|
+
let t = clamp(count / maxCount, 0.0, 1.0);
|
|
380
|
+
if (mode == 1u) { // sqrt
|
|
381
|
+
return sqrt(t);
|
|
382
|
+
}
|
|
383
|
+
if (mode == 2u) { // log
|
|
384
|
+
// log1p(count) / log1p(max)
|
|
385
|
+
return clamp(log(1.0 + count) / max(1e-9, log(1.0 + maxCount)), 0.0, 1.0);
|
|
386
|
+
}
|
|
387
|
+
return t; // linear
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
@fragment
|
|
391
|
+
fn fsMain(@builtin(position) pos: vec4f) -> @location(0) vec4f {
|
|
392
|
+
// pos.xy is framebuffer pixel coords (device px) with origin top-left.
|
|
393
|
+
let x = pos.x;
|
|
394
|
+
let y = pos.y;
|
|
395
|
+
|
|
396
|
+
let left = f32(u.plotOriginPx.x);
|
|
397
|
+
let top = f32(u.plotOriginPx.y);
|
|
398
|
+
// plot scissor also applied on CPU; keep a guard anyway.
|
|
399
|
+
if (x < left || y < top) {
|
|
400
|
+
return vec4f(0.0);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
let localX = u32((x - left) / f32(u.binSizePx));
|
|
404
|
+
let localY = u32((y - top) / f32(u.binSizePx));
|
|
405
|
+
if (localX >= u.binCountX || localY >= u.binCountY) {
|
|
406
|
+
return vec4f(0.0);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
let idx = localY * u.binCountX + localX;
|
|
410
|
+
let c = f32(bins[idx]);
|
|
411
|
+
let maxC = f32(maxBuf[0]);
|
|
412
|
+
|
|
413
|
+
let t = applyNormalization(c, maxC, u.normalization);
|
|
414
|
+
let lutX = i32(round(t * 255.0));
|
|
415
|
+
let lut = textureLoad(lutTex, vec2<i32>(lutX, 0), 0);
|
|
416
|
+
return vec4f(lut.rgb, 1.0);
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
`;const ma="bgra8unorm",Rn=e=>Math.min(1,Math.max(0,e)),_t=(e,t,n)=>Math.min(n,Math.max(t,e|0)),da=e=>{if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))},Cr=(e,t,n)=>{const i=e.scale(t),r=e.scale(n);if(!Number.isFinite(t)||!Number.isFinite(n)||t===n||!Number.isFinite(i)||!Number.isFinite(r))return{a:0,b:Number.isFinite(i)?i:0};const s=(r-i)/(n-t),o=i-s*t;return{a:Number.isFinite(s)?s:0,b:Number.isFinite(o)?o:0}},ha=(e,t,n,i,r)=>{e[0]=t,e[1]=0,e[2]=0,e[3]=0,e[4]=0,e[5]=i,e[6]=0,e[7]=0,e[8]=0,e[9]=0,e[10]=1,e[11]=0,e[12]=n,e[13]=r,e[14]=0,e[15]=1},pa=e=>{const{canvasWidth:t,canvasHeight:n,devicePixelRatio:i}=e,r=e.left*i,s=t-e.right*i,o=e.top*i,c=n-e.bottom*i,l=_t(Math.floor(r),0,Math.max(0,t)),u=_t(Math.floor(o),0,Math.max(0,n)),m=_t(Math.ceil(s),0,Math.max(0,t)),f=_t(Math.ceil(c),0,Math.max(0,n)),a=Math.max(0,m-l),v=Math.max(0,f-u);return{x:l,y:u,w:a,h:v}},An=(e,t,n)=>e+(t-e)*n,ba=(e,t,n)=>[An(e[0],t[0],n),An(e[1],t[1],n),An(e[2],t[2],n),An(e[3],t[3],n)],ga=e=>Ke(e)??[0,0,0,1],Ir=e=>e==="plasma"?["#0d0887","#6a00a8","#b12a90","#e16462","#fca636","#f0f921"]:e==="inferno"?["#000004","#420a68","#932667","#dd513a","#fca50a","#fcffa4"]:["#440154","#3b528b","#21918c","#5ec962","#fde725"],ya=e=>{const n=(typeof e=="string"?Ir(e):Array.isArray(e)&&e.length>0?e:Ir("viridis")).map(ga),i=Math.max(2,n.length),r=new Uint8Array(new ArrayBuffer(256*4));for(let s=0;s<256;s++){const c=s/255*(i-1),l=Math.min(i-2,Math.max(0,Math.floor(c))),u=c-l,m=ba(n[l],n[l+1],u);r[s*4+0]=_t(Math.round(Rn(m[0])*255),0,255),r[s*4+1]=_t(Math.round(Rn(m[1])*255),0,255),r[s*4+2]=_t(Math.round(Rn(m[2])*255),0,255),r[s*4+3]=_t(Math.round(Rn(m[3])*255),0,255)}return r},xa=e=>{if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return"custom"}},va=e=>e==="sqrt"?1:e==="log"?2:0;function wa(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??ma,r=e.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:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}}]}),s=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:2,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"read-only-storage"}},{binding:3,visibility:GPUShaderStage.FRAGMENT,texture:{sampleType:"unfilterable-float"}}]}),o=Ve(e,128,{label:"scatterDensity/computeUniforms"}),c=new ArrayBuffer(128),l=new Float32Array(c,0,20),u=new Uint32Array(c),m=Ve(e,48,{label:"scatterDensity/renderUniforms"}),f=new ArrayBuffer(48),a=new Uint32Array(f),v=or(e,fa,"scatterDensityBinning.wgsl"),M=e.createComputePipeline({label:"scatterDensity/binPointsPipeline",layout:e.createPipelineLayout({bindGroupLayouts:[r]}),compute:{module:v,entryPoint:"binPoints"}}),C=e.createComputePipeline({label:"scatterDensity/reduceMaxPipeline",layout:e.createPipelineLayout({bindGroupLayouts:[r]}),compute:{module:v,entryPoint:"reduceMax"}}),p=lt(e,{label:"scatterDensity/renderPipeline",bindGroupLayouts:[s],vertex:{code:Sr,label:"scatterDensityColormap.wgsl"},fragment:{code:Sr,label:"scatterDensityColormap.wgsl",formats:i,blend:void 0},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let F=null,b=null,x=0,y=null,d=null,h="",N=null,w=null,I=null,R=-1,P=0,T=0,B=0,U=0,G=0,D=null,_=0,X=0,Z=2,V=!0,re=!1,ce=new Uint32Array(0);const Y=()=>{if(n)throw new Error("ScatterDensityRenderer is disposed.")},ne=ue=>{const se=xa(ue.densityColormap);if(y||(y=e.createTexture({label:"scatterDensity/lutTexture",size:{width:256,height:1,depthOrArrayLayers:1},format:"rgba8unorm",usage:GPUTextureUsage.TEXTURE_BINDING|GPUTextureUsage.COPY_DST}),d=y.createView(),h=""),se===h)return;const be=ya(ue.densityColormap);e.queue.writeTexture({texture:y},be,{bytesPerRow:256*4,rowsPerImage:1},{width:256,height:1,depthOrArrayLayers:1}),h=se},Se=(ue,se)=>{const be=Math.max(1,ue|0)*Math.max(1,se|0);if(F&&b&&be<=x)return;const K=Math.max(1,be);if(x=Math.max(256,da(K)),F){try{F.destroy()}catch{}F=null}if(b){try{b.destroy()}catch{}b=null}F=e.createBuffer({label:"scatterDensity/binsBuffer",size:x*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),b=e.createBuffer({label:"scatterDensity/maxBuffer",size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),ce=new Uint32Array(x),N=null,w=null,V=!0},Ce=()=>{!F||!b||!d||!I||(N||(N=e.createBindGroup({label:"scatterDensity/computeBindGroup",layout:r,entries:[{binding:0,resource:{buffer:o}},{binding:1,resource:{buffer:I}},{binding:2,resource:{buffer:F}},{binding:3,resource:{buffer:b}}]})),w||(w=e.createBindGroup({label:"scatterDensity/renderBindGroup",layout:s,entries:[{binding:0,resource:{buffer:m}},{binding:1,resource:{buffer:F}},{binding:2,resource:{buffer:b}},{binding:3,resource:d}]})))};return{prepare:(ue,se,be,K,ee,Ie,he,te,Re)=>{Y(),re=!0;const Fe=pa(te),Ae=te.devicePixelRatio,We=Number.isFinite(ue.binSize)?Math.max(1e-6,ue.binSize):2,qe=Math.max(1,Math.round(We*(Number.isFinite(Ae)&&Ae>0?Ae:1))),Le=Math.max(1,Math.ceil(Fe.w/qe)),Ne=Math.max(1,Math.ceil(Fe.h/qe));Se(Le,Ne),ne(ue);const $e=va(ue.densityNormalization);I!==se&&(I=se,N=null,w=null,V=!0),R!==be&&(R=be,V=!0),(P!==K||T!==ee)&&(P=K,T=ee,V=!0),(B!==qe||U!==Le||G!==Ne)&&(B=qe,U=Le,G=Ne,V=!0),(!D||D.x!==Fe.x||D.y!==Fe.y||D.w!==Fe.w||D.h!==Fe.h)&&(D=Fe,V=!0),(_!==te.canvasWidth||X!==te.canvasHeight)&&(_=te.canvasWidth,X=te.canvasHeight,V=!0),Z!==$e&&(Z=$e,V=!0);const Ue=Re,et=(Ue==null?void 0:Ue.xMin)??0,Oe=(Ue==null?void 0:Ue.xMax)??1,at=(Ue==null?void 0:Ue.yMin)??0,ke=(Ue==null?void 0:Ue.yMax)??1,{a:ze,b:pt}=Cr(Ie,et,Oe),{a:Ze,b:st}=Cr(he,at,ke);ha(l,ze,pt,Ze,st),l[16]=te.canvasWidth>0?te.canvasWidth:1,l[17]=te.canvasHeight>0?te.canvasHeight:1,l[18]=0,l[19]=0,u[20]=Fe.x>>>0,u[21]=Fe.y>>>0,u[22]=Fe.w>>>0,u[23]=Fe.h>>>0,u[24]=qe>>>0,u[25]=Le>>>0,u[26]=Ne>>>0,u[27]=(Math.max(0,K)|0)>>>0,u[28]=(Math.max(0,ee)|0)>>>0,u[29]=$e>>>0,Ge(e,o,c),a[0]=Fe.x>>>0,a[1]=Fe.y>>>0,a[2]=Fe.w>>>0,a[3]=Fe.h>>>0,a[4]=qe>>>0,a[5]=Le>>>0,a[6]=Ne>>>0,a[7]=$e>>>0,Ge(e,m,f),Ce()},encodeCompute:ue=>{if(Y(),!re||!V)return;if(!F||!b||!N||R<=0){V=!1;return}if(!D||D.w<=0||D.h<=0){V=!1;return}e.queue.writeBuffer(F,0,ce.buffer,0,x*4),e.queue.writeBuffer(b,0,new Uint32Array([0]).buffer);const se=U*G|0,be=Math.max(0,T-P|0),K=ue.beginComputePass({label:"scatterDensity/computePass"});K.setBindGroup(0,N),K.setPipeline(M);const ee=256,Ie=Math.ceil(be/ee);Ie>0&&K.dispatchWorkgroups(Ie),K.setPipeline(C);const he=Math.ceil(se/ee);he>0&&K.dispatchWorkgroups(he),K.end(),V=!1},render:ue=>{Y(),re&&(!w||!D||!d||D.w<=0||D.h<=0||(ue.setScissorRect(D.x,D.y,D.w,D.h),ue.setPipeline(p),ue.setBindGroup(0,w),ue.draw(3),_>0&&X>0&&ue.setScissorRect(0,0,_,X)))},dispose:()=>{if(!n){n=!0;try{o.destroy()}catch{}try{m.destroy()}catch{}if(F)try{F.destroy()}catch{}if(b)try{b.destroy()}catch{}if(F=null,b=null,x=0,y)try{y.destroy()}catch{}y=null,d=null,N=null,w=null,I=null}}}}var Tr=`// pie.wgsl
|
|
420
|
+
// Instanced anti-aliased pie-slice shader (instanced quad + SDF mask).
|
|
421
|
+
//
|
|
422
|
+
// - Per-instance vertex input:
|
|
423
|
+
// - center = vec2<f32> slice center (transformed by VSUniforms.transform)
|
|
424
|
+
// - startAngleRad = f32 start angle in radians
|
|
425
|
+
// - endAngleRad = f32 end angle in radians
|
|
426
|
+
// - radiiPx = vec2<f32>(innerRadiusPx, outerRadiusPx) in *device pixels*
|
|
427
|
+
// - color = vec4<f32> RGBA color in [0..1]
|
|
428
|
+
//
|
|
429
|
+
// - Draw call: draw(6, instanceCount) using triangle-list expansion in VS
|
|
430
|
+
//
|
|
431
|
+
// - Uniforms:
|
|
432
|
+
// - @group(0) @binding(0): VSUniforms { transform, viewportPx }
|
|
433
|
+
//
|
|
434
|
+
// Notes:
|
|
435
|
+
// - The quad is expanded in clip space using \`radiusPx\` and \`viewportPx\`.
|
|
436
|
+
// - Fragment uses an SDF mask for the circle boundary + an angular wedge mask.
|
|
437
|
+
// - Fully outside fragments are discarded to avoid unnecessary blending work.
|
|
438
|
+
//
|
|
439
|
+
// Conventions: matches other shaders in this repo (vsMain/fsMain, group 0 bindings,
|
|
440
|
+
// and explicit uniform padding/alignment where needed).
|
|
441
|
+
|
|
442
|
+
const PI: f32 = 3.141592653589793;
|
|
443
|
+
const TAU: f32 = 6.283185307179586; // 2*pi
|
|
444
|
+
|
|
445
|
+
struct VSUniforms {
|
|
446
|
+
transform: mat4x4<f32>,
|
|
447
|
+
viewportPx: vec2<f32>,
|
|
448
|
+
// Pad to 16-byte alignment (mat4x4 is 64B; vec2 adds 8B; pad to 80B).
|
|
449
|
+
_pad0: vec2<f32>,
|
|
450
|
+
};
|
|
451
|
+
|
|
452
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
453
|
+
|
|
454
|
+
struct VSIn {
|
|
455
|
+
@location(0) center: vec2<f32>,
|
|
456
|
+
@location(1) startAngleRad: f32,
|
|
457
|
+
@location(2) endAngleRad: f32,
|
|
458
|
+
@location(3) radiiPx: vec2<f32>, // (innerPx, outerPx)
|
|
459
|
+
@location(4) color: vec4<f32>,
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
struct VSOut {
|
|
463
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
464
|
+
@location(0) localPx: vec2<f32>,
|
|
465
|
+
@location(1) startAngleRad: f32,
|
|
466
|
+
@location(2) endAngleRad: f32,
|
|
467
|
+
@location(3) radiiPx: vec2<f32>,
|
|
468
|
+
@location(4) color: vec4<f32>,
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
@vertex
|
|
472
|
+
fn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
473
|
+
// Fixed local corners for 2 triangles (triangle-list).
|
|
474
|
+
// \`localNdc\` is a quad in [-1, 1]^2; we convert it to pixel offsets via radiusPx.
|
|
475
|
+
let localNdc = array<vec2<f32>, 6>(
|
|
476
|
+
vec2<f32>(-1.0, -1.0),
|
|
477
|
+
vec2<f32>( 1.0, -1.0),
|
|
478
|
+
vec2<f32>(-1.0, 1.0),
|
|
479
|
+
vec2<f32>(-1.0, 1.0),
|
|
480
|
+
vec2<f32>( 1.0, -1.0),
|
|
481
|
+
vec2<f32>( 1.0, 1.0)
|
|
482
|
+
);
|
|
483
|
+
|
|
484
|
+
let corner = localNdc[vertexIndex];
|
|
485
|
+
let outerPx = in.radiiPx.y;
|
|
486
|
+
let localPx = corner * outerPx;
|
|
487
|
+
|
|
488
|
+
// Convert pixel offset to clip-space offset.
|
|
489
|
+
// Clip space spans [-1, 1] across the viewport, so px -> clip is (2 / viewportPx).
|
|
490
|
+
let localClip = localPx * (2.0 / vsUniforms.viewportPx);
|
|
491
|
+
|
|
492
|
+
let centerClip = (vsUniforms.transform * vec4<f32>(in.center, 0.0, 1.0)).xy;
|
|
493
|
+
|
|
494
|
+
var out: VSOut;
|
|
495
|
+
out.clipPosition = vec4<f32>(centerClip + localClip, 0.0, 1.0);
|
|
496
|
+
out.localPx = localPx;
|
|
497
|
+
out.startAngleRad = in.startAngleRad;
|
|
498
|
+
out.endAngleRad = in.endAngleRad;
|
|
499
|
+
out.radiiPx = in.radiiPx;
|
|
500
|
+
out.color = in.color;
|
|
501
|
+
return out;
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
fn wrapToTau(theta: f32) -> f32 {
|
|
505
|
+
// Maps theta to [0, TAU). (Input often comes from atan2 in [-PI, PI].)
|
|
506
|
+
return select(theta, theta + TAU, theta < 0.0);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
@fragment
|
|
510
|
+
fn fsMain(in: VSOut) -> @location(0) vec4<f32> {
|
|
511
|
+
let p = in.localPx;
|
|
512
|
+
let r = length(p);
|
|
513
|
+
|
|
514
|
+
let innerPx = in.radiiPx.x;
|
|
515
|
+
let outerPx = in.radiiPx.y;
|
|
516
|
+
|
|
517
|
+
// --- Radial mask: ring between inner and outer radii (inner==0 => pie) ---
|
|
518
|
+
// Positive inside the ring, negative outside.
|
|
519
|
+
let radialDist = min(r - innerPx, outerPx - r);
|
|
520
|
+
let radialW = fwidth(radialDist);
|
|
521
|
+
let radialA = smoothstep(-radialW, radialW, radialDist);
|
|
522
|
+
|
|
523
|
+
if (radialA <= 0.0) {
|
|
524
|
+
discard;
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
// Compute fragment angle in [0, TAU).
|
|
528
|
+
let angle = wrapToTau(atan2(p.y, p.x));
|
|
529
|
+
|
|
530
|
+
// --- Angular mask: wedge between start/end angles with wrap ---
|
|
531
|
+
let start = in.startAngleRad;
|
|
532
|
+
let end = in.endAngleRad;
|
|
533
|
+
|
|
534
|
+
// Compute span in [0, 2π) with wrap.
|
|
535
|
+
var span = end - start;
|
|
536
|
+
span = span + select(0.0, TAU, span < 0.0);
|
|
537
|
+
|
|
538
|
+
// Compute rel in [0, 2π) with wrap.
|
|
539
|
+
var rel = angle - start;
|
|
540
|
+
rel = rel + select(0.0, TAU, rel < 0.0);
|
|
541
|
+
|
|
542
|
+
let inside = rel <= span;
|
|
543
|
+
|
|
544
|
+
// Signed angular distance (in radians) to nearest boundary.
|
|
545
|
+
// - Inside: +min(rel, span-rel)
|
|
546
|
+
// - Outside: -min(rel-span, 2π-rel)
|
|
547
|
+
let dIn = min(rel, max(span - rel, 0.0));
|
|
548
|
+
let dOutA = max(rel - span, 0.0);
|
|
549
|
+
let dOutB = max(TAU - rel, 0.0);
|
|
550
|
+
let dOut = min(dOutA, dOutB);
|
|
551
|
+
|
|
552
|
+
let signedAngleDist = select(-dOut, dIn, inside);
|
|
553
|
+
|
|
554
|
+
// Convert to approximate pixel distance to the boundary ray.
|
|
555
|
+
// (For small angles, perpendicular distance to a ray ≈ r * angle.)
|
|
556
|
+
let angleDistPx = signedAngleDist * max(r, 1.0);
|
|
557
|
+
|
|
558
|
+
let angW = fwidth(angleDistPx);
|
|
559
|
+
let angularA = smoothstep(-angW, angW, angleDistPx);
|
|
560
|
+
|
|
561
|
+
let aOut = radialA * angularA;
|
|
562
|
+
if (aOut <= 0.0) {
|
|
563
|
+
discard;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
return vec4<f32>(in.color.rgb, in.color.a * aOut);
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
`;const Fa="bgra8unorm",Bn=40,wi=Bn/4,un=Math.PI*2,Pr=e=>Math.min(1,Math.max(0,e)),En=(e,t,n)=>Math.min(n,Math.max(t,e|0)),Rr=e=>{if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))},Ar=e=>{if(!Number.isFinite(e))return 0;const t=e%un;return t<0?t+un:t},Na=(e,t)=>{const n=Ke(e);if(n)return[n[0],n[1],n[2],Pr(n[3])];const i=Ke(t);return i?[i[0],i[1],i[2],Pr(i[3])]:[0,0,0,1]},fn=(e,t)=>{if(typeof e=="number")return Number.isFinite(e)?e:null;if(typeof e!="string")return null;const n=e.trim();if(n.length===0)return null;if(n.endsWith("%")){const r=Number.parseFloat(n.slice(0,-1));return Number.isFinite(r)?r/100*t:null}const i=Number.parseFloat(n);return Number.isFinite(i)?i:null},Ma=(e,t,n)=>{const i=(e==null?void 0:e[0])??"50%",r=(e==null?void 0:e[1])??"50%",s=fn(i,t),o=fn(r,n);return{x:Number.isFinite(s)?s:t*.5,y:Number.isFinite(o)?o:n*.5}},Sa=e=>Array.isArray(e),Ca=(e,t)=>{if(e==null)return{inner:0,outer:t*.7};if(Sa(e)){const r=fn(e[0],t),s=fn(e[1],t),o=Math.max(0,Number.isFinite(r)?r:0),c=Math.max(o,Number.isFinite(s)?s:t*.7);return{inner:o,outer:Math.min(t,c)}}const n=fn(e,t),i=Math.max(0,Number.isFinite(n)?n:t*.7);return{inner:0,outer:Math.min(t,i)}},Ia=e=>{const{canvasWidth:t,canvasHeight:n,devicePixelRatio:i}=e,r=e.left*i,s=t-e.right*i,o=e.top*i,c=n-e.bottom*i,l=En(Math.floor(r),0,Math.max(0,t)),u=En(Math.floor(o),0,Math.max(0,n)),m=En(Math.ceil(s),0,Math.max(0,t)),f=En(Math.ceil(c),0,Math.max(0,n)),a=Math.max(0,m-l),v=Math.max(0,f-u);return{x:l,y:u,w:a,h:v}},Ta=new Float32Array([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]);function Pa(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??Fa,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}}]}),s=Ve(e,80,{label:"pieRenderer/vsUniforms"}),o=new ArrayBuffer(80),c=new Float32Array(o),l=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}}]}),u=lt(e,{label:"pieRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:Tr,label:"pie.wgsl",buffers:[{arrayStride:Bn,stepMode:"instance",attributes:[{shaderLocation:0,format:"float32x2",offset:0},{shaderLocation:1,format:"float32",offset:8},{shaderLocation:2,format:"float32",offset:12},{shaderLocation:3,format:"float32x2",offset:16},{shaderLocation:4,format:"float32x4",offset:24}]}]},fragment:{code:Tr,label:"pie.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let m=null,f=0,a=new ArrayBuffer(0),v=new Float32Array(a),M=0,C=0,p=null;const F=()=>{if(n)throw new Error("PieRenderer is disposed.")},b=N=>{if(N<=v.length)return;const w=Math.max(8,Rr(N));a=new ArrayBuffer(w*4),v=new Float32Array(a)},x=(N,w)=>{const I=Number.isFinite(N)&&N>0?N:1,R=Number.isFinite(w)&&w>0?w:1;c.set(Ta,0),c[16]=I,c[17]=R,c[18]=0,c[19]=0,Ge(e,s,o)};return{prepare:(N,w)=>{var ee;F();const I=w.devicePixelRatio,R=I>0&&Number.isFinite(I)?I:1;M=w.canvasWidth,C=w.canvasHeight,x(w.canvasWidth,w.canvasHeight),p=Ia(w);const P=w.canvasWidth/R,T=w.canvasHeight/R;if(!(P>0)||!(T>0)){f=0;return}const B=P-w.left-w.right,U=T-w.top-w.bottom;if(!(B>0)||!(U>0)){f=0;return}const G=.5*Math.min(B,U);if(!(G>0)){f=0;return}const D=Ma(N.center,B,U),_=w.left+D.x,X=w.top+D.y,Z=_/P*2-1,V=1-X/T*2;if(!Number.isFinite(Z)||!Number.isFinite(V)){f=0;return}const re=Ca(N.radius,G),ce=Math.max(0,Math.min(re.inner,re.outer)),Y=Math.max(ce,re.outer),ne=ce*R,Se=Y*R;if(!(Se>0)){f=0;return}let Ce=0,fe=0;for(let Ie=0;Ie<N.data.length;Ie++){const he=(ee=N.data[Ie])==null?void 0:ee.value;typeof he=="number"&&Number.isFinite(he)&&he>0&&(Ce+=he,fe++)}if(!(Ce>0)||fe===0){f=0;return}b(fe*wi);const oe=v,ve=typeof N.startAngle=="number"&&Number.isFinite(N.startAngle)?N.startAngle:90;let we=Ar(ve*Math.PI/180),ue=0,se=0,be=0;for(let Ie=0;Ie<N.data.length;Ie++){const he=N.data[Ie],te=he==null?void 0:he.value;if(typeof te!="number"||!Number.isFinite(te)||te<=0)continue;be++;const Re=be===fe;let Ae=te/Ce*un;if(Re?Ae=Math.max(0,un-ue):Ae=Math.max(0,Math.min(un,Ae)),ue+=Ae,!(Ae>0))continue;const We=we,qe=Ar(we+Ae);we=qe;const[Le,Ne,$e,Ue]=Na(he.color,N.color);oe[se+0]=Z,oe[se+1]=V,oe[se+2]=We,oe[se+3]=qe,oe[se+4]=ne,oe[se+5]=Se,oe[se+6]=Le,oe[se+7]=Ne,oe[se+8]=$e,oe[se+9]=Ue,se+=wi}f=se/wi;const K=Math.max(4,f*Bn);if(!m||m.size<K){const Ie=Math.max(Math.max(4,Rr(K)),m?m.size:0);if(m)try{m.destroy()}catch{}m=e.createBuffer({label:"pieRenderer/instanceBuffer",size:Ie,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}m&&f>0&&e.queue.writeBuffer(m,0,a,0,f*Bn)},render:N=>{F(),!(!m||f===0)&&(p&&M>0&&C>0&&N.setScissorRect(p.x,p.y,p.w,p.h),N.setPipeline(u),N.setBindGroup(0,l),N.setVertexBuffer(0,m),N.draw(6,f),p&&M>0&&C>0&&N.setScissorRect(0,0,M,C))},dispose:()=>{if(!n){if(n=!0,m)try{m.destroy()}catch{}m=null,f=0;try{s.destroy()}catch{}M=0,C=0,p=null}}}}var Br=`// candlestick.wgsl
|
|
570
|
+
// Instanced candlestick shader (bodies + wicks):
|
|
571
|
+
// - Per-instance vertex input:
|
|
572
|
+
// - xClip, openClip, closeClip, lowClip, highClip, bodyWidthClip (6 floats)
|
|
573
|
+
// - bodyColor rgba (4 floats)
|
|
574
|
+
// - Draw call: draw(18, instanceCount) using triangle-list expansion in VS
|
|
575
|
+
// - vertices 0-5: body quad (2 triangles)
|
|
576
|
+
// - vertices 6-11: upper wick (2 triangles)
|
|
577
|
+
// - vertices 12-17: lower wick (2 triangles)
|
|
578
|
+
// - Uniforms:
|
|
579
|
+
// - @group(0) @binding(0): VSUniforms { transform, wickWidthClip }
|
|
580
|
+
|
|
581
|
+
struct VSUniforms {
|
|
582
|
+
transform: mat4x4<f32>,
|
|
583
|
+
wickWidthClip: f32,
|
|
584
|
+
_pad0: f32,
|
|
585
|
+
_pad1: f32,
|
|
586
|
+
_pad2: f32,
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
590
|
+
|
|
591
|
+
struct VSIn {
|
|
592
|
+
@location(0) xClip: f32,
|
|
593
|
+
@location(1) openClip: f32,
|
|
594
|
+
@location(2) closeClip: f32,
|
|
595
|
+
@location(3) lowClip: f32,
|
|
596
|
+
@location(4) highClip: f32,
|
|
597
|
+
@location(5) bodyWidthClip: f32,
|
|
598
|
+
@location(6) bodyColor: vec4<f32>,
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
struct VSOut {
|
|
602
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
603
|
+
@location(0) color: vec4<f32>,
|
|
604
|
+
};
|
|
605
|
+
|
|
606
|
+
@vertex
|
|
607
|
+
fn vsMain(in: VSIn, @builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
608
|
+
// Compute body bounds
|
|
609
|
+
let bodyTop = max(in.openClip, in.closeClip);
|
|
610
|
+
let bodyBottom = min(in.openClip, in.closeClip);
|
|
611
|
+
let bodyLeft = in.xClip - in.bodyWidthClip * 0.5;
|
|
612
|
+
let bodyRight = in.xClip + in.bodyWidthClip * 0.5;
|
|
613
|
+
|
|
614
|
+
// Wick bounds
|
|
615
|
+
let wickLeft = in.xClip - vsUniforms.wickWidthClip * 0.5;
|
|
616
|
+
let wickRight = in.xClip + vsUniforms.wickWidthClip * 0.5;
|
|
617
|
+
|
|
618
|
+
var pos: vec2<f32>;
|
|
619
|
+
|
|
620
|
+
if (vertexIndex < 6u) {
|
|
621
|
+
// Body quad (vertices 0-5)
|
|
622
|
+
let corners = array<vec2<f32>, 6>(
|
|
623
|
+
vec2<f32>(0.0, 0.0),
|
|
624
|
+
vec2<f32>(1.0, 0.0),
|
|
625
|
+
vec2<f32>(0.0, 1.0),
|
|
626
|
+
vec2<f32>(0.0, 1.0),
|
|
627
|
+
vec2<f32>(1.0, 0.0),
|
|
628
|
+
vec2<f32>(1.0, 1.0)
|
|
629
|
+
);
|
|
630
|
+
let corner = corners[vertexIndex];
|
|
631
|
+
let bodyMin = vec2<f32>(bodyLeft, bodyBottom);
|
|
632
|
+
let bodyMax = vec2<f32>(bodyRight, bodyTop);
|
|
633
|
+
pos = bodyMin + corner * (bodyMax - bodyMin);
|
|
634
|
+
} else if (vertexIndex < 12u) {
|
|
635
|
+
// Upper wick (vertices 6-11): from bodyTop to highClip
|
|
636
|
+
let idx = vertexIndex - 6u;
|
|
637
|
+
let corners = array<vec2<f32>, 6>(
|
|
638
|
+
vec2<f32>(0.0, 0.0),
|
|
639
|
+
vec2<f32>(1.0, 0.0),
|
|
640
|
+
vec2<f32>(0.0, 1.0),
|
|
641
|
+
vec2<f32>(0.0, 1.0),
|
|
642
|
+
vec2<f32>(1.0, 0.0),
|
|
643
|
+
vec2<f32>(1.0, 1.0)
|
|
644
|
+
);
|
|
645
|
+
let corner = corners[idx];
|
|
646
|
+
let wickMin = vec2<f32>(wickLeft, bodyTop);
|
|
647
|
+
let wickMax = vec2<f32>(wickRight, in.highClip);
|
|
648
|
+
pos = wickMin + corner * (wickMax - wickMin);
|
|
649
|
+
} else {
|
|
650
|
+
// Lower wick (vertices 12-17): from lowClip to bodyBottom
|
|
651
|
+
let idx = vertexIndex - 12u;
|
|
652
|
+
let corners = array<vec2<f32>, 6>(
|
|
653
|
+
vec2<f32>(0.0, 0.0),
|
|
654
|
+
vec2<f32>(1.0, 0.0),
|
|
655
|
+
vec2<f32>(0.0, 1.0),
|
|
656
|
+
vec2<f32>(0.0, 1.0),
|
|
657
|
+
vec2<f32>(1.0, 0.0),
|
|
658
|
+
vec2<f32>(1.0, 1.0)
|
|
659
|
+
);
|
|
660
|
+
let corner = corners[idx];
|
|
661
|
+
let wickMin = vec2<f32>(wickLeft, in.lowClip);
|
|
662
|
+
let wickMax = vec2<f32>(wickRight, bodyBottom);
|
|
663
|
+
pos = wickMin + corner * (wickMax - wickMin);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
var out: VSOut;
|
|
667
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(pos, 0.0, 1.0);
|
|
668
|
+
out.color = in.bodyColor;
|
|
669
|
+
return out;
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
@fragment
|
|
673
|
+
fn fsMain(in: VSOut) -> @location(0) vec4<f32> {
|
|
674
|
+
return in.color;
|
|
675
|
+
}
|
|
676
|
+
`;const Ra="bgra8unorm",Aa=1,rn=40,zt=rn/4,Ba=e=>Math.min(1,Math.max(0,e)),Dn=(e,t,n)=>Math.min(n,Math.max(t,e|0)),mn=e=>Ke(e)??[0,0,0,1],Un=e=>{if(!Number.isFinite(e)||e<=0)return 1;const t=Math.ceil(e);return 2**Math.ceil(Math.log2(t))},Ea=e=>{const t=e.trim().match(/^(\d+(?:\.\d+)?)%$/);if(!t)return null;const n=Number(t[1])/100;return Number.isFinite(n)?n:null},Da=e=>Array.isArray(e),Er=e=>Da(e)?{timestamp:e[0],open:e[1],close:e[2],low:e[3],high:e[4]}:{timestamp:e.timestamp,open:e.open,close:e.close,low:e.low,high:e.high},Ua=e=>{const t=e.devicePixelRatio;if(!(t>0))return null;const n=e.canvasWidth/t,i=e.canvasHeight/t,r=n-e.left-e.right,s=i-e.top-e.bottom;return!(r>0)||!(s>0)?null:{plotWidthCss:r,plotHeightCss:s}},La=e=>{const{left:t,right:n,top:i,bottom:r,canvasWidth:s,canvasHeight:o,devicePixelRatio:c}=e,l=t*c,u=s-n*c,m=i*c,f=o-r*c,a=l/s*2-1,v=u/s*2-1,M=1-m/o*2,C=1-f/o*2;return{left:a,right:v,top:M,bottom:C,width:v-a,height:M-C}},_a=e=>{const{canvasWidth:t,canvasHeight:n,devicePixelRatio:i}=e,r=e.left*i,s=t-e.right*i,o=e.top*i,c=n-e.bottom*i,l=Dn(Math.floor(r),0,Math.max(0,t)),u=Dn(Math.floor(o),0,Math.max(0,n)),m=Dn(Math.ceil(s),0,Math.max(0,t)),f=Dn(Math.ceil(c),0,Math.max(0,n)),a=Math.max(0,m-l),v=Math.max(0,f-u);return{x:l,y:u,w:a,h:v}},Ga=e=>{const t=[];for(let i=0;i<e.length;i++){const{timestamp:r}=Er(e[i]);Number.isFinite(r)&&t.push(r)}if(t.length<2)return 1;t.sort((i,r)=>i-r);let n=Number.POSITIVE_INFINITY;for(let i=1;i<t.length;i++){const r=t[i]-t[i-1];r>0&&r<n&&(n=r)}return Number.isFinite(n)&&n>0?n:1},Wa=(e,t,n,i)=>{if(Number.isFinite(t)&&t>0){const c=e.scale(0),l=e.scale(0+t),u=Math.abs(l-c);if(Number.isFinite(u)&&u>0)return u}const r=Math.abs(n.width);if(!(r>0))return 0;const s=Math.max(1,Math.floor(i));return r/s},$a=()=>{const e=new ArrayBuffer(64);return new Float32Array(e).set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),e};function Oa(e,t){let n=!1;const i=(t==null?void 0:t.targetFormat)??Ra,r=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}}]}),s=Ve(e,80,{label:"candlestickRenderer/vsUniforms"});Ge(e,s,$a());const o=new ArrayBuffer(80),c=new Float32Array(o),l=e.createBindGroup({layout:r,entries:[{binding:0,resource:{buffer:s}}]}),u=lt(e,{label:"candlestickRenderer/pipeline",bindGroupLayouts:[r],vertex:{code:Br,label:"candlestick.wgsl",buffers:[{arrayStride:rn,stepMode:"instance",attributes:[{shaderLocation:0,format:"float32",offset:0},{shaderLocation:1,format:"float32",offset:4},{shaderLocation:2,format:"float32",offset:8},{shaderLocation:3,format:"float32",offset:12},{shaderLocation:4,format:"float32",offset:16},{shaderLocation:5,format:"float32",offset:20},{shaderLocation:6,format:"float32x4",offset:24}]}]},fragment:{code:Br,label:"candlestick.wgsl",formats:i,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let m=null,f=0,a=new ArrayBuffer(0),v=new Float32Array(a),M=0,C=0,p=null,F=!1,b=null,x=0,y=new ArrayBuffer(0),d=new Float32Array(y);const h=()=>{if(n)throw new Error("CandlestickRenderer is disposed.")},N=T=>{if(T<=v.length)return;const B=Math.max(8,Un(T));a=new ArrayBuffer(B*4),v=new Float32Array(a)},w=T=>{if(T<=d.length)return;const B=Math.max(8,Un(T));y=new ArrayBuffer(B*4),d=new Float32Array(y)};return{prepare:(T,B,U,G,D,_)=>{if(h(),B.length===0){f=0,x=0;return}const X=Ua(D);if(!X){f=0,x=0;return}const Z=La(D),V=X.plotWidthCss>0?Z.width/X.plotWidthCss:0;M=D.canvasWidth,C=D.canvasHeight,p=_a(D);const re=Ga(B),ce=Wa(U,re,Z,B.length);let Y=0;const ne=T.barWidth;if(typeof ne=="number")Y=Math.max(0,ne)*V;else if(typeof ne=="string"){const Re=Ea(ne);Y=Re==null?0:ce*Ba(Re)}const Se=T.barMinWidth*V,Ce=T.barMaxWidth*V;Y=Math.min(Math.max(Y,Se),Ce);const fe=T.itemStyle.borderWidth??Aa,oe=Math.max(0,fe)*V;c.set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1,oe,0,0,0]),Ge(e,s,o);const ve=mn(T.itemStyle.upColor),we=mn(T.itemStyle.downColor),ue=mn(T.itemStyle.upBorderColor),se=mn(T.itemStyle.downBorderColor),be=_?mn(_):[0,0,0,1];F=T.style==="hollow",N(B.length*zt);const K=v;let ee=0;F&&w(B.length*zt);const Ie=d;let he=0;for(let Re=0;Re<B.length;Re++){const{timestamp:Fe,open:Ae,close:We,low:qe,high:Le}=Er(B[Re]);if(!Number.isFinite(Fe)||!Number.isFinite(Ae)||!Number.isFinite(We)||!Number.isFinite(qe)||!Number.isFinite(Le))continue;const Ne=U.scale(Fe),$e=G.scale(Ae),Ue=G.scale(We),et=G.scale(qe),Oe=G.scale(Le);if(!Number.isFinite(Ne)||!Number.isFinite($e)||!Number.isFinite(Ue)||!Number.isFinite(et)||!Number.isFinite(Oe))continue;const at=We>Ae;if(F){const ke=at?ue:se;if(K[ee+0]=Ne,K[ee+1]=$e,K[ee+2]=Ue,K[ee+3]=et,K[ee+4]=Oe,K[ee+5]=Y,K[ee+6]=ke[0],K[ee+7]=ke[1],K[ee+8]=ke[2],K[ee+9]=ke[3],ee+=zt,at){const ze=T.itemStyle.borderWidth*V,pt=Math.max(0,Y-2*ze);Ie[he+0]=Ne,Ie[he+1]=$e,Ie[he+2]=Ue,Ie[he+3]=et,Ie[he+4]=Oe,Ie[he+5]=pt,Ie[he+6]=be[0],Ie[he+7]=be[1],Ie[he+8]=be[2],Ie[he+9]=be[3],he+=zt}}else{const ke=at?ve:we;K[ee+0]=Ne,K[ee+1]=$e,K[ee+2]=Ue,K[ee+3]=et,K[ee+4]=Oe,K[ee+5]=Y,K[ee+6]=ke[0],K[ee+7]=ke[1],K[ee+8]=ke[2],K[ee+9]=ke[3],ee+=zt}}f=ee/zt,x=he/zt;const te=Math.max(4,f*rn);if(!m||m.size<te){const Re=Math.max(Math.max(4,Un(te)),m?m.size:0);if(m)try{m.destroy()}catch{}m=e.createBuffer({label:"candlestickRenderer/instanceBuffer",size:Re,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}if(f>0&&e.queue.writeBuffer(m,0,a,0,f*rn),F&&x>0){const Re=Math.max(4,x*rn);if(!b||b.size<Re){const Fe=Math.max(Math.max(4,Un(Re)),b?b.size:0);if(b)try{b.destroy()}catch{}b=e.createBuffer({label:"candlestickRenderer/hollowInstanceBuffer",size:Fe,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST})}e.queue.writeBuffer(b,0,y,0,x*rn)}},render:T=>{h(),!(!m||f===0)&&(p&&M>0&&C>0&&T.setScissorRect(p.x,p.y,p.w,p.h),T.setPipeline(u),T.setBindGroup(0,l),T.setVertexBuffer(0,m),T.draw(18,f),F&&b&&x>0&&(T.setVertexBuffer(0,b),T.draw(6,x)),p&&M>0&&C>0&&T.setScissorRect(0,0,M,C))},dispose:()=>{if(!n){if(n=!0,m)try{m.destroy()}catch{}if(m=null,f=0,b)try{b.destroy()}catch{}b=null,x=0;try{s.destroy()}catch{}M=0,C=0,p=null}}}}var Dr=`// crosshair.wgsl
|
|
677
|
+
// Minimal crosshair line shader:
|
|
678
|
+
// - Vertex input: vec2<f32> position in clip-space coordinates
|
|
679
|
+
// - VS uniform: transform mat4 (identity)
|
|
680
|
+
// - FS uniform: solid RGBA color
|
|
681
|
+
|
|
682
|
+
struct VSUniforms {
|
|
683
|
+
transform: mat4x4<f32>,
|
|
684
|
+
};
|
|
685
|
+
|
|
686
|
+
@group(0) @binding(0) var<uniform> vsUniforms: VSUniforms;
|
|
687
|
+
|
|
688
|
+
struct FSUniforms {
|
|
689
|
+
color: vec4<f32>,
|
|
690
|
+
};
|
|
691
|
+
|
|
692
|
+
@group(0) @binding(1) var<uniform> fsUniforms: FSUniforms;
|
|
693
|
+
|
|
694
|
+
struct VSIn {
|
|
695
|
+
@location(0) position: vec2<f32>,
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
struct VSOut {
|
|
699
|
+
@builtin(position) clipPosition: vec4<f32>,
|
|
700
|
+
};
|
|
701
|
+
|
|
702
|
+
@vertex
|
|
703
|
+
fn vsMain(in: VSIn) -> VSOut {
|
|
704
|
+
var out: VSOut;
|
|
705
|
+
out.clipPosition = vsUniforms.transform * vec4<f32>(in.position, 0.0, 1.0);
|
|
706
|
+
return out;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
@fragment
|
|
710
|
+
fn fsMain() -> @location(0) vec4<f32> {
|
|
711
|
+
return fsUniforms.color;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
`;const ka=e=>e+3&-4,Va=1024,za=128,Xa=16384,Ha=e=>{if(e.byteOffset&3)throw new Error("createStreamBuffer.write: data.byteOffset must be 4-byte aligned.");return new Uint32Array(e.buffer,e.byteOffset,e.byteLength>>>2)};function Ya(e,t){if(!Number.isFinite(t)||t<=0)throw new Error(`createStreamBuffer(maxSize): maxSize (bytes) must be a positive number. Received: ${String(t)}`);const n=Math.max(4,Math.floor(t)),i=ka(n),r=e.limits.maxBufferSize;if(i>r)throw new Error(`createStreamBuffer(maxSize): requested size ${i} bytes exceeds device.limits.maxBufferSize (${r}).`);const s=i>>>2,o=b=>({buffer:e.createBuffer({label:b,size:i,usage:GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_DST}),mirror:new Uint32Array(s)}),c=[o("streamBuffer/a"),o("streamBuffer/b")];let l=!1,u=0,m=0;const f=()=>{if(l)throw new Error("createStreamBuffer: StreamBuffer is disposed.")},a=(b,x,y)=>{const d=c[b],h=d.mirror;if(y<0||y>x.length)throw new Error("createStreamBuffer.write: internal error (invalid usedWords).");if(y===0)return;const N=y<<2;e.queue.writeBuffer(d.buffer,0,x.buffer,x.byteOffset,N),h.set(x.subarray(0,y),0)},v=(b,x,y)=>{const d=c[b],h=d.mirror;if(y<0||y>x.length)throw new Error("createStreamBuffer.write: internal error (invalid usedWords).");const N=y<<2;if(N>0&&N<=Va){a(b,x,y);return}const w=[];let I=0,R=0,P=0;for(;P<y;){for(;P<y&&h[P]===x[P];)P++;if(P>=y)break;const T=P;for(P++;P<y&&h[P]!==x[P];)P++;const B=P;if(w.push([T,B]),I++,R+=B-T,I>za||R>Xa){a(b,x,y);return}}for(let T=0;T<w.length;T++){const[B,U]=w[T],G=B<<2,D=U-B<<2;e.queue.writeBuffer(d.buffer,G,x.buffer,x.byteOffset+G,D),h.set(x.subarray(B,U),B)}};return{write:b=>{if(f(),b.length&1)throw new Error("createStreamBuffer.write: data length must be even (vec2<f32> vertices).");const x=b.byteLength;if(x>i)throw new Error(`createStreamBuffer.write: data.byteLength (${x}) exceeds capacity (${i}). Increase maxSize.`);const y=b.length>>>1;if(x===0){m=y;return}const d=Ha(b),h=1-u;v(h,d,d.length),u=h,m=y},getBuffer:()=>(f(),c[u].buffer),getVertexCount:()=>(f(),m),dispose:()=>{if(!l){l=!0,m=0;for(const b of c)try{b.buffer.destroy()}catch{}}}}}const qa="bgra8unorm",Za=[1,1,1,.8],ja=8,Ka=6,Ja=4,Ur=8192,Qa=()=>{const e=new ArrayBuffer(64);return new Float32Array(e).set([1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1]),e},ec=e=>Number.isFinite(e.left)&&Number.isFinite(e.right)&&Number.isFinite(e.top)&&Number.isFinite(e.bottom)&&Number.isFinite(e.canvasWidth)&&Number.isFinite(e.canvasHeight),Ln=(e,t,n)=>Math.min(n,Math.max(t,e|0)),tc=(e,t)=>{if(!Number.isFinite(e)||e<0)throw new Error("CrosshairRenderer.prepare: lineWidth must be a finite non-negative number.");if(e===0)return[];const n=e*t,i=Math.max(1,Math.min(ja,Math.round(n))),r=(i-1)/2,s=[];for(let o=0;o<i;o++)s.push(o-r);return s},sn=(e,t)=>e/t*2-1,on=(e,t)=>1-e/t*2,_n=(e,t)=>{e.push(t[0],t[1],t[2],t[3])},Lr=(e,t)=>{if(!Number.isFinite(e)||!Number.isFinite(t))return[];const n=Math.min(e,t),i=Math.max(e,t);if(i<=n)return[];const r=Ka,o=r+Ja;if(!Number.isFinite(o))return[];const c=Math.ceil((i-n)/o);if(!Number.isFinite(c)||c<=0)return[];const l=[];let u=n;for(;u<i;){const m=u,f=Math.min(u+r,i);f>m&&l.push([m,f]),u+=o}return l},nc=(e,t,n,i)=>{if(!Number.isFinite(e)||!Number.isFinite(t))throw new Error("CrosshairRenderer.prepare: x and y must be finite numbers.");if(!ec(n))throw new Error("CrosshairRenderer.prepare: gridArea dimensions must be finite numbers.");if(n.canvasWidth<=0||n.canvasHeight<=0)throw new Error("CrosshairRenderer.prepare: canvas dimensions must be positive.");if(n.left<0||n.right<0||n.top<0||n.bottom<0)throw new Error("CrosshairRenderer.prepare: gridArea margins must be non-negative.");const{canvasWidth:r,canvasHeight:s}=n,o=Number.isFinite(n.devicePixelRatio)&&n.devicePixelRatio>0?n.devicePixelRatio:1,c=n.left*o,l=r-n.right*o,u=n.top*o,m=s-n.bottom*o,f=Ln(Math.floor(c),0,Math.max(0,r)),a=Ln(Math.floor(u),0,Math.max(0,s)),v=Ln(Math.ceil(l),0,Math.max(0,r)),M=Ln(Math.ceil(m),0,Math.max(0,s)),C=Math.max(0,v-f),p=Math.max(0,M-a),F=e*o,b=t*o,x=tc(i.lineWidth,o);if(x.length===0||!i.showX&&!i.showY)return{vertices:new Float32Array(0),scissor:{x:f,y:a,w:C,h:p}};const y=[],d=i.showX?Lr(u,m):[],h=i.showY?Lr(c,l):[],w=((i.showX?d.length:0)+(i.showY?h.length:0))*x.length*2,I=w>0&&w<=Ur,R=B=>{const U=sn(B,r),G=on(u,s),D=on(m,s);_n(y,[U,G,U,D])},P=B=>{const U=on(B,s),G=sn(c,r),D=sn(l,r);_n(y,[G,U,D,U])};if(i.showX)for(let B=0;B<x.length;B++){const U=F+x[B];if(!I){R(U);continue}const G=sn(U,r);for(let D=0;D<d.length;D++){const[_,X]=d[D],Z=on(_,s),V=on(X,s);_n(y,[G,Z,G,V])}}if(i.showY)for(let B=0;B<x.length;B++){const U=b+x[B];if(!I){P(U);continue}const G=on(U,s);for(let D=0;D<h.length;D++){const[_,X]=h[D],Z=sn(_,r),V=sn(X,r);_n(y,[Z,G,V,G])}}return{vertices:new Float32Array(y),scissor:{x:f,y:a,w:C,h:p}}};function ic(e,t){let n=!1,i=!0;const r=(t==null?void 0:t.targetFormat)??qa,s=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.VERTEX,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),o=Ve(e,64,{label:"crosshairRenderer/vsUniforms"}),c=Ve(e,16,{label:"crosshairRenderer/fsUniforms"}),l=e.createBindGroup({layout:s,entries:[{binding:0,resource:{buffer:o}},{binding:1,resource:{buffer:c}}]}),u=lt(e,{label:"crosshairRenderer/pipeline",bindGroupLayouts:[s],vertex:{code:Dr,label:"crosshair.wgsl",buffers:[{arrayStride:8,stepMode:"vertex",attributes:[{shaderLocation:0,format:"float32x2",offset:0}]}]},fragment:{code:Dr,label:"crosshair.wgsl",formats:r,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"line-list",cullMode:"none"},multisample:{count:1}}),m=Ya(e,Ur*8);let f=0,a=0,v=0,M={x:0,y:0,w:0,h:0};const C=()=>{if(n)throw new Error("CrosshairRenderer is disposed.")};return{prepare:(y,d,h,N)=>{if(C(),typeof N.showX!="boolean"||typeof N.showY!="boolean")throw new Error("CrosshairRenderer.prepare: showX/showY must be boolean.");if(typeof N.color!="string")throw new Error("CrosshairRenderer.prepare: color must be a string.");if(!Number.isFinite(N.lineWidth)||N.lineWidth<0)throw new Error("CrosshairRenderer.prepare: lineWidth must be a finite non-negative number.");const{vertices:w,scissor:I}=nc(y,d,h,N);w.byteLength===0?f=0:(m.write(w),f=m.getVertexCount()),Ge(e,o,Qa());const R=Ke(N.color)??Za,P=new ArrayBuffer(4*4);new Float32Array(P).set([R[0],R[1],R[2],R[3]]),Ge(e,c,P),a=h.canvasWidth,v=h.canvasHeight,M=I},render:y=>{C(),i&&f!==0&&(a<=0||v<=0||(y.setScissorRect(M.x,M.y,M.w,M.h),y.setPipeline(u),y.setBindGroup(0,l),y.setVertexBuffer(0,m.getBuffer()),y.draw(f),y.setScissorRect(0,0,a,v)))},setVisible:y=>{C(),i=!!y},dispose:()=>{if(!n){n=!0;try{o.destroy()}catch{}try{c.destroy()}catch{}m.dispose(),f=0,a=0,v=0,M={x:0,y:0,w:0,h:0}}}}}var _r=`// highlight.wgsl
|
|
715
|
+
// Draws an anti-aliased ring highlight around a point.
|
|
716
|
+
//
|
|
717
|
+
// Contract:
|
|
718
|
+
// - \`@builtin(position)\` in the fragment stage is framebuffer-space pixels.
|
|
719
|
+
// - The renderer supplies \`center\` and ring sizes in *device pixels*.
|
|
720
|
+
|
|
721
|
+
struct Uniforms {
|
|
722
|
+
center: vec2<f32>,
|
|
723
|
+
radius: f32,
|
|
724
|
+
thickness: f32,
|
|
725
|
+
color: vec4<f32>,
|
|
726
|
+
outlineColor: vec4<f32>,
|
|
727
|
+
};
|
|
728
|
+
|
|
729
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
730
|
+
|
|
731
|
+
struct VSOut {
|
|
732
|
+
@builtin(position) position: vec4<f32>,
|
|
733
|
+
};
|
|
734
|
+
|
|
735
|
+
@vertex
|
|
736
|
+
fn vsMain(@builtin(vertex_index) vertexIndex: u32) -> VSOut {
|
|
737
|
+
// Fullscreen triangle.
|
|
738
|
+
// Covers clip-space [-1,1] with 3 verts: (-1,-1), (3,-1), (-1,3)
|
|
739
|
+
let positions = array<vec2<f32>, 3>(
|
|
740
|
+
vec2<f32>(-1.0, -1.0),
|
|
741
|
+
vec2<f32>(3.0, -1.0),
|
|
742
|
+
vec2<f32>(-1.0, 3.0)
|
|
743
|
+
);
|
|
744
|
+
|
|
745
|
+
var out: VSOut;
|
|
746
|
+
out.position = vec4<f32>(positions[vertexIndex], 0.0, 1.0);
|
|
747
|
+
return out;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
fn ringCoverage(distancePx: f32, radiusPx: f32, thicknessPx: f32) -> f32 {
|
|
751
|
+
let aa = 1.0; // ~1px antialias band (device pixels)
|
|
752
|
+
let halfT = max(0.5, thicknessPx * 0.5);
|
|
753
|
+
let a0 = smoothstep(radiusPx - halfT - aa, radiusPx - halfT + aa, distancePx);
|
|
754
|
+
let a1 = smoothstep(radiusPx + halfT - aa, radiusPx + halfT + aa, distancePx);
|
|
755
|
+
return clamp(a0 - a1, 0.0, 1.0);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
@fragment
|
|
759
|
+
fn fsMain(@builtin(position) fragPos: vec4<f32>) -> @location(0) vec4<f32> {
|
|
760
|
+
let d = distance(fragPos.xy, u.center);
|
|
761
|
+
|
|
762
|
+
let ring = ringCoverage(d, u.radius, u.thickness);
|
|
763
|
+
let outline = ringCoverage(d, u.radius, u.thickness + 2.0);
|
|
764
|
+
|
|
765
|
+
let cover = max(ring, outline);
|
|
766
|
+
if (cover <= 0.0) {
|
|
767
|
+
discard;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
// Blend between outline and ring color based on relative coverage,
|
|
771
|
+
// then apply total coverage as alpha.
|
|
772
|
+
let t = clamp(select(0.0, ring / cover, cover > 0.0), 0.0, 1.0);
|
|
773
|
+
let rgb = mix(u.outlineColor.rgb, u.color.rgb, t);
|
|
774
|
+
let a = mix(u.outlineColor.a, u.color.a, t) * cover;
|
|
775
|
+
return vec4<f32>(rgb, a);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
`;const rc="bgra8unorm",sc=[1,1,1,1],Gn=e=>Math.min(1,Math.max(0,e)),Wn=(e,t,n)=>Math.min(n,Math.max(t,e|0)),oc=e=>Number.isFinite(e.x)&&Number.isFinite(e.y)&&Number.isFinite(e.w)&&Number.isFinite(e.h),ac=(e,t)=>{const n=Number.isFinite(t)?t:1;return[Gn(e[0]*n),Gn(e[1]*n),Gn(e[2]*n),Gn(e[3])]},cc=e=>.2126*e[0]+.7152*e[1]+.0722*e[2];function lc(e,t){let n=!1,i=!0;const r=(t==null?void 0:t.targetFormat)??rc,s=e.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.FRAGMENT,buffer:{type:"uniform"}}]}),o=Ve(e,48,{label:"highlightRenderer/uniforms"}),c=e.createBindGroup({layout:s,entries:[{binding:0,resource:{buffer:o}}]}),l=lt(e,{label:"highlightRenderer/pipeline",bindGroupLayouts:[s],vertex:{code:_r,label:"highlight.wgsl"},fragment:{code:_r,label:"highlight.wgsl",formats:r,blend:{color:{operation:"add",srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{operation:"add",srcFactor:"one",dstFactor:"one-minus-src-alpha"}}},primitive:{topology:"triangle-list",cullMode:"none"},multisample:{count:1}});let u=0,m=0,f={x:0,y:0,w:0,h:0},a=!1;const v=()=>{if(n)throw new Error("HighlightRenderer is disposed.")};return{prepare:(b,x,y)=>{if(v(),!Number.isFinite(b.centerDeviceX)||!Number.isFinite(b.centerDeviceY))throw new Error("HighlightRenderer.prepare: point center must be finite.");if(!Number.isFinite(b.canvasWidth)||!Number.isFinite(b.canvasHeight)||b.canvasWidth<=0||b.canvasHeight<=0)throw new Error("HighlightRenderer.prepare: canvasWidth/canvasHeight must be positive finite numbers.");if(!oc(b.scissor))throw new Error("HighlightRenderer.prepare: scissor must be finite.");if(!Number.isFinite(y)||y<0)throw new Error("HighlightRenderer.prepare: size must be a finite non-negative number.");const d=b.devicePixelRatio,h=Number.isFinite(d)&&d>0?d:1,N=y*h,w=Math.max(1,N*1.5),I=Math.max(1,Math.round(Math.max(2,w*.25))),R=Ke(x)??sc,P=ac(R,1.25),B=cc(R)>.7?[0,0,0,.9]:[1,1,1,.9],U=new ArrayBuffer(12*4);new Float32Array(U).set([b.centerDeviceX,b.centerDeviceY,w,I,P[0],P[1],P[2],1,B[0],B[1],B[2],B[3]]),Ge(e,o,U),u=b.canvasWidth,m=b.canvasHeight;const G=Wn(Math.floor(b.scissor.x),0,Math.max(0,b.canvasWidth)),D=Wn(Math.floor(b.scissor.y),0,Math.max(0,b.canvasHeight)),_=Wn(Math.ceil(b.scissor.x+b.scissor.w),0,Math.max(0,b.canvasWidth)),X=Wn(Math.ceil(b.scissor.y+b.scissor.h),0,Math.max(0,b.canvasHeight));f={x:G,y:D,w:Math.max(0,_-G),h:Math.max(0,X-D)},a=!0},render:b=>{v(),i&&a&&(u<=0||m<=0||f.w===0||f.h===0||(b.setScissorRect(f.x,f.y,f.w,f.h),b.setPipeline(l),b.setBindGroup(0,c),b.draw(3),b.setScissorRect(0,0,u,m)))},setVisible:b=>{v(),i=!!b},dispose:()=>{if(!n){n=!0;try{o.destroy()}catch{}u=0,m=0,f={x:0,y:0,w:0,h:0},a=!1}}}}const uc=6,fc=500;function mc(e,t){let n=!1,i=t;const r={mousemove:new Set,click:new Set,mouseleave:new Set};let s=null,o=null;const c=y=>{const d=e.getBoundingClientRect();if(d.width===0||d.height===0)return null;const h=y.clientX-d.left,N=y.clientY-d.top,w=i.left,I=i.top,R=d.width-i.left-i.right,P=d.height-i.top-i.bottom,T=h-w,B=N-I,U=T>=0&&T<=R&&B>=0&&B<=P;return{x:h,y:N,gridX:T,gridY:B,plotWidthCss:R,plotHeightCss:P,isInGrid:U,originalEvent:y}},l=(y,d)=>{const h=c(d);if(h)for(const N of r[y])N(h)},u=y=>{s&&y.isPrimary&&y.pointerId===s.pointerId&&(s=null)},m=y=>{n||l("mousemove",y)},f=y=>{n||(u(y),l("mouseleave",y))},a=y=>{n||(u(y),l("mouseleave",y))},v=y=>{if(!n){if(o===y.pointerId){o=null;return}u(y),l("mouseleave",y)}},M=y=>{if(n||!y.isPrimary||y.pointerType==="mouse"&&y.button!==0)return;const d=e.getBoundingClientRect();if(!(d.width===0||d.height===0)){s={pointerId:y.pointerId,startClientX:y.clientX,startClientY:y.clientY,startTimeMs:y.timeStamp};try{e.setPointerCapture(y.pointerId)}catch{}}},C=y=>{if(n||!y.isPrimary||!s||y.pointerId!==s.pointerId)return;const d=y.timeStamp-s.startTimeMs,h=y.clientX-s.startClientX,N=y.clientY-s.startClientY,w=h*h+N*N;s=null;try{e.hasPointerCapture(y.pointerId)&&(o=y.pointerId,e.releasePointerCapture(y.pointerId))}catch{}const I=uc;d<=fc&&w<=I*I&&l("click",y)};return e.addEventListener("pointermove",m,{passive:!0}),e.addEventListener("pointerleave",f,{passive:!0}),e.addEventListener("pointercancel",a,{passive:!0}),e.addEventListener("lostpointercapture",v,{passive:!0}),e.addEventListener("pointerdown",M,{passive:!0}),e.addEventListener("pointerup",C,{passive:!0}),{canvas:e,on:(y,d)=>{n||r[y].add(d)},off:(y,d)=>{r[y].delete(d)},updateGridArea:y=>{i=y},dispose:()=>{n||(n=!0,s=null,o=null,e.removeEventListener("pointermove",m),e.removeEventListener("pointerleave",f),e.removeEventListener("pointercancel",a),e.removeEventListener("lostpointercapture",v),e.removeEventListener("pointerdown",M),e.removeEventListener("pointerup",C),r.mousemove.clear(),r.click.clear(),r.mouseleave.clear())}}}const Gr=(e,t,n)=>Math.min(n,Math.max(t,e)),dc=(e,t)=>{const n=e.deltaY;if(!Number.isFinite(n)||n===0)return 0;switch(e.deltaMode){case WheelEvent.DOM_DELTA_PIXEL:return n;case WheelEvent.DOM_DELTA_LINE:return n*16;case WheelEvent.DOM_DELTA_PAGE:return n*(Number.isFinite(t)&&t>0?t:800);default:return n}},hc=(e,t)=>{const n=e.deltaX;if(!Number.isFinite(n)||n===0)return 0;switch(e.deltaMode){case WheelEvent.DOM_DELTA_PIXEL:return n;case WheelEvent.DOM_DELTA_LINE:return n*16;case WheelEvent.DOM_DELTA_PAGE:return n*(Number.isFinite(t)&&t>0?t:800);default:return n}},pc=e=>{const t=Math.abs(e);if(!Number.isFinite(t)||t===0)return 1;const n=Math.min(t,200);return Math.exp(n*.002)},bc=e=>e.pointerType==="mouse"&&(e.buttons&4)!==0,gc=e=>e.pointerType==="mouse"&&e.shiftKey&&(e.buttons&1)!==0;function yc(e,t){let n=!1,i=!1,r=null,s=!1,o=0;const c=()=>{s=!1,o=0},l=M=>{if(r=M,!i)return;const C=M.originalEvent;if(!(M.isInGrid&&(gc(C)||bc(C)))){c();return}const F=M.plotWidthCss;if(!(F>0)||!Number.isFinite(F)){c();return}if(!s){s=!0,o=M.gridX;return}const b=M.gridX-o;if(o=M.gridX,!Number.isFinite(b)||b===0)return;const{start:x,end:y}=t.getRange(),d=y-x;if(!Number.isFinite(d)||d===0)return;const h=-(b/F)*d;!Number.isFinite(h)||h===0||t.pan(h)},u=M=>{r=null,c()},m=M=>{if(!i||n)return;const C=r;if(!C||!C.isInGrid)return;const p=C.plotWidthCss,F=C.plotHeightCss;if(!(p>0)||!(F>0))return;const b=dc(M,F),x=hc(M,p);if(Math.abs(x)>Math.abs(b)&&x!==0){const{start:R,end:P}=t.getRange(),T=P-R;if(!Number.isFinite(T)||T===0)return;const B=x/p*T;if(!Number.isFinite(B)||B===0)return;M.preventDefault(),t.pan(B);return}if(b===0)return;const y=pc(b);if(!(y>1))return;const{start:d,end:h}=t.getRange(),N=h-d;if(!Number.isFinite(N)||N===0)return;const w=Gr(C.gridX/p,0,1),I=Gr(d+w*N,0,100);M.preventDefault(),b<0?t.zoomIn(I,y):t.zoomOut(I,y)},f=()=>{n||i||(i=!0,e.on("mousemove",l),e.on("mouseleave",u),e.canvas.addEventListener("wheel",m,{passive:!1}))},a=()=>{n||!i||(i=!1,e.off("mousemove",l),e.off("mouseleave",u),e.canvas.removeEventListener("wheel",m),r=null,c())};return{enable:f,disable:a,dispose:()=>{n||(a(),n=!0)}}}const xc=.5,vc=100,ut=(e,t,n)=>Math.min(n,Math.max(t,e)),Fi=e=>ut(e,0,1),Wr=e=>Object.is(e,-0)?0:e,wc=e=>({start:e.start,end:e.end});function Fc(e,t,n){let i=0,r=100,s=null;const o=new Set;let c=(()=>{const h=Number.isFinite(n==null?void 0:n.minSpan)?n.minSpan:xc;return ut(Number.isFinite(h)?h:0,0,100)})(),l=(()=>{const h=Number.isFinite(n==null?void 0:n.maxSpan)?n.maxSpan:vc;return ut(Number.isFinite(h)?h:100,0,100)})(),u=Math.min(c,l),m=Math.max(c,l);const f=()=>{const h={start:i,end:r};if(s!==null&&s.start===h.start&&s.end===h.end)return;s=wc(h);const N=Array.from(o);for(const w of N)w({start:i,end:r})},a=(h,N,w)=>{if(w){if(typeof w=="string")switch(w){case"start":return{center:h,ratio:0};case"end":return{center:N,ratio:1};case"center":return{center:(h+N)*.5,ratio:.5}}if(w&&Number.isFinite(w.center)&&Number.isFinite(w.ratio))return{center:w.center,ratio:w.ratio}}},v=(h,N,w)=>{if(!Number.isFinite(h)||!Number.isFinite(N))return;let I=h,R=N;if(I>R){const B=I;I=R,R=B}let P=R-I;if(!Number.isFinite(P)||P<0)return;const T=ut(P,u,m);if(T!==P){const B=w!=null&&w.anchor&&Number.isFinite(w.anchor.center)?ut(w.anchor.center,0,100):(I+R)*.5,U=w!=null&&w.anchor&&Number.isFinite(w.anchor.ratio)?Fi(w.anchor.ratio):.5;I=B-U*T,R=I+T,P=T}if(P>100&&(I=0,R=100,P=100),I<0){const B=-I;I+=B,R+=B}if(R>100){const B=R-100;I-=B,R-=B}I=ut(I,0,100),R=ut(R,0,100),I=Wr(I),R=Wr(R),!(I===i&&R===r)&&(i=I,r=R,(w==null?void 0:w.emit)!==!1&&f())};return v(e,t,{emit:!1}),{getRange:()=>({start:i,end:r}),setRange:(h,N)=>{v(h,N)},setRangeAnchored:(h,N,w)=>{v(h,N,{anchor:a(h,N,w)})},setSpanConstraints:(h,N)=>{const w=typeof h=="number"&&Number.isFinite(h)?ut(h,0,100):c,I=typeof N=="number"&&Number.isFinite(N)?ut(N,0,100):l;if(w===c&&I===l)return;c=w,l=I,u=Math.min(c,l),m=Math.max(c,l);const R=i,P=r,T=1e-6,B=P>=100-T?"end":R<=0+T?"start":"center";v(R,P,{anchor:a(R,P,B)})},zoomIn:(h,N)=>{if(!Number.isFinite(h)||!Number.isFinite(N)||N<=1)return;const w=ut(h,0,100),I=r-i,R=I===0?.5:Fi((w-i)/I),P=I/N,T=w-R*P,B=T+P;v(T,B,{anchor:{center:w,ratio:R}})},zoomOut:(h,N)=>{if(!Number.isFinite(h)||!Number.isFinite(N)||N<=1)return;const w=ut(h,0,100),I=r-i,R=I===0?.5:Fi((w-i)/I),P=I*N,T=w-R*P,B=T+P;v(T,B,{anchor:{center:w,ratio:R}})},pan:h=>{Number.isFinite(h)&&v(i+h,r+h)},onChange:h=>(o.add(h),()=>{o.delete(h)})}}const $r=20,Nc=.01,Mc=.2,dn=4,Or=new WeakMap;function Sc(e,t,n){return e>=n.left&&e<=n.right&&t>=n.top&&t<=n.bottom}const Ni=e=>Math.min(1,Math.max(0,e)),Cc=e=>{const t=e.trim().match(/^(\d+(?:\.\d+)?)%$/);if(!t)return null;const n=Number(t[1])/100;return Number.isFinite(n)?n:null},Ic=e=>{if(typeof e!="string")return"";const t=e.trim();return t.length>0?t:""},Mi=e=>Array.isArray(e),hn=e=>Mi(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},kr=e=>{if(Mi(e)){const n=e[2];return typeof n=="number"&&Number.isFinite(n)?n:null}const t=e.size;return typeof t=="number"&&Number.isFinite(t)?t:null},Tc=e=>Mi(e)?e:[e.x,e.y,e.size],Pc=(e,t)=>{try{const n=e(t);return typeof n=="number"&&Number.isFinite(n)?n:null}catch{return null}},pn=(e,t)=>{const n=kr(t);if(n!=null)return Math.max(0,n);const i=e.symbolSize;if(typeof i=="number")return Number.isFinite(i)?Math.max(0,i):dn;if(typeof i=="function"){const r=Pc(i,Tc(t));return r==null?dn:Math.max(0,r)}return dn},Rc=e=>{const t=Or.get(e);if(t!==void 0)return t;const n=e.data,i=e.symbolSize;let r=0;if(typeof i!="function"){const s=typeof i=="number"&&Number.isFinite(i)?Math.max(0,i):dn;let o=0,c=!1;for(let l=0;l<n.length;l++){const u=kr(n[l]);if(u==null)c=!0;else{const m=Math.max(0,u);m>o&&(o=m)}}r=c?Math.max(o,s):o}else for(let s=0;s<n.length;s++){const o=pn(e,n[s]);o>r&&(r=o)}return r=Number.isFinite(r)?Math.max(0,r):dn,Or.set(e,r),r};function Ac(e){const t=new Map,n=new Array(e.length),i=new Array(e.length);let r=0;for(let s=0;s<e.length;s++){const o=Ic(e[s].stack);if(i[s]=o,o!==""){const c=t.get(o);if(c!==void 0)n[s]=c;else{const l=r++;t.set(o,l),n[s]=l}}else n[s]=r++}return{clusterIndexBySeries:n,clusterCount:Math.max(1,r),stackIdBySeries:i}}function Bc(e){const t=[];for(let i=0;i<e.length;i++){const r=e[i].data;for(let s=0;s<r.length;s++){const{x:o}=hn(r[s]);Number.isFinite(o)&&t.push(o)}}if(t.length<2)return 1;t.sort((i,r)=>i-r);let n=Number.POSITIVE_INFINITY;for(let i=1;i<t.length;i++){const r=t[i]-t[i-1];r>0&&r<n&&(n=r)}return Number.isFinite(n)&&n>0?n:1}function Ec(e,t,n){if(Number.isFinite(n)&&n>0){const o=t.scale(0),c=t.scale(0+n),l=Math.abs(c-o);if(Number.isFinite(l)&&l>0)return l}const i=[];for(let s=0;s<e.length;s++){const o=e[s].data;for(let c=0;c<o.length;c++){const{x:l}=hn(o[c]);if(!Number.isFinite(l))continue;const u=t.scale(l);Number.isFinite(u)&&i.push(u)}}if(i.length<2)return 0;i.sort((s,o)=>s-o);let r=Number.POSITIVE_INFINITY;for(let s=1;s<i.length;s++){const o=i[s]-i[s-1];o>0&&o<r&&(r=o)}return Number.isFinite(r)&&r>0?r:0}const Dc=e=>{let t,n,i;for(let r=0;r<e.length;r++){const s=e[r];t===void 0&&s.barWidth!==void 0&&(t=s.barWidth),n===void 0&&s.barGap!==void 0&&(n=s.barGap),i===void 0&&s.barCategoryGap!==void 0&&(i=s.barCategoryGap)}return{barWidth:t,barGap:n,barCategoryGap:i}};function Vr(e,t){const n=Ac(e),i=n.clusterCount,r=Bc(e),s=Ec(e,t,r),o=Dc(e),c=Ni(o.barGap??Nc),l=Ni(o.barCategoryGap??Mc),u=Math.max(0,s*(1-l)),m=i+Math.max(0,i-1)*c,f=m>0?u/m:0;let a=0;const v=o.barWidth;if(typeof v=="number")a=Math.max(0,v),a=Math.min(a,f);else if(typeof v=="string"){const p=Cc(v);a=p==null?0:f*Ni(p)}a>0||(a=f);const M=a*c,C=i*a+Math.max(0,i-1)*M;return{categoryStep:r,categoryWidthPx:s,barWidthPx:a,gapPx:M,clusterWidthPx:C,clusterSlots:n}}const Si=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(let i=0;i<e.length;i++){const r=e[i].data;for(let s=0;s<r.length;s++){const{y:o}=hn(r[s]);Number.isFinite(o)&&(o<t&&(t=o),o>n&&(n=o))}}return!Number.isFinite(t)||!Number.isFinite(n)||t<=0&&0<=n?0:Math.abs(t)<Math.abs(n)?t:n};function Uc(e,t){let n=0;for(let i=0;i<e.length;i++){const r=e[i].data;for(let s=0;s<r.length;s++){const{y:o}=hn(r[s]);if(!Number.isFinite(o))continue;const c=t.scale(o);Number.isFinite(c)&&c>n&&(n=c)}}return Math.max(0,n)}function Lc(e,t,n){const i=t.invert(n),r=t.invert(0),s=Math.min(i,r),o=Math.max(i,r);let c;!Number.isFinite(s)||!Number.isFinite(o)?c=Si(e):s<=0&&0<=o?c=0:s>0?c=s:o<0?c=o:c=Si(e);let l=t.scale(c);return Number.isFinite(l)||(c=Si(e),l=t.scale(c)),Number.isFinite(l)||(c=0,l=t.scale(0)),{baselineDomain:c,baselinePx:l}}function _c(e,t,n,i){return Number.isFinite(t)&&t>0&&Number.isFinite(e)?Math.round(e/t):Number.isFinite(i)&&i>0&&Number.isFinite(n)?Math.round(n/i):Math.round(n*1e6)}const Gc=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<t?n=r+1:i=r}return n},Wc=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].x<t?n=r+1:i=r}return n};function Ci(e,t,n,i,r,s=$r){var C;if(!Number.isFinite(t)||!Number.isFinite(n))return null;const o=Number.isFinite(s)?Math.max(0,s):$r,c=o*o,l=i.invert(t);if(!Number.isFinite(l))return null;let u=-1,m=-1,f=null,a=Number.POSITIVE_INFINITY;const v=[],M=[];for(let p=0;p<e.length;p++){const F=e[p];(F==null?void 0:F.type)==="bar"&&(v.push(F),M.push(p))}if(v.length>0){const p=Vr(v,i);if(p.barWidthPx>0&&p.clusterWidthPx>=0){const F=Uc(v,r),{baselineDomain:b,baselinePx:x}=Lc(v,r,F),{clusterSlots:y,barWidthPx:d,gapPx:h,clusterWidthPx:N,categoryWidthPx:w,categoryStep:I}=p,R=new Map;let P=null;for(let T=0;T<v.length;T++){const B=v[T],U=M[T]??-1;if(U<0)continue;const G=B.data,D=y.clusterIndexBySeries[T]??0,_=y.stackIdBySeries[T]??"";for(let X=0;X<G.length;X++){const{x:Z,y:V}=hn(G[X]);if(!Number.isFinite(Z)||!Number.isFinite(V))continue;const re=i.scale(Z);if(!Number.isFinite(re))continue;const ce=re-N/2+D*(d+h),Y=ce+d;let ne=b,Se=V;if(_!==""){let we=R.get(_);we||(we=new Map,R.set(_,we));const ue=_c(re,w,Z,I);let se=we.get(ue);se||(se={posSum:b,negSum:b},we.set(ue,se)),V>=0?(ne=se.posSum,Se=ne+V,se.posSum=Se):(ne=se.negSum,Se=ne+V,se.negSum=Se)}else ne=b,Se=V;const Ce=_!==""?r.scale(ne):x,fe=r.scale(Se);if(!Number.isFinite(Ce)||!Number.isFinite(fe))continue;const oe={left:ce,right:Y,top:Math.min(Ce,fe),bottom:Math.max(Ce,fe)};if(!Sc(t,n,oe))continue;(P===null||oe.top<P.top||oe.top===P.top&&U>P.seriesIndex)&&(P={seriesIndex:U,dataIndex:X,top:oe.top})}}if(P){const T=(C=e[P.seriesIndex])==null?void 0:C.data[P.dataIndex];if(T)return{seriesIndex:P.seriesIndex,dataIndex:P.dataIndex,point:T,distance:0}}}}for(let p=0;p<e.length;p++){const F=e[p];if(F.type==="pie"||F.type==="candlestick")continue;const b=F.data,x=b.length;if(x===0)continue;const y=F.type==="scatter",d=y?F:null,h=d?Rc(d):0,N=y?(o+h)*(o+h):c,w=b[0];if(Array.isArray(w)){const R=b,P=Gc(R,l);let T=P-1,B=P;for(;T>=0||B<x;){const U=Math.min(a,N);let G=Number.POSITIVE_INFINITY;if(T>=0){const _=R[T][0];if(Number.isFinite(_)){const X=i.scale(_);if(Number.isFinite(X)){const Z=X-t;G=Z*Z}}}let D=Number.POSITIVE_INFINITY;if(B<x){const _=R[B][0];if(Number.isFinite(_)){const X=i.scale(_);if(Number.isFinite(X)){const Z=X-t;D=Z*Z}}}if(G>U&&D>U)break;if(G<=D&&G<=U&&T>=0){const _=R[T][1];if(Number.isFinite(_)){const X=r.scale(_);if(Number.isFinite(X)){const Z=X-n,V=G+Z*Z,re=b[T],ce=d?(()=>{const Y=pn(d,re),ne=o+Y;return ne*ne})():c;V<=ce&&(V<a||V===a&&(f===null||p<u||p===u&&T<m))&&(a=V,u=p,m=T,f=re)}}T--}else G<=D&&T--;if(D<=G&&D<=U&&B<x){const _=R[B][1];if(Number.isFinite(_)){const X=r.scale(_);if(Number.isFinite(X)){const Z=X-n,V=D+Z*Z,re=b[B],ce=d?(()=>{const Y=pn(d,re),ne=o+Y;return ne*ne})():c;V<=ce&&(V<a||V===a&&(f===null||p<u||p===u&&B<m))&&(a=V,u=p,m=B,f=re)}}B++}else D<G&&B++}}else{const R=b,P=Wc(R,l);let T=P-1,B=P;for(;T>=0||B<x;){const U=Math.min(a,N);let G=Number.POSITIVE_INFINITY;if(T>=0){const _=R[T].x;if(Number.isFinite(_)){const X=i.scale(_);if(Number.isFinite(X)){const Z=X-t;G=Z*Z}}}let D=Number.POSITIVE_INFINITY;if(B<x){const _=R[B].x;if(Number.isFinite(_)){const X=i.scale(_);if(Number.isFinite(X)){const Z=X-t;D=Z*Z}}}if(G>U&&D>U)break;if(G<=D&&G<=U&&T>=0){const _=R[T].y;if(Number.isFinite(_)){const X=r.scale(_);if(Number.isFinite(X)){const Z=X-n,V=G+Z*Z,re=b[T],ce=d?(()=>{const Y=pn(d,re),ne=o+Y;return ne*ne})():c;V<=ce&&(V<a||V===a&&(f===null||p<u||p===u&&T<m))&&(a=V,u=p,m=T,f=re)}}T--}else G<=D&&T--;if(D<=G&&D<=U&&B<x){const _=R[B].y;if(Number.isFinite(_)){const X=r.scale(_);if(Number.isFinite(X)){const Z=X-n,V=D+Z*Z,re=b[B],ce=d?(()=>{const Y=pn(d,re),ne=o+Y;return ne*ne})():c;V<=ce&&(V<a||V===a&&(f===null||p<u||p===u&&B<m))&&(a=V,u=p,m=B,f=re)}}B++}else D<G&&B++}}}return f===null||!Number.isFinite(a)?null:{seriesIndex:u,dataIndex:m,point:f,distance:Math.sqrt(a)}}const Ii=new WeakMap,zr=(e,t)=>{if(Ii.has(e))return Ii.get(e);let n=!1;if(t){const i=e;for(let r=0;r<i.length;r++){const s=i[r][0];if(Number.isNaN(s)){n=!0;break}}}else{const i=e;for(let r=0;r<i.length;r++){const s=i[r].x;if(Number.isNaN(s)){n=!0;break}}}return Ii.set(e,n),n},$c=(e,t)=>{const n=[];for(let l=0;l<e.length;l++){const u=e[l];(u==null?void 0:u.type)==="bar"&&n.push({globalSeriesIndex:l,s:u})}if(n.length===0)return null;const i=Vr(n.map(l=>l.s),t),r=i.barWidthPx,s=i.gapPx,o=i.clusterWidthPx;if(!Number.isFinite(r)||!(r>0))return null;const c=new Map;for(let l=0;l<n.length;l++){const u=n[l].globalSeriesIndex,m=i.clusterSlots.clusterIndexBySeries[l]??0;c.set(u,m)}return{barWidth:r,gap:s,clusterWidth:o,clusterIndexByGlobalSeriesIndex:c}},Xr=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<t?n=r+1:i=r}return n},Hr=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].x<t?n=r+1:i=r}return n};function Yr(e,t,n,i){if(!Number.isFinite(t))return[];const r=Number.POSITIVE_INFINITY,s=r*r,o=n.invert(t);if(!Number.isFinite(o))return[];const c=[],l=$c(e,n);for(let u=0;u<e.length;u++){const m=e[u];if(m.type==="pie"||m.type==="candlestick")continue;const f=m.data,a=f.length;if(a===0)continue;const v=f[0],M=Array.isArray(v);if(m.type==="bar"&&l){const x=l.clusterIndexByGlobalSeriesIndex.get(u);if(x!==void 0){const{barWidth:y,gap:d,clusterWidth:h}=l,N=-h/2+x*(y+d),w=0;if(Number.isFinite(y)&&y>0&&Number.isFinite(N)){let I=-1;const R=P=>{if(!Number.isFinite(P))return!1;const T=P+N,B=T+y;return t>=T-w&&t<B+w};if(zr(f,M))if(M){const P=f;for(let T=0;T<a;T++){const B=P[T][0];if(!Number.isFinite(B))continue;const U=n.scale(B);R(U)&&(I=I<0?T:Math.min(I,T))}}else{const P=f;for(let T=0;T<a;T++){const B=P[T].x;if(!Number.isFinite(B))continue;const U=n.scale(B);R(U)&&(I=I<0?T:Math.min(I,T))}}else{const P=n.invert(t-N);if(Number.isFinite(P)){const T=M?Xr(f,P):Hr(f,P),B=U=>{if(U<0||U>=a)return null;const G=M?f[U][0]:f[U].x;if(!Number.isFinite(G))return null;const D=n.scale(G);return Number.isFinite(D)?D:null};for(let U=T-1;U>=0;U--){const G=B(U);if(G===null)continue;const D=G+N,_=D+y;if(_+w<=t)break;t>=D-w&&t<_+w&&(I=I<0?U:Math.min(I,U))}for(let U=T;U<a;U++){const G=B(U);if(G===null)continue;const D=G+N;if(D-w>t)break;const _=D+y;t<_+w&&(I=I<0?U:Math.min(I,U))}}}if(I>=0){c.push({seriesIndex:u,dataIndex:I,point:f[I]});continue}}}}let C=-1,p=null,F=s;const b=(x,y)=>{!Number.isFinite(y)||!(y<F||y===F&&(C<0||x<C))||(F=y,C=x,p=f[x])};if(zr(f,M))if(M){const x=f;for(let y=0;y<a;y++){const d=x[y][0];if(!Number.isFinite(d))continue;const h=n.scale(d);if(!Number.isFinite(h))continue;const N=h-t;b(y,N*N)}}else{const x=f;for(let y=0;y<a;y++){const d=x[y].x;if(!Number.isFinite(d))continue;const h=n.scale(d);if(!Number.isFinite(h))continue;const N=h-t;b(y,N*N)}}else if(M){const x=f,y=Xr(x,o);let d=y-1,h=y;const N=w=>{const I=x[w][0];if(!Number.isFinite(I))return null;const R=n.scale(I);if(!Number.isFinite(R))return null;const P=R-t;return P*P};for(;d>=0||h<a;){for(;d>=0&&N(d)===null;)d--;for(;h<a&&N(h)===null;)h++;if(d<0&&h>=a)break;const w=d>=0?N(d)??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY,I=h<a?N(h)??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY;if(w>F&&I>F)break;w<=I?(d>=0&&w<=F&&b(d,w),d--,h<a&&I<=F&&I===w&&(b(h,I),h++)):(h<a&&I<=F&&b(h,I),h++)}}else{const x=f,y=Hr(x,o);let d=y-1,h=y;const N=w=>{const I=x[w].x;if(!Number.isFinite(I))return null;const R=n.scale(I);if(!Number.isFinite(R))return null;const P=R-t;return P*P};for(;d>=0||h<a;){for(;d>=0&&N(d)===null;)d--;for(;h<a&&N(h)===null;)h++;if(d<0&&h>=a)break;const w=d>=0?N(d)??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY,I=h<a?N(h)??Number.POSITIVE_INFINITY:Number.POSITIVE_INFINITY;if(w>F&&I>F)break;w<=I?(d>=0&&w<=F&&b(d,w),d--,h<a&&I<=F&&I===w&&(b(h,I),h++)):(h<a&&I<=F&&b(h,I),h++)}}p!==null&&c.push({seriesIndex:u,dataIndex:C,point:p})}return c}const Oc=e=>Math.min(1,Math.max(0,e)),kc=e=>{const t=e.trim().match(/^(\d+(?:\.\d+)?)%$/);if(!t)return null;const n=Number(t[1])/100;return Number.isFinite(n)?n:null},Ti=e=>Array.isArray(e),Xt=e=>Ti(e)?e[0]:e.timestamp,Vc=e=>Ti(e)?e[1]:e.open,zc=e=>Ti(e)?e[2]:e.close,qr=new WeakMap,Xc=e=>{const t=qr.get(e);if(t!==void 0)return t;const n=[];for(let s=0;s<e.length;s++){const o=Xt(e[s]);Number.isFinite(o)&&n.push(o)}if(n.length<2)return 1;n.sort((s,o)=>s-o);let i=Number.POSITIVE_INFINITY;for(let s=1;s<n.length;s++){const o=n[s]-n[s-1];o>0&&o<i&&(i=o)}const r=Number.isFinite(i)&&i>0?i:1;return qr.set(e,r),r};function Hc(e,t,n,i){if(t.length===0)return 0;const r=Xc(t);let s=0;if(Number.isFinite(r)&&r>0){let f=null;for(let a=0;a<t.length;a++){const v=Xt(t[a]);if(Number.isFinite(v)){f=v;break}}if(f!=null){const a=n.scale(f),v=n.scale(f+r),M=Math.abs(v-a);Number.isFinite(M)&&M>0&&(s=M)}}(!(s>0)||!Number.isFinite(s))&&(s=(Number.isFinite(i??Number.NaN)?i:0)/Math.max(1,t.length));let o=0;const c=e.barWidth;if(typeof c=="number")o=Number.isFinite(c)?Math.max(0,c):0;else if(typeof c=="string"){const f=kc(c);o=f==null?0:s*Oc(f)}const l=Number.isFinite(e.barMinWidth)?Math.max(0,e.barMinWidth):0,u=Number.isFinite(e.barMaxWidth)?Math.max(0,e.barMaxWidth):Number.POSITIVE_INFINITY,m=Math.max(l,u);return o=Math.min(Math.max(o,l),m),Number.isFinite(o)?o:0}const $n=new WeakMap,Yc=e=>{const t=$n.get(e);if(t!==void 0)return t;let n=Number.NEGATIVE_INFINITY;for(let i=0;i<e.length;i++){const r=Xt(e[i]);if(!Number.isFinite(r)||r<n)return $n.set(e,!1),!1;n=r}return $n.set(e,!0),!0},qc=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;Xt(e[r])<t?n=r+1:i=r}return n};function Zc(e,t,n,i,r,s){if(!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(s)||!(s>0))return null;const o=i.invert(t);if(!Number.isFinite(o))return null;const c=s/2;let l=null,u=Number.POSITIVE_INFINITY;const m=(a,v,M,C)=>{if(Number.isFinite(C)){if(C<u){u=C,l={seriesIndex:a,dataIndex:v,point:M};return}C===u&&l&&(v<l.dataIndex?l={seriesIndex:a,dataIndex:v,point:M}:v===l.dataIndex&&a<l.seriesIndex&&(l={seriesIndex:a,dataIndex:v,point:M}))}},f=a=>{const v=Vc(a),M=zc(a);if(!Number.isFinite(v)||!Number.isFinite(M))return!1;const C=r.scale(v),p=r.scale(M);if(!Number.isFinite(C)||!Number.isFinite(p))return!1;const F=Math.min(C,p),b=Math.max(C,p);return n>=F&&n<=b};for(let a=0;a<e.length;a++){const M=e[a].data,C=M.length;if(C===0)continue;if(!Yc(M)){for(let b=0;b<C;b++){const x=M[b],y=Xt(x);if(!Number.isFinite(y))continue;const d=i.scale(y);if(!Number.isFinite(d))continue;const h=Math.abs(t-d);h>c||f(x)&&m(a,b,x,h)}continue}const F=qc(M,o);for(let b=F-1;b>=0;b--){const x=M[b],y=Xt(x),d=i.scale(y);if(!Number.isFinite(d))continue;if(d<t-c)break;const h=Math.abs(t-d);h>c||f(x)&&m(a,b,x,h)}for(let b=F;b<C;b++){const x=M[b],y=Xt(x),d=i.scale(y);if(!Number.isFinite(d))continue;if(d>t+c)break;const h=Math.abs(t-d);h>c||f(x)&&m(a,b,x,h)}}return l}const Ht=Math.PI*2,Pi=e=>{if(!Number.isFinite(e))return 0;const t=e%Ht;return t<0?t+Ht:t};function jc(e,t,n,i,r){var x;if(!Number.isFinite(e)||!Number.isFinite(t)||!Number.isFinite(i.x)||!Number.isFinite(i.y))return null;const s=Number.isFinite(r.inner)?Math.max(0,r.inner):0,o=Number.isFinite(r.outer)?Math.max(0,r.outer):0;if(!(o>0))return null;const c=e-i.x,l=i.y-t,u=Math.hypot(c,l);if(!Number.isFinite(u)||u<=s||u>o)return null;const m=Pi(Math.atan2(l,c)),f=n.series,a=f.data;let v=0,M=0;for(let y=0;y<a.length;y++){const d=(x=a[y])==null?void 0:x.value;typeof d=="number"&&Number.isFinite(d)&&d>0&&(v+=d,M++)}if(!(v>0)||M===0)return null;const C=typeof f.startAngle=="number"&&Number.isFinite(f.startAngle)?f.startAngle:90;let p=Pi(C*Math.PI/180),F=0,b=0;for(let y=0;y<a.length;y++){const d=a[y],h=d==null?void 0:d.value;if(typeof h!="number"||!Number.isFinite(h)||h<=0)continue;b++;const N=b===M;let I=h/v*Ht;if(N?I=Math.max(0,Ht-F):I=Math.max(0,Math.min(Ht,I)),F+=I,!(I>0))continue;const R=p,P=Pi(p+I);p=P;let T=P-R;T<0&&(T+=Ht);let B=m-R;if(B<0&&(B+=Ht),B<=T)return{seriesIndex:n.seriesIndex,dataIndex:y,slice:d}}return null}const On=(e,t)=>{if(!Number.isFinite(t))throw new Error(`${e} must be a finite number. Received: ${String(t)}`)};function kn(){let e=0,t=1,n=0,i=1;const r={domain(s,o){return On("domain min",s),On("domain max",o),e=s,t=o,r},range(s,o){return On("range min",s),On("range max",o),n=s,i=o,r},scale(s){if(!Number.isFinite(s))return Number.NaN;if(e===t)return(n+i)/2;const o=(s-e)/(t-e);return n+o*(i-n)},invert(s){if(!Number.isFinite(s))return Number.NaN;if(e===t)return e;if(n===i)return(e+t)/2;const o=(s-n)/(i-n);return e+o*(t-e)}};return r}const Kc=e=>{switch(e){case"start":return{translateX:"0%",originX:"0%"};case"middle":return{translateX:"-50%",originX:"50%"};case"end":return{translateX:"-100%",originX:"100%"}}};function Jc(e){const t=getComputedStyle(e),n=t.position,i=t.overflow,r=n==="static",s=i==="hidden"||i==="scroll"||i==="auto",o=r?e.style.position:null,c=s?e.style.overflow:null;r&&(e.style.position="relative"),s&&(e.style.overflow="visible");const l=document.createElement("div");l.style.position="absolute",l.style.inset="0",l.style.pointerEvents="none",l.style.overflow="visible",l.style.zIndex="10",e.appendChild(l);let u=!1;return{clear:()=>{u||l.replaceChildren()},addLabel:(v,M,C,p)=>{if(u)return document.createElement("span");const F=document.createElement("span");F.textContent=v,F.style.position="absolute",F.style.left=`${M}px`,F.style.top=`${C}px`,F.style.pointerEvents="none",F.style.userSelect="none",F.style.whiteSpace="nowrap",F.style.lineHeight="1",(p==null?void 0:p.fontSize)!=null&&(F.style.fontSize=`${p.fontSize}px`),(p==null?void 0:p.color)!=null&&(F.style.color=p.color);const b=(p==null?void 0:p.rotation)??0,x=(p==null?void 0:p.anchor)??"start",{translateX:y,originX:d}=Kc(x);return F.style.transformOrigin=`${d} 50%`,F.style.transform=`translateX(${y}) translateY(-50%) rotate(${b}deg)`,l.appendChild(F),F},dispose:()=>{if(!u){u=!0;try{l.remove()}finally{o!==null&&(e.style.position=o),c!==null&&(e.style.overflow=c)}}}}}function Qc(e){return Math.max(e+1,Math.round(e*1.15))}function Vn(e,t,n){e.dir="auto",e.style.fontFamily=n.fontFamily,t.isTitle&&(e.style.fontWeight="600")}const el=(e,t)=>{var i;const n=(i=e.name)==null?void 0:i.trim();return n||`Series ${t+1}`},tl=(e,t,n)=>{var s;const i=(s=e.color)==null?void 0:s.trim();if(i)return i;const r=n.colorPalette;return r.length>0?r[t%r.length]??"#000000":"#000000"},nl=(e,t)=>{const n=e==null?void 0:e.trim();return n||`Slice ${t+1}`},il=(e,t,n,i)=>{const r=e==null?void 0:e.trim();if(r)return r;const s=i.colorPalette,o=s.length;return o>0?s[(t+n)%o]??"#000000":"#000000"};function rl(e,t="right"){const i=getComputedStyle(e).position==="static",r=i?e.style.position:null;i&&(e.style.position="relative");const s=document.createElement("div");s.style.position="absolute",s.style.pointerEvents="none",s.style.userSelect="none",s.style.boxSizing="border-box",s.style.padding="8px",s.style.borderRadius="8px",s.style.borderStyle="solid",s.style.borderWidth="1px",s.style.maxHeight="calc(100% - 16px)",s.style.overflow="auto";const o=document.createElement("div");o.style.display="flex",o.style.gap="8px",s.appendChild(o),(f=>{switch(s.style.top="",s.style.right="",s.style.bottom="",s.style.left="",s.style.maxWidth="",o.style.flexDirection="",o.style.flexWrap="",o.style.alignItems="",f){case"right":{s.style.top="8px",s.style.right="8px",s.style.maxWidth="40%",o.style.flexDirection="column",o.style.flexWrap="nowrap",o.style.alignItems="flex-start";return}case"left":{s.style.top="8px",s.style.left="8px",s.style.maxWidth="40%",o.style.flexDirection="column",o.style.flexWrap="nowrap",o.style.alignItems="flex-start";return}case"top":{s.style.top="8px",s.style.left="8px",s.style.right="8px",o.style.flexDirection="row",o.style.flexWrap="wrap",o.style.alignItems="center";return}case"bottom":{s.style.bottom="8px",s.style.left="8px",s.style.right="8px",o.style.flexDirection="row",o.style.flexWrap="wrap",o.style.alignItems="center";return}}})(t),e.appendChild(s);let l=!1;return{update:(f,a)=>{if(l)return;s.style.color=a.textColor,s.style.background=a.backgroundColor,s.style.borderColor=a.axisLineColor,s.style.fontFamily=a.fontFamily,s.style.fontSize=`${a.fontSize}px`;const v=[];for(let M=0;M<f.length;M++){const C=f[M];if(C.type==="pie")for(let p=0;p<C.data.length;p++){const F=C.data[p],b=document.createElement("div");b.style.display="flex",b.style.alignItems="center",b.style.gap="6px",b.style.lineHeight="1.1",b.style.whiteSpace="nowrap";const x=document.createElement("div");x.style.width="10px",x.style.height="10px",x.style.borderRadius="2px",x.style.flex="0 0 auto",x.style.background=il(F==null?void 0:F.color,M,p,a),x.style.border=`1px solid ${a.axisLineColor}`;const y=document.createElement("span");y.textContent=nl(F==null?void 0:F.name,p),b.appendChild(x),b.appendChild(y),v.push(b)}else{const p=document.createElement("div");p.style.display="flex",p.style.alignItems="center",p.style.gap="6px",p.style.lineHeight="1.1",p.style.whiteSpace="nowrap";const F=document.createElement("div");F.style.width="10px",F.style.height="10px",F.style.borderRadius="2px",F.style.flex="0 0 auto",F.style.background=tl(C,M,a),F.style.border=`1px solid ${a.axisLineColor}`;const b=document.createElement("span");b.textContent=el(C,M),p.appendChild(F),p.appendChild(b),v.push(p)}}o.replaceChildren(...v)},dispose:()=>{if(!l){l=!0;try{s.remove()}finally{r!==null&&(e.style.position=r)}}}}}const Zr=(e,t,n)=>n<t||e<t?t:e>n?n:e;function jr(e){const n=getComputedStyle(e).position==="static",i=n?e.style.position:null;n&&(e.style.position="relative");const r=document.createElement("div");r.style.position="absolute",r.style.left="0",r.style.top="0",r.style.pointerEvents="none",r.style.userSelect="none",r.style.boxSizing="border-box",r.style.zIndex="var(--chartgpu-tooltip-z, 10)",r.style.padding="var(--chartgpu-tooltip-padding, 6px 8px)",r.style.borderRadius="var(--chartgpu-tooltip-radius, 8px)",r.style.borderStyle="solid",r.style.borderWidth="var(--chartgpu-tooltip-border-width, 1px)",r.style.borderColor="var(--chartgpu-tooltip-border, rgba(224,224,224,0.35))",r.style.boxShadow="var(--chartgpu-tooltip-shadow, 0 6px 18px rgba(0,0,0,0.35))",r.style.maxWidth="var(--chartgpu-tooltip-max-width, min(320px, 100%))",r.style.overflow="hidden",r.style.fontFamily='var(--chartgpu-tooltip-font-family, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji")',r.style.fontSize="var(--chartgpu-tooltip-font-size, 12px)",r.style.lineHeight="var(--chartgpu-tooltip-line-height, 1.2)",r.style.color="var(--chartgpu-tooltip-color, #e0e0e0)",r.style.background="var(--chartgpu-tooltip-bg, rgba(26,26,46,0.95))",r.style.whiteSpace="normal",r.style.opacity="0",r.style.transitionProperty="opacity";const s=140;r.style.transitionDuration=`${s}ms`,r.style.transitionTimingFunction="ease",r.style.willChange="opacity",r.style.display="none",r.style.visibility="hidden",r.setAttribute("role","tooltip"),e.appendChild(r);let o=!1,c=0,l=null,u=null;const m=()=>{l!=null&&(window.clearTimeout(l),l=null),u!=null&&(window.cancelAnimationFrame(u),u=null)},f=()=>r.style.display==="none"||r.style.visibility==="hidden",a=()=>{const p=r.style.visibility;r.style.visibility="hidden";const F=r.offsetWidth,b=r.offsetHeight;return r.style.visibility=p,{width:F,height:b}};return{show:(p,F,b)=>{if(o)return;c+=1,m();const x=f();r.innerHTML=b;const y=12,d=12,h=8;r.style.display="block",r.style.visibility="hidden";const{width:N,height:w}=a(),I=e.clientWidth,R=e.clientHeight;let P=p+y,T=F+d;if(P+N>I-h&&(P=p-y-N),T+w>R-h&&(T=F-d-w),P=Zr(P,h,I-h-N),T=Zr(T,h,R-h-w),r.style.left=`${P}px`,r.style.top=`${T}px`,r.style.visibility="visible",x){r.style.opacity="0";const B=c;u=window.requestAnimationFrame(()=>{u=null,!o&&B===c&&(r.style.opacity="1")})}else r.style.opacity="1"},hide:()=>{if(o)return;if(c+=1,m(),r.style.display==="none"||r.style.visibility==="hidden"){r.style.opacity="0",r.style.visibility="hidden",r.style.display="none";return}r.style.opacity="0";const p=c;l=window.setTimeout(()=>{l=null,!o&&p===c&&(r.style.visibility="hidden",r.style.display="none")},s+50)},dispose:()=>{if(!o){o=!0;try{m(),r.remove()}finally{i!==null&&(e.style.position=i)}}}}}const zn="—";function xt(e){return e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function Yt(e){if(!Number.isFinite(e))return zn;const i=(Object.is(e,-0)?0:e).toFixed(2).replace(/\.?0+$/,"");return i==="-0"?"0":i}function Kr(e){const t=e.seriesName.trim();return t.length>0?t:`Series ${e.seriesIndex+1}`}function Jr(e){const t=e.trim();return t.length===0?"#888":/^#[0-9a-fA-F]{3}$/.test(t)||/^#[0-9a-fA-F]{6}$/.test(t)||/^#[0-9a-fA-F]{8}$/.test(t)||/^rgba?\(\s*\d{1,3}\s*(?:,\s*|\s+)\d{1,3}\s*(?:,\s*|\s+)\d{1,3}(?:\s*(?:,\s*|\/\s*)(?:0|1|0?\.\d+))?\s*\)$/.test(t)||/^[a-zA-Z]+$/.test(t)?t:"#888"}function Qr(e){return e.length===5}function sl(e,t){if(!Number.isFinite(e)||!Number.isFinite(t)||e===0)return zn;const n=(t-e)/e*100;return Number.isFinite(n)?`${n>0?"+":""}${n.toFixed(2)}%`:zn}function es(e,t){const n=xt(Kr(e)),i=xt(t);return['<div style="display:flex;align-items:center;justify-content:space-between;gap:12px;">','<span style="display:flex;align-items:center;gap:8px;min-width:0;">',`<span style="width:8px;height:8px;border-radius:999px;flex:0 0 auto;background-color:${xt(Jr(e.color))};"></span>`,`<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;">${n}</span>`,"</span>",`<span style="font-variant-numeric:tabular-nums;white-space:nowrap;">${i}</span>`,"</div>"].join("")}function ts(e){const[,t,n,i,r]=e.value,s=xt(Kr(e)),o=xt(Jr(e.color)),c=Yt(t),l=Yt(r),u=Yt(i),m=Yt(n),f=n>t,a=f?"▲":"▼",v=f?"#22c55e":"#ef4444",M=sl(t,n),C=`O: ${c} H: ${l} L: ${u} C: ${m}`,p=xt(C),F=xt(a),b=xt(M),x=xt(v);return['<div style="display:flex;flex-direction:column;gap:4px;">','<div style="display:flex;align-items:center;gap:8px;">',`<span style="width:8px;height:8px;border-radius:999px;flex:0 0 auto;background-color:${o};"></span>`,`<span style="overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-weight:600;">${s}</span>`,"</div>",`<div style="font-variant-numeric:tabular-nums;white-space:nowrap;font-size:0.9em;">${p}</div>`,'<div style="display:flex;align-items:center;gap:6px;font-variant-numeric:tabular-nums;">',`<span style="color:${x};font-weight:700;">${F}</span>`,`<span style="color:${x};font-weight:600;">${b}</span>`,"</div>","</div>"].join("")}function ol(e){return ts(e)}function bn(e){return Qr(e.value)?ol(e):es(e,Yt(e.value[1]))}function Ri(e){if(e.length===0)return"";const t=`x: ${Yt(e[0].value[0])}`,n=`<div style="margin:0 0 6px 0;font-weight:600;font-variant-numeric:tabular-nums;white-space:nowrap;">${xt(t)}</div>`,i=e.map(r=>Qr(r.value)?ts(r):es(r,Yt(r.value[1]))).join('<div style="height:4px;"></div>');return`${n}${i}`}const al=e=>Number.isFinite(e)?e:0,cl=e=>Number.isFinite(e)?e:null;function ns(){const e=new Map;function t(s,o,c,l,u,m){const f=Symbol("Animation");if(Array.isArray(s)||Array.isArray(o)){if(!Array.isArray(s)||!Array.isArray(o))throw new Error('Array animation requires both "from" and "to" to be arrays');if(s.length!==o.length)throw new Error(`Array animation length mismatch: from.length=${s.length}, to.length=${o.length}`);const a=new Array(s.length);return e.set(f,{kind:"array",from:s,to:o,duration:c,easing:l,onUpdate:u,onComplete:m,startTime:null,out:a}),f}return e.set(f,{kind:"scalar",from:s,to:o,duration:c,easing:l,onUpdate:u,onComplete:m,startTime:null}),f}function n(s){e.delete(s)}function i(){e.clear()}function r(s){var l;const o=cl(s);if(o===null)return;const c=Array.from(e.keys());for(const u of c){const m=e.get(u);if(!m)continue;const f=m.startTime??o;m.startTime===null&&e.set(u,{...m,startTime:f});const a=al(m.duration),v=Math.max(0,o-f),M=a<=0||v>=a,C=a<=0?1:v/a,p=M?1:m.easing(C);if(m.kind==="scalar"){const F=m.from+(m.to-m.from)*p;if(m.onUpdate(F),!e.has(u))continue}else{const F=m.out.length;for(let b=0;b<F;b++){const x=m.from[b]??0,y=m.to[b]??0;m.out[b]=x+(y-x)*p}if(m.onUpdate(m.out),!e.has(u))continue}M&&((l=m.onComplete)==null||l.call(m),e.delete(u))}}return{animate:t,cancel:n,cancelAll:i,update:r}}const Xn=e=>Number.isNaN(e)||e<=0?0:e>=1?1:e;function is(e){return Xn(e)}function ll(e){const n=1-Xn(e);return 1-n*n*n}function ul(e){const t=Xn(e);if(t<.5)return 4*t*t*t;const n=-2*t+2;return 1-n*n*n/2}function fl(e){const t=Xn(e),n=7.5625,i=2.75;if(t<1/i)return n*t*t;if(t<2/i){const s=t-1.5/i;return n*s*s+.75}if(t<2.5/i){const s=t-2.25/i;return n*s*s+.9375}const r=t-2.625/i;return n*r*r+.984375}function ml(e){switch(e){case"linear":return is;case"cubicOut":return ll;case"cubicInOut":return ul;case"bounceOut":return fl;default:return is}}const Ye=Ki;function rs(e,t=1){return e?Ye(e)?e.clientWidth:e.width/t:0}function dl(e,t=1){return e?Ye(e)?e.clientHeight:e.height/t:0}const hl="bgra8unorm",gn=5,ss=6,Ai=4,pl=1,bl=4,Hn=24*60*60*1e3,gl=30*Hn,yl=365*Hn,xl=9,Bi=1,vl=6,Yn=e=>typeof e=="number"&&Number.isFinite(e)?e:null,vt=e=>typeof e=="number"&&Number.isFinite(e)?e:void 0,wl=2e4,Ei=e=>{throw new Error(`RenderCoordinator: unreachable value: ${String(e)}`)},qn=e=>Array.isArray(e),wt=e=>qn(e)?{x:e[0],y:e[1]}:{x:e.x,y:e.y},Di=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;for(let s=0;s<e.length;s++){const{x:o,y:c}=wt(e[s]);!Number.isFinite(o)||!Number.isFinite(c)||(o<t&&(t=o),o>n&&(n=o),c<i&&(i=c),c>r&&(r=c))}return!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)?null:(t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r})},Fl=(e,t)=>{if(t.length===0)return e;let n=e;if(!n){const c=Di(t);if(!c)return e;n=c}let i=n.xMin,r=n.xMax,s=n.yMin,o=n.yMax;for(let c=0;c<t.length;c++){const{x:l,y:u}=wt(t[c]);!Number.isFinite(l)||!Number.isFinite(u)||(l<i&&(i=l),l>r&&(r=l),u<s&&(s=u),u>o&&(o=u))}return i===r&&(r=i+1),s===o&&(o=s+1),{xMin:i,xMax:r,yMin:s,yMax:o}},Nl=(e,t)=>{if(t.length===0)return e;let n=(e==null?void 0:e.xMin)??Number.POSITIVE_INFINITY,i=(e==null?void 0:e.xMax)??Number.NEGATIVE_INFINITY,r=(e==null?void 0:e.yMin)??Number.POSITIVE_INFINITY,s=(e==null?void 0:e.yMax)??Number.NEGATIVE_INFINITY;for(let o=0;o<t.length;o++){const c=t[o],l=ft(c)?c[0]:c.timestamp,u=ft(c)?c[3]:c.low,m=ft(c)?c[4]:c.high;!Number.isFinite(l)||!Number.isFinite(u)||!Number.isFinite(m)||(l<n&&(n=l),l>i&&(i=l),u<r&&(r=u),m>s&&(s=m))}return!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)||!Number.isFinite(s)?e:(n===i&&(i=n+1),r===s&&(s=r+1),{xMin:n,xMax:i,yMin:r,yMax:s})},os=(e,t)=>{let n=Number.POSITIVE_INFINITY,i=Number.NEGATIVE_INFINITY,r=Number.POSITIVE_INFINITY,s=Number.NEGATIVE_INFINITY;for(let o=0;o<e.length;o++){const c=e[o];if(c.type==="pie")continue;const l=(t==null?void 0:t[o])??null;if(l){const f=l;if(Number.isFinite(f.xMin)&&Number.isFinite(f.xMax)&&Number.isFinite(f.yMin)&&Number.isFinite(f.yMax)){f.xMin<n&&(n=f.xMin),f.xMax>i&&(i=f.xMax),f.yMin<r&&(r=f.yMin),f.yMax>s&&(s=f.yMax);continue}}const u=c.rawBounds;if(u){const f=u;if(Number.isFinite(f.xMin)&&Number.isFinite(f.xMax)&&Number.isFinite(f.yMin)&&Number.isFinite(f.yMax)){f.xMin<n&&(n=f.xMin),f.xMax>i&&(i=f.xMax),f.yMin<r&&(r=f.yMin),f.yMax>s&&(s=f.yMax);continue}}if(c.type==="candlestick"){const f=c.rawData??c.data;for(let a=0;a<f.length;a++){const v=f[a];if(ft(v)){const M=v[0],C=v[3],p=v[4];if(!Number.isFinite(M)||!Number.isFinite(C)||!Number.isFinite(p))continue;const F=Math.min(C,p),b=Math.max(C,p);M<n&&(n=M),M>i&&(i=M),F<r&&(r=F),b>s&&(s=b)}else{const M=v.timestamp,C=v.low,p=v.high;if(!Number.isFinite(M)||!Number.isFinite(C)||!Number.isFinite(p))continue;const F=Math.min(C,p),b=Math.max(C,p);M<n&&(n=M),M>i&&(i=M),F<r&&(r=F),b>s&&(s=b)}}continue}const m=c.data;for(let f=0;f<m.length;f++){const{x:a,y:v}=wt(m[f]);!Number.isFinite(a)||!Number.isFinite(v)||(a<n&&(n=a),a>i&&(i=a),v<r&&(r=v),v>s&&(s=v))}}return!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)||!Number.isFinite(s)?{xMin:0,xMax:1,yMin:0,yMax:1}:(n===i&&(i=n+1),r===s&&(s=r+1),{xMin:n,xMax:i,yMin:r,yMax:s})},Zn=(e,t)=>{let n=e,i=t;if((!Number.isFinite(n)||!Number.isFinite(i))&&(n=0,i=1),n===i)i=n+1;else if(n>i){const r=n;n=i,i=r}return{min:n,max:i}},as=(e,t)=>{const n=e.canvas;if(!n)throw new Error("RenderCoordinator: gpuContext.canvas is required.");const i=e.devicePixelRatio??1,r=Number.isFinite(i)&&i>0?i:1,s=n.width,o=n.height;if(!Number.isFinite(s)||!Number.isFinite(o))throw new Error(`RenderCoordinator: Invalid canvas dimensions: width=${s}, height=${o}. Canvas must be initialized with finite dimensions before rendering.`);const c=Math.max(1,Math.floor(s)),l=Math.max(1,Math.floor(o)),u=Number.isFinite(t.grid.left)?t.grid.left:0,m=Number.isFinite(t.grid.right)?t.grid.right:0,f=Number.isFinite(t.grid.top)?t.grid.top:0,a=Number.isFinite(t.grid.bottom)?t.grid.bottom:0,v=Math.max(0,u),M=Math.max(0,m),C=Math.max(0,f),p=Math.max(0,a);return{left:v,right:M,top:C,bottom:p,canvasWidth:c,canvasHeight:l,devicePixelRatio:r}},Ml=e=>{const t=Math.max(0,Math.min(255,Math.round(e[0]*255))),n=Math.max(0,Math.min(255,Math.round(e[1]*255))),i=Math.max(0,Math.min(255,Math.round(e[2]*255))),r=Math.max(0,Math.min(1,e[3]));return`rgba(${t},${n},${i},${r})`},cs=(e,t)=>{const n=Ke(e);if(!n)return e;const i=Math.max(0,Math.min(1,n[3]*t));return Ml([n[0],n[1],n[2],i])},Sl=(e,t)=>{if(e.length===0)return 0;const n=e.reduce((i,r)=>Math.max(i,r.text.length),0);return Math.ceil(n*t*.6)},Cl=e=>{const{left:t,right:n,top:i,bottom:r,canvasWidth:s,canvasHeight:o,devicePixelRatio:c}=e,l=t*c,u=s-n*c,m=i*c,f=o-r*c,a=l/s*2-1,v=u/s*2-1,M=1-m/o*2,C=1-f/o*2;return{left:a,right:v,top:M,bottom:C}},Ft=e=>Math.min(1,Math.max(0,e)),Nt=(e,t,n)=>Math.min(n,Math.max(t,e|0)),jn=(e,t,n)=>e+(t-e)*Ft(n),Kn=(e,t,n)=>Zn(jn(e.min,t.min,n),jn(e.max,t.max,n)),ls=e=>{const{canvasWidth:t,canvasHeight:n,devicePixelRatio:i}=e,r=e.left*i,s=t-e.right*i,o=e.top*i,c=n-e.bottom*i,l=Nt(Math.floor(r),0,Math.max(0,t)),u=Nt(Math.floor(o),0,Math.max(0,n)),m=Nt(Math.ceil(s),0,Math.max(0,t)),f=Nt(Math.ceil(c),0,Math.max(0,n)),a=Math.max(0,m-l),v=Math.max(0,f-u);return{x:l,y:u,w:a,h:v}},Jn=(e,t)=>(e+1)/2*t,Ui=(e,t)=>(1-e)/2*t,Il=e=>Array.isArray(e),us=e=>e.length>0&&Il(e[0]),qt=new WeakMap,fs=(e,t)=>{const n=qt.get(e);if(n!==void 0)return n;let i=Number.NEGATIVE_INFINITY;if(t){const s=e;for(let o=0;o<s.length;o++){const c=s[o][0];if(!Number.isFinite(c)||c<i)return qt.set(e,!1),!1;i=c}return qt.set(e,!0),!0}const r=e;for(let s=0;s<r.length;s++){const o=r[s].x;if(!Number.isFinite(o)||o<i)return qt.set(e,!1),!1;i=o}return qt.set(e,!0),!0},ms=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<t?n=r+1:i=r}return n},ds=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<=t?n=r+1:i=r}return n},hs=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].x<t?n=r+1:i=r}return n},ps=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].x<=t?n=r+1:i=r}return n},Qn=(e,t,n)=>{const i=e.length;if(i===0||!Number.isFinite(t)||!Number.isFinite(n))return e;const r=us(e);if(fs(e,r)){const c=r?ms(e,t):hs(e,t),l=r?ds(e,n):ps(e,n);return c<=0&&l>=i?e:l<=c?[]:e.slice(c,l)}const o=[];for(let c=0;c<i;c++){const l=e[c],{x:u}=wt(l);Number.isFinite(u)&&u>=t&&u<=n&&o.push(l)}return o},Tl=(e,t,n)=>{const i=e.length;if(i===0)return{start:0,end:0};if(!Number.isFinite(t)||!Number.isFinite(n))return{start:0,end:i};const r=us(e);if(!fs(e,r))return{start:0,end:i};const o=r?ms(e,t):hs(e,t),c=r?ds(e,n):ps(e,n),l=Nt(o,0,i),u=Nt(c,0,i);return u<=l?{start:l,end:l}:{start:l,end:u}};function ft(e){return Array.isArray(e)}const ei=new WeakMap,Pl=e=>{const t=ei.get(e);if(t!==void 0)return t;let n=Number.NEGATIVE_INFINITY;for(let i=0;i<e.length;i++){const r=e[i],s=ft(r)?r[0]:r.timestamp;if(!Number.isFinite(s)||s<n)return ei.set(e,!1),!1;n=s}return ei.set(e,!0),!0},Rl=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<t?n=r+1:i=r}return n},Al=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r][0]<=t?n=r+1:i=r}return n},Bl=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].timestamp<t?n=r+1:i=r}return n},El=(e,t)=>{let n=0,i=e.length;for(;n<i;){const r=n+i>>>1;e[r].timestamp<=t?n=r+1:i=r}return n},ti=(e,t,n)=>{const i=e.length;if(i===0||!Number.isFinite(t)||!Number.isFinite(n))return e;const r=Pl(e),s=i>0&&ft(e[0]);if(r){const c=s?Rl(e,t):Bl(e,t),l=s?Al(e,n):El(e,n);return c<=0&&l>=i?e:l<=c?[]:e.slice(c,l)}const o=[];for(let c=0;c<i;c++){const l=e[c],u=ft(l)?l[0]:l.timestamp;Number.isFinite(u)&&u>=t&&u<=n&&o.push(l)}return o},yn=(e,t)=>{if(typeof e=="number")return Number.isFinite(e)?e:null;if(typeof e!="string")return null;const n=e.trim();if(n.length===0)return null;if(n.endsWith("%")){const r=Number.parseFloat(n.slice(0,-1));return Number.isFinite(r)?r/100*t:null}const i=Number.parseFloat(n);return Number.isFinite(i)?i:null},Dl=(e,t,n)=>{const i=(e==null?void 0:e[0])??"50%",r=(e==null?void 0:e[1])??"50%",s=yn(i,t),o=yn(r,n);return{x:Number.isFinite(s)?s:t*.5,y:Number.isFinite(o)?o:n*.5}},Ul=e=>Array.isArray(e),bs=(e,t)=>{if(e==null)return{inner:0,outer:t*.7};if(Ul(e)){const r=yn(e[0],t),s=yn(e[1],t),o=Math.max(0,Number.isFinite(r)?r:0),c=Math.max(o,Number.isFinite(s)?s:t*.7);return{inner:o,outer:Math.min(t,c)}}const n=yn(e,t),i=Math.max(0,Number.isFinite(n)?n:t*.7);return{inner:0,outer:Math.min(t,i)}},Ll=6,_l=(e,t=Ll)=>{const n=Math.abs(e);if(!Number.isFinite(n)||n===0)return 0;for(let i=0;i<=t;i++){const r=n*10**i,s=Math.round(r),o=Math.abs(r-s),c=1e-9*Math.max(1,Math.abs(r));if(o<=c)return i}return Math.max(0,Math.min(t,Math.ceil(-Math.log10(n))+1))},gs=e=>{const t=_l(e);return new Intl.NumberFormat(void 0,{maximumFractionDigits:t})},ys=(e,t)=>{if(!Number.isFinite(t))return null;const n=Math.abs(t)<1e-12?0:t,i=e.format(n);return i==="NaN"?null:i},mt=e=>String(Math.trunc(e)).padStart(2,"0"),Gl=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],xs=(e,t)=>{if(!Number.isFinite(e))return null;(!Number.isFinite(t)||t<0)&&(t=0);const n=new Date(e);if(!Number.isFinite(n.getTime()))return null;const i=n.getFullYear(),r=n.getMonth()+1,s=n.getDate(),o=n.getHours(),c=n.getMinutes();return t<Hn?`${mt(o)}:${mt(c)}`:t<=7*Hn?`${mt(r)}/${mt(s)} ${mt(o)}:${mt(c)}`:t<3*gl?`${mt(r)}/${mt(s)}`:t<=yl?`${Gl[n.getMonth()]??mt(r)} ${mt(s)}`:`${i}/${mt(r)}`},ni=(e,t,n)=>{const i=Math.max(1,Math.floor(n)),r=new Array(i);for(let s=0;s<i;s++){const o=i===1?.5:s/(i-1);r[s]=e+o*(t-e)}return r},Wl=e=>{const{axisMin:t,axisMax:n,xScale:i,plotClipLeft:r,plotClipRight:s,canvasCssWidth:o,visibleRangeMs:c,measureCtx:l,measureCache:u,fontSize:m,fontFamily:f}=e,a=Yn(t)??i.invert(r),v=Yn(n)??i.invert(s);if(!l||o<=0)return{tickCount:gn,tickValues:ni(a,v,gn)};l.font=`${m}px ${f}`,u&&u.size>2e3&&u.clear();const M=u?`${m}px ${f}@@`:null;for(let C=xl;C>=Bi;C--){const p=ni(a,v,C);let F=Number.NEGATIVE_INFINITY,b=!0;for(let x=0;x<p.length;x++){const y=p[x],d=xs(y,c);if(d==null)continue;const h=(()=>{if(!M)return l.measureText(d).width;const T=M+d,B=u.get(T);if(B!=null)return B;const U=l.measureText(d).width;return u.set(T,U),U})(),N=i.scale(y),w=Jn(N,o),I=C===1?"middle":x===0?"start":x===p.length-1?"end":"middle",R=I==="start"?w:I==="end"?w-h:w-h*.5,P=I==="start"?w+h:I==="end"?w:w+h*.5;if(R<F+vl){b=!1;break}F=P}if(b)return{tickCount:C,tickValues:p}}return{tickCount:Bi,tickValues:ni(a,v,Bi)}},Zt=(e,t)=>{const n=os(e.series,t),i=vt(e.xAxis.min)??n.xMin,r=vt(e.xAxis.max)??n.xMax;return Zn(i,r)},Li=(e,t)=>{const n=os(e.series,t),i=vt(e.yAxis.min)??n.yMin,r=vt(e.yAxis.max)??n.yMax;return Zn(i,r)},jt=(e,t)=>{if(!t)return{...e,spanFraction:1};const n=e.max-e.min;if(!Number.isFinite(n)||n===0)return{...e,spanFraction:1};const i=t.start,r=t.end,s=e.min+i/100*n,o=e.min+r/100*n,c=Zn(s,o),l=(r-i)/100,u=Number.isFinite(l)?Math.max(0,Math.min(1,l)):1;return{min:c.min,max:c.max,spanFraction:u}},vs=e=>{if(e===!1||e==null)return null;const t=e===!0?{}:e;if(!t)return null;const n=t.duration??300,i=t.delay??0,r=Number.isFinite(n)?Math.max(0,n):300,s=Number.isFinite(i)?Math.max(0,i):0;return{durationMs:r,delayMs:s,easing:ml(t.easing)}},$l=e=>vs(e),Ol=e=>vs(e),_i=(e,t,n,i,r)=>{const s=e.point,o=ft(s)?s[0]:s.timestamp,c=ft(s)?s[1]:s.open,l=ft(s)?s[2]:s.close;if(!Number.isFinite(o)||!Number.isFinite(c)||!Number.isFinite(l))return null;const u=(c+l)/2,m=t.scale(o),f=n.scale(u);if(!Number.isFinite(m)||!Number.isFinite(f))return null;const a=i.left+m,v=i.top+f,M=Ye(r)?r.offsetLeft+a:a,C=Ye(r)?r.offsetTop+v:v;return!Number.isFinite(M)||!Number.isFinite(C)?null:{x:M,y:C}},ws=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY;for(let i=0;i<e.length;i++){const r=e[i].data;for(let s=0;s<r.length;s++){const{y:o}=wt(r[s]);Number.isFinite(o)&&(o<t&&(t=o),o>n&&(n=o))}}return!Number.isFinite(t)||!Number.isFinite(n)||t<=0&&0<=n?0:Math.abs(t)<Math.abs(n)?t:n},kl=(e,t,n)=>{const i=t.invert(n.bottom),r=t.invert(n.top),s=Math.min(i,r),o=Math.max(i,r);return!Number.isFinite(s)||!Number.isFinite(o)?ws(e):s<=0&&0<=o?0:s>0?s:o<0?o:ws(e)},Vl=(e,t,n,i)=>{const r=Ft(i);if(r>=1)return e;const s=kl(n,e,t),o=e.scale(s),c={domain(l,u){return e.domain(l,u),c},range(l,u){return e.range(l,u),c},scale(l){const u=e.scale(l);return!Number.isFinite(u)||!Number.isFinite(o)?u:o+(u-o)*r},invert(l){return e.invert(l)}};return c};function zl(e,t,n){var ks;if(!e.initialized)throw new Error("RenderCoordinator: gpuContext must be initialized.");const i=e.device;if(!i)throw new Error("RenderCoordinator: gpuContext.device is required.");if(!e.canvas)throw new Error("RenderCoordinator: gpuContext.canvas is required.");if(!e.canvasContext)throw new Error("RenderCoordinator: gpuContext.canvasContext is required.");i.lost.then(g=>{var A;(A=n==null?void 0:n.onDeviceLost)==null||A.call(n,g.message||g.reason||"unknown")}).catch(()=>{});const r=e.preferredFormat??hl,s=(n==null?void 0:n.domOverlays)!==!1,o=s&&Ye(e.canvas)?e.canvas.parentElement:null,c=o?Jc(o):null,l=o?rl(o,"right"):null,u=(()=>{if(typeof document>"u")return null;try{return document.createElement("canvas").getContext("2d")}catch{return null}})(),m=u?new Map:null;let f=!1,a=t,v=t.series.length,M="pending",C=0;const p=ns();let F=null,b=!1;const x=ns();let y=null,d=1,h=null;const N={cartesianDataBySeriesIndex:[],pieDataBySeriesIndex:[]},w=()=>{N.cartesianDataBySeriesIndex.length=0,N.pieDataBySeriesIndex.length=0},I=(g,A,S,E)=>{if(g.length!==A.length)return null;const W=A.length;if(W===0)return E??[];const O=E&&E.length===W?E:(()=>{const q=new Array(W);for(let k=0;k<W;k++){const H=A[k],{x:J}=wt(H),j=qn(H)?H[2]:H==null?void 0:H.size;q[k]=qn(H)?j==null?[J,0]:[J,0,j]:j==null?{x:J,y:0}:{x:J,y:0,size:j}}return q})(),$=Ft(S);for(let q=0;q<W;q++){const k=wt(g[q]).y,H=wt(A[q]).y,J=Number.isFinite(k)&&Number.isFinite(H)?jn(k,H,$):H,j=O[q];qn(j)?j[1]=J:j.y=J}return O},R=(g,A,S,E)=>{var H,J;const W=g.data,O=A.data;if(W.length!==O.length)return A;const $=O.length,q=E&&E.length===$?E:(()=>{const j=new Array($);for(let pe=0;pe<$;pe++)j[pe]={...O[pe],value:0};return j})(),k=Ft(S);for(let j=0;j<$;j++){const pe=(H=W[j])==null?void 0:H.value,me=(J=O[j])==null?void 0:J.value,Be=typeof pe=="number"&&typeof me=="number"&&Number.isFinite(pe)&&Number.isFinite(me)?Math.max(0,jn(pe,me,k)):typeof me=="number"&&Number.isFinite(me)?me:0;q[j].value=Be}return{...A,data:q}},P=(g,A,S,E)=>{if(g.length!==A.length)return A;const W=new Array(A.length);for(let O=0;O<A.length;O++){const $=g[O],q=A[O];if($.type!==q.type){W[O]=q;continue}if(q.type==="pie"){const Be=(E==null?void 0:E.pieDataBySeriesIndex[O])??null,Xe=R($,q,S,Be);E&&(E.pieDataBySeriesIndex[O]=Xe.data),W[O]=Xe;continue}const k=$,H=q,J=k.data,j=H.data;if(J.length!==j.length){W[O]=q;continue}if(j.length>wl){W[O]=q;continue}const pe=(E==null?void 0:E.cartesianDataBySeriesIndex[O])??null,me=I(J,j,S,pe);if(!me){W[O]=q;continue}E&&(E.cartesianDataBySeriesIndex[O]=me),W[O]={...q,data:me}}return W},T=(g,A,S)=>{const E=Kn(g.from.xBaseDomain,g.to.xBaseDomain,A),W=jt(E,S),O=Kn(g.from.yBaseDomain,g.to.yBaseDomain,A),$=P(g.from.series,g.to.series,A,null);return{xBaseDomain:E,xVisibleDomain:{min:W.min,max:W.max},yBaseDomain:O,series:$}},B=new Set;let U=new Array(t.series.length).fill(null),G=new Array(t.series.length).fill(null),D=a.series,_=a.series,X=[],Z=!1,V=null,re=null,ce=null,Y=!1;const ne=new Map;let Se=new Array(a.series.length).fill("unknown");const Ce=new Set;let fe=o&&((ks=a.tooltip)==null?void 0:ks.show)!==!1?jr(o):null,oe=null,ve=null,we=null;const ue=(g,A,S,E)=>{if(fe==null||fe.show(g,A,S),!s&&(n!=null&&n.onTooltipUpdate)){const W=Array.isArray(E)?E:[E];n.onTooltipUpdate({content:S,params:W,x:g,y:A})}},se=()=>{fe==null||fe.hide(),!s&&(n!=null&&n.onTooltipUpdate)&&n.onTooltipUpdate(null)},be=()=>{oe=null,ve=null,we=null,se()},K=g=>{!s&&(n!=null&&n.onCrosshairMove)&&n.onCrosshairMove(g)},ee=g=>{!s&&(n!=null&&n.onHoverChange)&&n.onHoverChange(g)};((g,A)=>{if(l==null||l.update(g,A),!s&&(n!=null&&n.onLegendUpdate)){const S=g.map((E,W)=>({name:E.name??"",color:E.color??"#888",seriesIndex:W}));n.onLegendUpdate(S)}})(a.series,a.theme);let he=eo(i);const te=Ro(i,{targetFormat:r}),Re=ur(i,{targetFormat:r}),Fe=ur(i,{targetFormat:r}),Ae=ic(i,{targetFormat:r});Ae.setVisible(!1);const We=lc(i,{targetFormat:r});We.setVisible(!1);const qe=as(e,a),Le=s&&Ye(e.canvas)?mc(e.canvas,qe):null;let Ne={source:"mouse",x:0,y:0,gridX:0,gridY:0,isInGrid:!1,hasPointer:!1},$e=null,Ue;const et=new Set;let Oe=null;const at=(g,A)=>{const S=Array.from(et);for(const E of S)E(g,A)},ke=(g,A)=>{const S=g!==null&&Number.isFinite(g)?g:null;$e===S&&Ue===A||($e=S,Ue=A,at($e,Ue))},ze=()=>{var g;(g=n==null?void 0:n.onRequestRender)==null||g.call(n)},pt=g=>g?Number.isFinite(g.start)&&Number.isFinite(g.end)&&g.start<=0&&g.end>=100:!0,Ze=()=>{V!==null&&(cancelAnimationFrame(V),V=null),re!==null&&(clearTimeout(re),re=null),Z=!1},st=()=>{ce!==null&&(clearTimeout(ce),ce=null)},At=()=>{var q;if(ne.size===0)return!1;Ce.clear();const g=(ie==null?void 0:ie.getRange())??null,A=pt(g),S=a.autoScroll===!0&&ie!=null&&a.xAxis.min==null&&a.xAxis.max==null,E=Zt(a,G),W=g?jt(E,g):null;let O=!1;for(const[k,H]of ne){if(H.length===0)continue;const J=a.series[k];if(!(!J||J.type==="pie")){if(O=!0,J.type==="candlestick"){let j=U[k];if(!j){const me=J.rawData??J.data;j=me.length===0?[]:me.slice(),U[k]=j,G[k]=J.rawBounds??null}const pe=H;j.push(...pe),G[k]=Nl(G[k],pe)}else{let j=U[k];if(!j){const me=J.rawData??J.data;j=me.length===0?[]:me.slice(),U[k]=j,G[k]=J.rawBounds??Di(j)}const pe=H;if(J.type==="line"&&J.sampling==="none"&&A&&Se[k]==="fullRawLine")try{he.appendSeries(k,pe),Ce.add(k)}catch{}j.push(...pe),G[k]=Fl(G[k],pe)}X[k]=null}}if(ne.clear(),!O)return!1;if(ie){const k=Oi(),H=ie;(q=H.setSpanConstraints)==null||q.call(H,k.minSpan,k.maxSpan)}if(S&&g&&W){const k=g;if(k.end>=99.5){const H=k.end-k.start,J=ie;J.setRangeAnchored?J.setRangeAnchored(100-H,100,"end"):ie.setRange(100-H,100)}else{const H=Zt(a,G),J=H.max-H.min;if(Number.isFinite(J)&&J>0){const j=(W.min-H.min)/J*100,pe=(W.max-H.min)/J*100,me=Math.max(0,Math.min(100,j)),Be=Math.max(0,Math.min(100,pe));ie.setRange(me,Be)}}}ki();const $=(ie==null?void 0:ie.getRange())??null;return($==null||pt($))&&(_=D),!0},Bt=g=>{if(f)return;const A=(g==null?void 0:g.requestRenderAfter)??!0,S=At(),E=(ie==null?void 0:ie.getRange())??null,W=pt(E),O=E!=null&&!W;let $=!1;Y?(Y=!1,st(),!E||W?_=D:ci(),$=!0):S&&O&&(Y=!1,st(),ci(),$=!0),(S||$)&&A&&ze()},Gt=g=>{f||Z||(V!==null&&(cancelAnimationFrame(V),V=null),re!==null&&(clearTimeout(re),re=null),Z=!0,V=requestAnimationFrame(()=>{if(V=null,f){Ze();return}re!==null&&(clearTimeout(re),re=null),Z=!1,Bt()}),re=(typeof self<"u"?self:window).setTimeout(()=>{if(f){Ze();return}Z&&(V!==null&&(cancelAnimationFrame(V),V=null),Z=!1,re=null,Bt())},16))},vn=()=>{f||(st(),Y=!1,ce=(typeof self<"u"?self:window).setTimeout(()=>{ce=null,!f&&(Y=!0,Gt())},100))},an=(g,A)=>{let S,E;if(Ye(g)){const $=g.getBoundingClientRect();if(!($.width>0)||!($.height>0))return null;S=$.width,E=$.height}else{const $=e.devicePixelRatio??1;if(console.log("[getPlotSizeCssPx] OffscreenCanvas dimensions:",{canvasWidth:g.width,canvasHeight:g.height,dpr:$,calculatedCssWidth:g.width/$,calculatedCssHeight:g.height/$}),S=g.width/$,E=g.height/$,!(S>0)||!(E>0))return null}const W=S-A.left-A.right,O=E-A.top-A.bottom;return!(W>0)||!(O>0)?null:{plotWidthCss:W,plotHeightCss:O}},mu=(g,A)=>{const S=e.canvas;if(!S)return null;const E=an(S,g);if(!E)return null;const W=kn().domain(A.xDomain.min,A.xDomain.max).range(0,E.plotWidthCss),O=kn().domain(A.yDomain.min,A.yDomain.max).range(E.plotHeightCss,0),$={xScale:W,yScale:O,plotWidthCss:E.plotWidthCss,plotHeightCss:E.plotHeightCss};return console.log("[computeInteractionScalesGridCssPx] Computed interaction scales:",{canvasType:Ye(S)?"HTMLCanvasElement":"OffscreenCanvas",plotWidthCss:$.plotWidthCss,plotHeightCss:$.plotHeightCss,xDomain:A.xDomain,yDomain:A.yDomain,xRange:[0,E.plotWidthCss],yRange:[E.plotHeightCss,0]}),$},oi=(g,A,S)=>{const E=a.series[g],{x:W,y:O}=wt(S);return{seriesName:(E==null?void 0:E.name)??"",seriesIndex:g,dataIndex:A,value:[W,O],color:(E==null?void 0:E.color)??"#888"}},du=(g,A,S)=>{const E=a.series[g];return ft(S)?{seriesName:(E==null?void 0:E.name)??"",seriesIndex:g,dataIndex:A,value:[S[0],S[1],S[2],S[3],S[4]],color:(E==null?void 0:E.color)??"#888"}:{seriesName:(E==null?void 0:E.name)??"",seriesIndex:g,dataIndex:A,value:[S.timestamp,S.open,S.close,S.low,S.high],color:(E==null?void 0:E.color)??"#888"}},Wi=(g,A,S,E,W)=>{const O=.5*Math.min(E,W);if(!(O>0))return null;for(let $=a.series.length-1;$>=0;$--){const q=g[$];if(q.type!=="pie")continue;const k=q,H=Dl(k.center,E,W),J=bs(k.radius,O),j=jc(A,S,{seriesIndex:$,series:k},H,J);if(j)return j}return null},$i=(g,A,S,E)=>{for(let W=g.length-1;W>=0;W--){const O=g[W];if(O.type!=="candlestick")continue;const $=O,q=Hc($,$.data,E.xScale,E.plotWidthCss),k=Zc([$],A,S,E.xScale,E.yScale,q);if(!k)continue;return{params:du(W,k.dataIndex,k.point),match:{point:k.point},seriesIndex:W}}return null},hu=g=>{if(Ne={source:"mouse",x:g.x,y:g.y,gridX:g.gridX,gridY:g.gridY,isInGrid:g.isInGrid,hasPointer:!0},g.isInGrid&&Oe){const A=Oe.xScale.invert(g.gridX);ke(Number.isFinite(A)?A:null,"mouse")}else g.isInGrid||ke(null,"mouse");Ae.setVisible(g.isInGrid),K(g.isInGrid?g.x:null),ee(g.isInGrid?g:null),ze()},pu=g=>{Ne.source==="mouse"&&(Ne={...Ne,isInGrid:!1,hasPointer:!1},Ae.setVisible(!1),be(),K(null),ee(null),ke(null,"mouse"),ze())};Le&&(Le.on("mousemove",hu),Le.on("mouseleave",pu));let ie=null,Je=null,Et=null,Kt=null;const ai=new Set,bu=g=>{const A=Array.from(ai);for(const S of A)S(g)},gu=g=>{var $,q;const A=($=g.dataZoom)==null?void 0:$.find(k=>(k==null?void 0:k.type)==="inside"),S=(q=g.dataZoom)==null?void 0:q.find(k=>(k==null?void 0:k.type)==="slider"),E=A??S;if(!E)return null;const W=Number.isFinite(E.start)?E.start:0,O=Number.isFinite(E.end)?E.end:100;return{start:W,end:O,hasInside:!!A}},wn=g=>Math.min(100,Math.max(0,g)),yu=g=>{let A=null,S=null;const E=g.dataZoom??[];for(const W of E)if(W&&!(W.type!=="inside"&&W.type!=="slider")){if(Number.isFinite(W.minSpan)){const O=wn(W.minSpan);A=A==null?O:Math.max(A,O)}if(Number.isFinite(W.maxSpan)){const O=wn(W.maxSpan);S=S==null?O:Math.min(S,O)}}return{minSpan:A??void 0,maxSpan:S??void 0}},xu=()=>{if(a.xAxis.type==="category")return null;let g=0;for(let S=0;S<a.series.length;S++){const E=a.series[S];if(E.type==="pie")continue;if(E.type==="candlestick"){const O=U[S]??E.rawData??E.data;g=Math.max(g,O.length);continue}const W=U[S]??E.rawData??E.data;g=Math.max(g,W.length)}if(g<2)return null;const A=100/(g-1);return Number.isFinite(A)?wn(A):null},Oi=()=>{const g=yu(a),A=xu(),S=Number.isFinite(g.minSpan)?wn(g.minSpan):A??.5,E=Number.isFinite(g.maxSpan)?wn(g.maxSpan):100;return{minSpan:S,maxSpan:E}},Bs=()=>{var A;const g=gu(a);if(!g){Je==null||Je.dispose(),Je=null,Et==null||Et(),Et=null,ie=null,Kt=null;return}if(ie){const S=Oi(),E=ie;(A=E.setSpanConstraints)==null||A.call(E,S.minSpan,S.maxSpan),(Kt==null||Kt.start!==g.start||Kt.end!==g.end)&&(ie.setRange(g.start,g.end),Kt={start:g.start,end:g.end})}else{const S=Oi();ie=Fc(g.start,g.end,S),Kt={start:g.start,end:g.end},Et=ie.onChange(E=>{vu(),ze(),vn(),bu({start:E.start,end:E.end})})}g.hasInside&&Le?Je||(Je=yc(Le,ie),Je.enable()):(Je==null||Je.dispose(),Je=null)},Es=()=>{const g=a.series.length;U=new Array(g).fill(null),G=new Array(g).fill(null),ne.clear();for(let A=0;A<g;A++){const S=a.series[A];if(S.type==="pie")continue;if(S.type==="candlestick"){const O=S.rawData??S.data,$=O.length===0?[]:O.slice();U[A]=$,G[A]=S.rawBounds??null;continue}const E=S.rawData??S.data,W=E.length===0?[]:E.slice();U[A]=W,G[A]=S.rawBounds??Di(W)}},ki=()=>{const g=new Array(a.series.length);for(let A=0;A<a.series.length;A++){const S=a.series[A];if(S.type==="pie"){g[A]=S;continue}if(S.type==="candlestick"){const $=U[A]??S.rawData??S.data,q=G[A]??S.rawBounds??void 0,k=S.sampling==="ohlc"&&$.length>S.samplingThreshold?hi($,S.samplingThreshold):$;g[A]={...S,rawData:$,rawBounds:q,data:k};continue}const E=U[A]??S.rawData??S.data,W=G[A]??S.rawBounds??void 0,O=tn(E,S.sampling,S.samplingThreshold);g[A]={...S,rawData:E,rawBounds:W,data:O}}D=g};function vu(){const g=(ie==null?void 0:ie.getRange())??null,A=Zt(a,G),S=jt(A,g);if(g==null||Number.isFinite(g.start)&&Number.isFinite(g.end)&&g.start<=0&&g.end>=100){_=D;return}const W=new Array(D.length);for(let O=0;O<D.length;O++){const $=D[O];if($.type==="pie"){W[O]=$;continue}const q=X[O];if(q&&S.min>=q.cachedRange.min&&S.max<=q.cachedRange.max){$.type==="candlestick"?W[O]={...$,data:ti(q.data,S.min,S.max)}:W[O]={...$,data:Qn(q.data,S.min,S.max)};continue}$.type==="candlestick"?W[O]={...$,data:ti($.data,S.min,S.max)}:W[O]={...$,data:Qn($.data,S.min,S.max)}}_=W}function ci(){const g=(ie==null?void 0:ie.getRange())??null,A=Zt(a,G),S=jt(A,g),O=(S.max-S.min)*.1,$=S.min-O,q=S.max+O,k=2,H=2e5,J=32,j=Math.max(.001,Math.min(1,S.spanFraction)),pe=new Array(D.length);for(let me=0;me<D.length;me++){const Be=D[me];if(Be.type==="pie"){pe[me]=Be;continue}if(g==null||Number.isFinite(g.start)&&Number.isFinite(g.end)&&g.start<=0&&g.end>=100){pe[me]=Be;continue}if(Be.type==="candlestick"){const ot=U[me]??Be.rawData??Be.data,gt=ti(ot,$,q),Pe=Be.sampling,en=Be.samplingThreshold,Fn=Number.isFinite(en)?Math.max(1,en|0):1,li=Math.min(H,Math.max(k,Fn*J)),Nn=Nt(Math.round(Fn/j),k,li),Mn=Pe==="ohlc"&>.length>Nn?hi(gt,Nn):gt;X[me]={data:Mn,cachedRange:{min:$,max:q},timestamp:Date.now()};const ui=ti(Mn,S.min,S.max);pe[me]={...Be,data:ui};continue}const Qe=U[me]??Be.rawData??Be.data,Q=Qn(Qe,$,q),Ee=Be.sampling,de=Be.samplingThreshold,Ct=Number.isFinite(de)?Math.max(1,de|0):1,Qt=Math.min(H,Math.max(k,Ct*J)),He=Nt(Math.round(Ct/j),k,Qt),cn=tn(Q,Ee,He);X[me]={data:cn,cachedRange:{min:$,max:q},timestamp:Date.now()};const ln=Qn(cn,S.min,S.max);pe[me]={...Be,data:ln}}_=pe}Es(),ki(),Bs(),ci(),X=new Array(a.series.length).fill(null);const bt=[],Mt=[],Dt=[],Jt=[],St=[],Ut=[],Vi=ta(i,{targetFormat:r}),Ds=g=>{for(;bt.length>g;){const A=bt.pop();A==null||A.dispose()}for(;bt.length<g;)bt.push(_o(i,{targetFormat:r}))},Us=g=>{for(;Mt.length>g;){const A=Mt.pop();A==null||A.dispose()}for(;Mt.length<g;)Mt.push(zo(i,{targetFormat:r}))},Ls=g=>{for(;Dt.length>g;){const A=Dt.pop();A==null||A.dispose()}for(;Dt.length<g;)Dt.push(ua(i,{targetFormat:r}))},_s=g=>{for(;Jt.length>g;){const A=Jt.pop();A==null||A.dispose()}for(;Jt.length<g;)Jt.push(wa(i,{targetFormat:r}))},Gs=g=>{for(;St.length>g;){const A=St.pop();A==null||A.dispose()}for(;St.length<g;)St.push(Pa(i,{targetFormat:r}))},Ws=g=>{for(;Ut.length>g;){const A=Ut.pop();A==null||A.dispose()}for(;Ut.length<g;)Ut.push(Oa(i,{targetFormat:r}))};Ds(a.series.length),Us(a.series.length),Ls(a.series.length),_s(a.series.length),Gs(a.series.length),Ws(a.series.length);const Wt=()=>{if(f)throw new Error("RenderCoordinator is disposed.")},$s=()=>{if(y)try{x.cancel(y)}catch{}y=null,d=1,h=null,w()},Os=(g,A)=>g.min===A.min&&g.max===A.max,wu=(g,A)=>{if(g.length!==A.length)return!0;for(let S=0;S<g.length;S++){const E=g[S],W=A[S];if(E.type!==W.type)return!0;if(E.type==="pie"){const O=E,$=W;if(O.data!==$.data||O.data.length!==$.data.length)return!0}else{const O=E,$=W,q=O.rawData??O.data,k=$.rawData??$.data;if(q!==k||q.length!==k.length)return!0}}return!1},Fu=g=>{var Qe;Wt();const A=(ie==null?void 0:ie.getRange())??null,S=(()=>{if(h&&y){try{x.update(performance.now())}catch{}return T(h,d,A)}const Q=Zt(a,G),Ee=jt(Q,A),de=Li(a,G);return{xBaseDomain:Q,xVisibleDomain:{min:Ee.min,max:Ee.max},yBaseDomain:de,series:_}})();$s();const E=wu(a.series,g.series);if(a=g,D=g.series,_=g.series,Se=new Array(g.series.length).fill("unknown"),X=new Array(g.series.length).fill(null),l==null||l.update(g.series,g.theme),st(),Y=!1,Ze(),Es(),ki(),Bs(),ci(),o){const Q=((Qe=a.tooltip)==null?void 0:Qe.show)!==!1;Q&&!fe&&(fe=jr(o),oe=null,ve=null,we=null),!Q&&fe&&be()}else be();const W=g.series.length;if(Ds(W),Us(W),Ls(W),_s(W),Gs(W),Ws(W),W<v)for(let Q=W;Q<v;Q++)he.removeSeries(Q);if(v=W,a.animation===!1&&M==="running"&&(p.cancelAll(),F=null,M="done",C=1),a.animation===!1){$s();return}const O=(ie==null?void 0:ie.getRange())??null,$=Zt(a,G),q=jt($,O),k=Li(a,G),H=_,J=!Os(S.xBaseDomain,$)||!Os(S.yBaseDomain,k);if(!(b&&(J||E)))return;const pe=Ol(a.animation);if(!pe)return;h={from:{xBaseDomain:S.xBaseDomain,xVisibleDomain:S.xVisibleDomain,yBaseDomain:S.yBaseDomain,series:S.series},to:{xBaseDomain:$,xVisibleDomain:{min:q.min,max:q.max},yBaseDomain:k,series:H}},w();const me=pe.delayMs+pe.durationMs,Be=Q=>{const Ee=Ft(Q);if(!(me>0))return 1;const de=Ee*me;if(de<=pe.delayMs)return 0;if(!(pe.durationMs>0))return 1;const Ct=(de-pe.delayMs)/pe.durationMs;return pe.easing(Ct)};d=0;const Xe=x.animate(0,1,me,Be,Q=>{f||y!==Xe||(d=Ft(Q),d<1&&ze())},()=>{f||y!==Xe||(d=1,h=null,y=null,w())});y=Xe},Nu=(g,A)=>{if(Wt(),!Number.isFinite(g)||g<0||g>=a.series.length||!A||A.length===0)return;if(a.series[g].type==="pie"){B.has(g)||(B.add(g),console.warn(`RenderCoordinator.appendData(${g}, ...): pie series are not supported by streaming append.`));return}const E=ne.get(g);E?E.push(...A):ne.set(g,Array.from(A)),Gt()},Mu=g=>{switch(g.type){case"area":return!0;case"line":return g.areaStyle!=null;case"bar":return!1;case"scatter":return!1;case"pie":return!1;case"candlestick":return!1;default:return Ei(g)}};return{setOptions:Fu,appendData:Nu,getInteractionX:()=>$e,setInteractionX:(g,A)=>{Wt();const S=g!==null&&Number.isFinite(g)?g:null;Ne={...Ne,source:S===null?"mouse":"sync"},ke(S,A),S===null&&Ne.hasPointer===!1&&(Ae.setVisible(!1),We.setVisible(!1),se(),K(null)),ze()},onInteractionXChange:g=>(Wt(),et.add(g),()=>{et.delete(g)}),getZoomRange:()=>(ie==null?void 0:ie.getRange())??null,setZoomRange:(g,A)=>{Wt(),ie&&ie.setRange(g,A)},onZoomRangeChange:g=>(Wt(),ai.add(g),()=>{ai.delete(g)}),handlePointerEvent:g=>{if(Wt(),s||!e.canvas||!Number.isFinite(g.x)||!Number.isFinite(g.y)||!Number.isFinite(g.gridX)||!Number.isFinite(g.gridY)||!Number.isFinite(g.plotWidthCss)||!Number.isFinite(g.plotHeightCss))return;const{type:S,x:E,y:W,gridX:O,gridY:$,plotWidthCss:q,plotHeightCss:k,isInGrid:H}=g;if(S==="leave"){Ne={...Ne,isInGrid:!1,hasPointer:!1},Ae.setVisible(!1),oe=null,ve=null,we=null,se(),K(null),ee(null),ke(null,"mouse"),ze();return}if(S==="move"){Ne={source:"mouse",x:E,y:W,gridX:O,gridY:$,isInGrid:H,hasPointer:!0},ze();return}if(S==="click"){if(!(n!=null&&n.onClickData))return;let J=null,j=null,pe=null;if(H&&Oe){if(j=Wi(_,O,$,q,k),!j){const me=$i(_,O,$,Oe);me&&(pe={seriesIndex:me.seriesIndex,dataIndex:me.params.dataIndex,point:me.match.point})}!j&&!pe&&(J=Ci(_,O,$,Oe.xScale,Oe.yScale,20))}n.onClickData({x:E,y:W,gridX:O,gridY:$,isInGrid:H,nearest:J,pieSlice:j,candlestick:pe});return}if(S==="wheel"){if(!H||!ie)return;const J=g.deltaX??0,j=g.deltaY??0,pe=g.deltaMode??0,me=(ot,gt)=>{if(!Number.isFinite(ot)||ot===0)return 0;switch(pe){case 1:return ot*16;case 2:return ot*(Number.isFinite(gt)&>>0?gt:800);default:return ot}},Be=me(j,k),Xe=me(J,q);if(Math.abs(Xe)>Math.abs(Be)&&Xe!==0){const{start:ot,end:gt}=ie.getRange(),Pe=gt-ot;if(!Number.isFinite(Pe)||Pe===0)return;const en=Xe/q*Pe;if(!Number.isFinite(en)||en===0)return;ie.pan(en);return}if(Be===0)return;const Qe=Math.abs(Be);if(!Number.isFinite(Qe)||Qe===0)return;const Q=Math.min(Qe,200),de=Math.exp(Q*.002);if(!(de>1))return;const{start:Ct,end:Qt}=ie.getRange(),He=Qt-Ct;if(!Number.isFinite(He)||He===0)return;const cn=Math.min(1,Math.max(0,O/q)),ln=Math.min(100,Math.max(0,Ct+cn*He));Be<0?ie.zoomIn(ln,de):ie.zoomOut(ln,de),ze();return}},render:()=>{var Fn,li,Nn,Mn,ui,Vs,zs,Xs,Hs;if(Wt(),!e.canvasContext||!e.canvas)return;(ne.size>0||Y)&&(Ze(),Bt({requestRenderAfter:!1}));const g=a.series.some(L=>L.type!=="pie"),A=_;if(M!=="done"){const L=$l(a.animation),z=(()=>{for(let ye=0;ye<A.length;ye++){const ae=A[ye];switch(ae.type){case"pie":{if(ae.data.some(le=>typeof(le==null?void 0:le.value)=="number"&&Number.isFinite(le.value)&&le.value>0))return!0;break}case"line":case"area":case"bar":case"scatter":case"candlestick":{if(ae.data.length>0)return!0;break}default:Ei(ae)}}return!1})();if(M==="pending"&&L&&z){const ye=L.delayMs+L.durationMs,ae=le=>{const Te=Ft(le);if(!(ye>0))return 1;const ge=Te*ye;if(ge<=L.delayMs)return 0;if(!(L.durationMs>0))return 1;const xe=(ge-L.delayMs)/L.durationMs;return L.easing(xe)};C=0,M="running",F=p.animate(0,1,ye,ae,le=>{f||M!=="running"||(C=Ft(le),C<1&&ze())},()=>{f||(M="done",C=1,F=null)})}p.update(performance.now())}h!==null&&y&&x.update(performance.now());const S=as(e,a);Le==null||Le.updateGridArea(S);const E=(ie==null?void 0:ie.getRange())??null,W=h?Ft(d):1,O=h?Kn(h.from.xBaseDomain,h.to.xBaseDomain,W):Zt(a,G),$=h?Kn(h.from.yBaseDomain,h.to.yBaseDomain,W):Li(a,G),q=jt(O,E),k=Cl(S),H=ls(S),J=kn().domain(q.min,q.max).range(k.left,k.right),j=kn().domain($.min,$.max).range(k.bottom,k.top),pe=S.devicePixelRatio,me=e.canvas?rs(e.canvas,pe):0,Be=Math.abs(q.max-q.min);let Xe=gn,Qe=[];if(a.xAxis.type==="time"){const L=Wl({axisMin:Yn(a.xAxis.min),axisMax:Yn(a.xAxis.max),xScale:J,plotClipLeft:k.left,plotClipRight:k.right,canvasCssWidth:me,visibleRangeMs:Be,measureCtx:u,measureCache:m??void 0,fontSize:a.theme.fontSize,fontFamily:a.theme.fontFamily||"sans-serif"});Xe=L.tickCount,Qe=L.tickValues}else{const L=vt(a.xAxis.min)??J.invert(k.left),z=vt(a.xAxis.max)??J.invert(k.right);Qe=ni(L,z,Xe)}const Q=mu(S,{xDomain:{min:q.min,max:q.max},yDomain:$});Oe=Q;const Ee=h&&W<1?P(h.from.series,h.to.series,W,N):_;if(Ne.source==="mouse"&&Ne.hasPointer&&Ne.isInGrid&&Q){const L=Q.xScale.invert(Ne.gridX);ke(Number.isFinite(L)?L:null,"mouse")}let de=Ne;if(Ne.source==="sync")if($e===null||!Q)de={...Ne,hasPointer:!1,isInGrid:!1};else{const L=Q.xScale.scale($e),z=Q.plotHeightCss*.5,ye=Number.isFinite(L)&&Number.isFinite(z)&&L>=0&&L<=Q.plotWidthCss&&z>=0&&z<=Q.plotHeightCss;de={source:"sync",gridX:Number.isFinite(L)?L:0,gridY:Number.isFinite(z)?z:0,x:S.left+(Number.isFinite(L)?L:0),y:S.top+(Number.isFinite(z)?z:0),isInGrid:ye,hasPointer:ye}}if(te.prepare(S,{color:a.theme.gridLineColor}),g&&(Re.prepare(a.xAxis,J,"x",S,a.theme.axisLineColor,a.theme.axisTickColor,Xe),Fe.prepare(a.yAxis,j,"y",S,a.theme.axisLineColor,a.theme.axisTickColor,gn)),de.hasPointer&&de.isInGrid){const L={showX:!0,showY:de.source!=="sync",color:cs(a.theme.axisLineColor,.6),lineWidth:pl};Ae.prepare(de.x,de.y,S,L),Ae.setVisible(!0),K(de.x)}else Ae.setVisible(!1),K(null);if(de.source==="mouse"&&de.hasPointer&&de.isInGrid)if(Q){const L=Ci(Ee,de.gridX,de.gridY,Q.xScale,Q.yScale);if(L){const{x:z,y:ye}=wt(L.point),ae=Q.xScale.scale(z),le=Q.yScale.scale(ye);if(Number.isFinite(ae)&&Number.isFinite(le)){const Te=S.left+ae,ge=S.top+le,xe=ls(S),Me={centerDeviceX:Te*S.devicePixelRatio,centerDeviceY:ge*S.devicePixelRatio,devicePixelRatio:S.devicePixelRatio,canvasWidth:S.canvasWidth,canvasHeight:S.canvasHeight,scissor:xe},De=((Fn=a.series[L.seriesIndex])==null?void 0:Fn.color)??"#888";We.prepare(Me,De,bl),We.setVisible(!0)}else We.setVisible(!1)}else We.setVisible(!1)}else We.setVisible(!1);else We.setVisible(!1);if(de.hasPointer&&de.isInGrid&&((li=a.tooltip)==null?void 0:li.show)!==!1){const L=e.canvas;if(console.log("[Tooltip block] State check:",{hasInteractionScales:!!Q,domOverlaysEnabled:s,hasCanvas:!!L,canvasType:L?Ye(L)?"HTMLCanvasElement":"OffscreenCanvas":"null",interactionScales:Q?{plotWidthCss:Q.plotWidthCss,plotHeightCss:Q.plotHeightCss}:null}),Q&&(!s||L&&Ye(L))){const z=(Nn=a.tooltip)==null?void 0:Nn.formatter,ye=((Mn=a.tooltip)==null?void 0:Mn.trigger)??"item",ae=Ye(L)?L.offsetLeft+de.x:de.x,le=Ye(L)?L.offsetTop+de.y:de.y;if(de.source==="sync"){const Te=Yr(Ee,de.gridX,Q.xScale);if(Te.length===0)be();else if(ye==="axis"){const ge=Te.map(Me=>oi(Me.seriesIndex,Me.dataIndex,Me.point)),xe=z?z(ge):Ri(ge);xe&&(xe!==oe||ae!==ve||le!==we)?(oe=xe,ve=ae,we=le,ue(ae,le,xe,ge)):xe||be()}else{const ge=Te[0],xe=oi(ge.seriesIndex,ge.dataIndex,ge.point),Me=z?z(xe):bn(xe);Me&&(Me!==oe||ae!==ve||le!==we)?(oe=Me,ve=ae,we=le,ue(ae,le,Me,xe)):Me||be()}}else if(ye==="axis"){const Te=Wi(Ee,de.gridX,de.gridY,Q.plotWidthCss,Q.plotHeightCss);if(Te){const ge={seriesName:Te.slice.name,seriesIndex:Te.seriesIndex,dataIndex:Te.dataIndex,value:[0,Te.slice.value],color:Te.slice.color},xe=z?z([ge]):bn(ge);xe&&(xe!==oe||ae!==ve||le!==we)?(oe=xe,ve=ae,we=le,ue(ae,le,xe,[ge])):xe||be()}else{const ge=$i(Ee,de.gridX,de.gridY,Q),xe=Yr(Ee,de.gridX,Q.xScale);if(xe.length===0)if(ge){const Me=[ge.params],De=z?z(Me):Ri(Me);if(De){const _e=_i(ge.match,Q.xScale,Q.yScale,S,L),tt=(_e==null?void 0:_e.x)??ae,yt=(_e==null?void 0:_e.y)??le;(De!==oe||tt!==ve||yt!==we)&&(oe=De,ve=tt,we=yt,ue(tt,yt,De,Me))}else be()}else be();else{const Me=xe.map(_e=>oi(_e.seriesIndex,_e.dataIndex,_e.point));ge&&Me.push(ge.params);const De=z?z(Me):Ri(Me);if(De){let _e=ae,tt=le;if(ge){const yt=_i(ge.match,Q.xScale,Q.yScale,S,L);yt&&(_e=yt.x,tt=yt.y)}(De!==oe||_e!==ve||tt!==we)&&(oe=De,ve=_e,we=tt,ue(_e,tt,De,Me))}else be()}}}else{const Te=Wi(Ee,de.gridX,de.gridY,Q.plotWidthCss,Q.plotHeightCss);if(Te){const ge={seriesName:Te.slice.name,seriesIndex:Te.seriesIndex,dataIndex:Te.dataIndex,value:[0,Te.slice.value],color:Te.slice.color},xe=z?z(ge):bn(ge);xe&&(xe!==oe||ae!==ve||le!==we)?(oe=xe,ve=ae,we=le,ue(ae,le,xe,ge)):xe||be()}else{const ge=$i(Ee,de.gridX,de.gridY,Q);if(ge){const Me=z?z(ge.params):bn(ge.params);if(Me){const De=_i(ge.match,Q.xScale,Q.yScale,S,L),_e=(De==null?void 0:De.x)??ae,tt=(De==null?void 0:De.y)??le;(Me!==oe||_e!==ve||tt!==we)&&(oe=Me,ve=_e,we=tt,ue(_e,tt,Me,ge.params))}else be();return}const xe=Ci(Ee,de.gridX,de.gridY,Q.xScale,Q.yScale);if(!xe)be();else{const Me=oi(xe.seriesIndex,xe.dataIndex,xe.point),De=z?z(Me):bn(Me);De&&(De!==oe||ae!==ve||le!==we)?(oe=De,ve=ae,we=le,ue(ae,le,De,Me)):De||be()}}}}else be()}else be();const Ct=a.yAxis.min??$.min,Qt=[],He=M==="running"?Ft(C):1;for(let L=0;L<Ee.length;L++){const z=Ee[L];switch(z.type){case"area":{const ye=z.baseline??Ct;bt[L].prepare(z,z.data,J,j,ye);break}case"line":{Ce.has(L)||he.setSeries(L,z.data);const ye=he.getSeriesBuffer(L);Mt[L].prepare(z,ye,J,j);const ae=(ie==null?void 0:ie.getRange())??null;if((ae==null||Number.isFinite(ae.start)&&Number.isFinite(ae.end)&&ae.start<=0&&ae.end>=100)&&z.sampling==="none"?Se[L]="fullRawLine":Se[L]="other",z.areaStyle){const Te={type:"area",name:z.name,rawData:z.data,data:z.data,color:z.areaStyle.color,areaStyle:z.areaStyle,sampling:z.sampling,samplingThreshold:z.samplingThreshold};bt[L].prepare(Te,Te.data,J,j,Ct)}break}case"bar":{Qt.push(z);break}case"scatter":{if(z.mode==="density"){const ye=z.rawData??z.data,ae=Tl(ye,q.min,q.max);Ce.has(L)||he.setSeries(L,ye);const le=he.getSeriesBuffer(L),Te=he.getSeriesPointCount(L);Jt[L].prepare(z,le,Te,ae.start,ae.end,J,j,S,z.rawBounds),Se[L]="other"}else{const ye=He<1?{...z,color:cs(z.color,He)}:z;Dt[L].prepare(ye,z.data,J,j,S)}break}case"pie":{if(He<1){const ye=e.canvas,ae=(Q==null?void 0:Q.plotWidthCss)??(ye&&Ye(ye)?(ui=an(ye,S))==null?void 0:ui.plotWidthCss:null),le=(Q==null?void 0:Q.plotHeightCss)??(ye&&Ye(ye)?(Vs=an(ye,S))==null?void 0:Vs.plotHeightCss:null),Te=typeof ae=="number"&&typeof le=="number"?.5*Math.min(ae,le):0;if(Te>0){const ge=bs(z.radius,Te),xe=Math.max(0,ge.inner)*He,Me=Math.max(xe,ge.outer)*He,De={...z,radius:[xe,Me]};St[L].prepare(De,S);break}}St[L].prepare(z,S);break}case"candlestick":{Ut[L].prepare(z,z.data,J,j,S,a.theme.backgroundColor);break}default:Ei(z)}}const cn=He<1?Vl(j,k,Qt,He):j;Vi.prepare(Qt,he,J,cn,S);const ln=e.canvasContext.getCurrentTexture().createView(),ot=i.createCommandEncoder({label:"renderCoordinator/commandEncoder"}),gt=ho(a.theme.backgroundColor,{r:0,g:0,b:0,a:1});for(let L=0;L<Ee.length;L++){const z=Ee[L];z.type==="scatter"&&z.mode==="density"&&Jt[L].encodeCompute(ot)}const Pe=ot.beginRenderPass({label:"renderCoordinator/renderPass",colorAttachments:[{view:ln,clearValue:gt,loadOp:"clear",storeOp:"store"}]});te.render(Pe);for(let L=0;L<Ee.length;L++)Ee[L].type==="pie"&&St[L].render(Pe);for(let L=0;L<Ee.length;L++)if(Mu(Ee[L]))if(He<1){const z=Nt(Math.floor(H.w*He),0,H.w);z>0&&H.h>0&&(Pe.setScissorRect(H.x,H.y,z,H.h),bt[L].render(Pe),Pe.setScissorRect(0,0,S.canvasWidth,S.canvasHeight))}else Pe.setScissorRect(H.x,H.y,H.w,H.h),bt[L].render(Pe),Pe.setScissorRect(0,0,S.canvasWidth,S.canvasHeight);H.w>0&&H.h>0&&(Pe.setScissorRect(H.x,H.y,H.w,H.h),Vi.render(Pe),Pe.setScissorRect(0,0,S.canvasWidth,S.canvasHeight));for(let L=0;L<Ee.length;L++)Ee[L].type==="candlestick"&&Ut[L].render(Pe);for(let L=0;L<Ee.length;L++){const z=Ee[L];z.type==="scatter"&&(z.mode==="density"?Jt[L].render(Pe):Dt[L].render(Pe))}for(let L=0;L<Ee.length;L++)if(Ee[L].type==="line")if(He<1){const z=Nt(Math.floor(H.w*He),0,H.w);z>0&&H.h>0&&(Pe.setScissorRect(H.x,H.y,z,H.h),Mt[L].render(Pe),Pe.setScissorRect(0,0,S.canvasWidth,S.canvasHeight))}else Pe.setScissorRect(H.x,H.y,H.w,H.h),Mt[L].render(Pe),Pe.setScissorRect(0,0,S.canvasWidth,S.canvasHeight);if(We.render(Pe),g&&(Re.render(Pe),Fe.render(Pe)),Ae.render(Pe),Pe.end(),i.queue.submit([ot.finish()]),b=!0,g&&(c&&o||!s&&(n==null?void 0:n.onAxisLabelsUpdate))){const L=e.canvas,z=rs(L,e.devicePixelRatio??1),ye=dl(L,e.devicePixelRatio??1);if(z<=0||ye<=0)return;const ae=Ye(L)?L.offsetLeft:0,le=Ye(L)?L.offsetTop:0,Te=Jn(k.left,z),ge=Jn(k.right,z),xe=Ui(k.top,ye),Me=Ui(k.bottom,ye);c==null||c.clear();const De=[],_e=[],tt=a.xAxis.tickLength??ss,yt=Me+tt+Ai+a.theme.fontSize*.5,Ys=a.xAxis.type==="time",Su=(()=>{if(Ys)return null;const je=vt(a.xAxis.min)??J.invert(k.left),ct=vt(a.xAxis.max)??J.invert(k.right),$t=Xe===1?0:(ct-je)/(Xe-1);return gs($t)})();for(let je=0;je<Qe.length;je++){const ct=Qe[je],$t=J.scale(ct),Ot=Jn($t,z),It=Qe.length===1?"middle":je===0?"start":je===Qe.length-1?"end":"middle",nt=Ys?xs(ct,Be):ys(Su,ct);if(nt==null)continue;const Tt={axis:"x",text:nt,x:ae+Ot,y:le+yt,anchor:It,isTitle:!1};if(De.push(Tt),c){const Pt=c.addLabel(nt,ae+Ot,le+yt,{fontSize:a.theme.fontSize,color:a.theme.textColor,anchor:It});Vn(Pt,Tt,a.theme)}}const zi=gn,Cu=a.yAxis.tickLength??ss,Xi=vt(a.yAxis.min)??j.invert(k.bottom),qs=vt(a.yAxis.max)??j.invert(k.top),Iu=(qs-Xi)/(zi-1),Tu=gs(Iu),Hi=Te-Cu-Ai,Yi=[];for(let je=0;je<zi;je++){const ct=je/(zi-1),$t=Xi+ct*(qs-Xi),Ot=j.scale($t),It=Ui(Ot,ye),nt=ys(Tu,$t);if(nt==null)continue;const Tt={axis:"y",text:nt,x:ae+Hi,y:le+It,anchor:"end",isTitle:!1};if(_e.push(Tt),c){const Pt=c.addLabel(nt,ae+Hi,le+It,{fontSize:a.theme.fontSize,color:a.theme.textColor,anchor:"end"});Vn(Pt,Tt,a.theme),Yi.push(Pt)}}const qi=Qc(a.theme.fontSize),Zi=((zs=a.xAxis.name)==null?void 0:zs.trim())??"";if(Zi.length>0){const je=(Te+ge)/2,ct=yt+a.theme.fontSize*.5,It=((Xs=a.dataZoom)==null?void 0:Xs.some(Pt=>(Pt==null?void 0:Pt.type)==="slider"))??!1?ye-32:ye,nt=(ct+It)/2,Tt={axis:"x",text:Zi,x:ae+je,y:le+nt,anchor:"middle",isTitle:!0};if(De.push(Tt),c){const Pt=c.addLabel(Zi,ae+je,le+nt,{fontSize:qi,color:a.theme.textColor,anchor:"middle"});Vn(Pt,Tt,a.theme)}}const ji=((Hs=a.yAxis.name)==null?void 0:Hs.trim())??"";if(ji.length>0){const je=Yi.length===0?Sl(_e,a.theme.fontSize):Yi.reduce((nt,Tt)=>Math.max(nt,Tt.getBoundingClientRect().width),0),ct=(xe+Me)/2,Ot=Hi-je-Ai-qi*.5,It={axis:"y",text:ji,x:ae+Ot,y:le+ct,anchor:"middle",rotation:-90,isTitle:!0};if(_e.push(It),c){const nt=c.addLabel(ji,ae+Ot,le+ct,{fontSize:qi,color:a.theme.textColor,anchor:"middle",rotation:-90});Vn(nt,It,a.theme)}}!s&&(n!=null&&n.onAxisLabelsUpdate)&&n.onAxisLabelsUpdate(De,_e)}},dispose:()=>{if(!f){f=!0;try{F&&p.cancel(F),p.cancelAll()}catch{}F=null,M="done",C=1;try{y&&x.cancel(y),x.cancelAll()}catch{}y=null,d=1,h=null,Ze(),st(),Y=!1,ne.clear(),Je==null||Je.dispose(),Je=null,Et==null||Et(),Et=null,ie=null,Kt=null,ai.clear(),Le==null||Le.dispose(),Ae.dispose(),We.dispose();for(let g=0;g<bt.length;g++)bt[g].dispose();bt.length=0;for(let g=0;g<Mt.length;g++)Mt[g].dispose();Mt.length=0;for(let g=0;g<Dt.length;g++)Dt[g].dispose();Dt.length=0;for(let g=0;g<St.length;g++)St[g].dispose();St.length=0;for(let g=0;g<Ut.length;g++)Ut[g].dispose();Ut.length=0,Vi.dispose(),te.dispose(),Re.dispose(),Fe.dispose(),he.dispose(),fe==null||fe.dispose(),fe=null,l==null||l.dispose(),c==null||c.dispose()}}}}const Xl={left:60,right:20,top:40,bottom:40},ii=["#5470C6","#91CC75","#FAC858","#EE6666","#73C0DE","#3BA272","#FC8452","#9A60B4","#EA7CCC"],Fs={width:2,opacity:1},Ns={opacity:.25},dt={style:"classic",itemStyle:{upColor:"#22c55e",downColor:"#ef4444",upBorderColor:"#22c55e",downBorderColor:"#ef4444",borderWidth:1},barWidth:"80%",barMinWidth:1,barMaxWidth:50,sampling:"ohlc",samplingThreshold:5e3},ri={mode:"points",binSize:2,densityColormap:"viridis",densityNormalization:"log"},it={grid:Xl,xAxis:{type:"value"},yAxis:{type:"value"},autoScroll:!1,palette:ii},Hl={backgroundColor:"#1a1a2e",textColor:"#e0e0e0",axisLineColor:"rgba(224,224,224,0.35)",axisTickColor:"rgba(224,224,224,0.55)",gridLineColor:"rgba(255,255,255,0.1)",colorPalette:[...["#00E5FF","#FF2D95","#B026FF","#00F5A0","#FFD300","#FF6B00","#4D5BFF","#FF3D3D"]],fontFamily:'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:12},Yl={backgroundColor:"#ffffff",textColor:"#333333",axisLineColor:"rgba(0,0,0,0.35)",axisTickColor:"rgba(0,0,0,0.55)",gridLineColor:"rgba(0,0,0,0.1)",colorPalette:[...["#1F77B4","#FF7F0E","#2CA02C","#D62728","#9467BD","#8C564B","#E377C2","#17BECF"]],fontFamily:'system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"',fontSize:12};function Gi(e){return e==="dark"?Hl:Yl}const ql=e=>{if(!Array.isArray(e))return;const t=[];for(const n of e){if(n===null||typeof n!="object"||Array.isArray(n))continue;const i=n,r=i.type;if(r!=="inside"&&r!=="slider")continue;const s=i.xAxisIndex,o=i.start,c=i.end,l=i.minSpan,u=i.maxSpan,m=typeof s=="number"&&Number.isFinite(s)?s:void 0,f=typeof o=="number"&&Number.isFinite(o)?o:void 0,a=typeof c=="number"&&Number.isFinite(c)?c:void 0,v=typeof l=="number"&&Number.isFinite(l)?l:void 0,M=typeof u=="number"&&Number.isFinite(u)?u:void 0;t.push({type:r,xAxisIndex:m,start:f,end:a,minSpan:v,maxSpan:M})}return t},xn=e=>Array.isArray(e)?e.filter(t=>typeof t=="string").map(t=>t.trim()).filter(t=>t.length>0):[],Zl=e=>{const t=Gi("dark");if(typeof e=="string"){const c=e.trim().toLowerCase();return Gi(c==="light"?"light":"dark")}if(e===null||typeof e!="object"||Array.isArray(e))return t;const n=e,i=c=>{const l=n[c];if(typeof l!="string")return;const u=l.trim();return u.length>0?u:void 0},r=n.fontSize,s=typeof r=="number"&&Number.isFinite(r)?r:void 0,o=xn(n.colorPalette);return{backgroundColor:i("backgroundColor")??t.backgroundColor,textColor:i("textColor")??t.textColor,axisLineColor:i("axisLineColor")??t.axisLineColor,axisTickColor:i("axisTickColor")??t.axisTickColor,gridLineColor:i("gridLineColor")??t.gridLineColor,colorPalette:o.length>0?o:Array.from(t.colorPalette),fontFamily:i("fontFamily")??t.fontFamily,fontSize:s??t.fontSize}},Rt=e=>{if(typeof e!="string")return;const t=e.trim();return t.length>0?t:void 0},jl=e=>{if(typeof e!="string")return;const t=e.trim().toLowerCase();return t==="none"||t==="lttb"||t==="average"||t==="max"||t==="min"||t==="ohlc"?t:void 0},Kl=e=>{if(typeof e!="string")return;const t=e.trim().toLowerCase();return t==="points"||t==="density"?t:void 0},Jl=e=>{if(typeof e!="string")return;const t=e.trim().toLowerCase();return t==="linear"||t==="sqrt"||t==="log"?t:void 0},Ql=e=>{if(typeof e!="number"||!Number.isFinite(e))return;const t=Math.floor(e);return t>0?Math.max(1,t):void 0},eu=e=>{if(typeof e=="string"){const i=e.trim().toLowerCase();return i==="viridis"||i==="plasma"||i==="inferno"?i:void 0}if(!Array.isArray(e))return;if(e.length>0&&e.every(i=>typeof i=="string"&&i.length>0&&i===i.trim())){const i=e;return Object.isFrozen(i)||Object.freeze(i),i}const n=e.filter(i=>typeof i=="string").map(i=>i.trim()).filter(i=>i.length>0);if(n.length!==0)return Object.freeze(n),n},tu=e=>{if(typeof e!="string")return;const t=e.trim().toLowerCase();return t==="none"||t==="ohlc"?t:void 0},Ms=e=>{if(typeof e!="number"||!Number.isFinite(e))return;const t=Math.floor(e);return t>0?t:void 0},Ss=e=>Array.isArray(e),si=e=>{let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;for(let s=0;s<e.length;s++){const o=e[s],c=Ss(o)?o[0]:o.x,l=Ss(o)?o[1]:o.y;!Number.isFinite(c)||!Number.isFinite(l)||(c<t&&(t=c),c>n&&(n=c),l<i&&(i=l),l>r&&(r=l))}if(!(!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)))return t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r}},nu=e=>Array.isArray(e),iu=e=>{if(e.length===0)return;let t=Number.POSITIVE_INFINITY,n=Number.NEGATIVE_INFINITY,i=Number.POSITIVE_INFINITY,r=Number.NEGATIVE_INFINITY;if(nu(e[0])){const o=e;for(let c=0;c<o.length;c++){const l=o[c],u=l[0],m=l[3],f=l[4];if(!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(f))continue;const a=Math.min(m,f),v=Math.max(m,f);u<t&&(t=u),u>n&&(n=u),a<i&&(i=a),v>r&&(r=v)}}else{const o=e;for(let c=0;c<o.length;c++){const l=o[c],u=l.timestamp,m=l.low,f=l.high;if(!Number.isFinite(u)||!Number.isFinite(m)||!Number.isFinite(f))continue;const a=Math.min(m,f),v=Math.max(m,f);u<t&&(t=u),u>n&&(n=u),a<i&&(i=a),v>r&&(r=v)}}if(!(!Number.isFinite(t)||!Number.isFinite(n)||!Number.isFinite(i)||!Number.isFinite(r)))return t===n&&(n=t+1),i===r&&(r=i+1),{xMin:t,xMax:n,yMin:i,yMax:r}},ru=e=>{throw new Error(`Unhandled series type: ${(e==null?void 0:e.type)??"unknown"}`)};let Cs=!1;const su=()=>{Cs||(console.warn("ChartGPU: Candlestick series rendering is not yet implemented. Series will be skipped."),Cs=!0)};function ou(e={}){var F,b,x,y;const t=Zl(e.theme),n=e.autoScroll,i=typeof n=="boolean"?n:it.autoScroll,r=e.animation,o=(typeof r=="boolean"||r!==null&&typeof r=="object"&&!Array.isArray(r)?r:void 0)??!0,c=xn(e.palette),l=c.length>0?{...t,colorPalette:c}:t,u=xn(l.colorPalette),m=u.length>0?u:xn(it.palette??ii).length>0?xn(it.palette??ii):Array.from(ii),f=m.length>0?m:["#000000"],a={...l,colorPalette:f.slice()},v={left:((F=e.grid)==null?void 0:F.left)??it.grid.left,right:((b=e.grid)==null?void 0:b.right)??it.grid.right,top:((x=e.grid)==null?void 0:x.top)??it.grid.top,bottom:((y=e.grid)==null?void 0:y.bottom)??it.grid.bottom},M=e.xAxis?{...it.xAxis,...e.xAxis,type:e.xAxis.type??it.xAxis.type}:{...it.xAxis},C=e.yAxis?{...it.yAxis,...e.yAxis,type:e.yAxis.type??it.yAxis.type}:{...it.yAxis},p=(e.series??[]).map((d,h)=>{var T,B,U,G,D,_,X,Z,V,re;const N=Rt(d.color),w=a.colorPalette[h%a.colorPalette.length],I=N??w,R=jl(d.sampling)??"lttb",P=Ms(d.samplingThreshold)??5e3;switch(d.type){case"area":{const Y=Rt((T=d.areaStyle)==null?void 0:T.color)??N??w,ne={opacity:((B=d.areaStyle)==null?void 0:B.opacity)??Ns.opacity,color:Y},Se=si(d.data);return{...d,rawData:d.data,data:tn(d.data,R,P),color:Y,areaStyle:ne,sampling:R,samplingThreshold:P,rawBounds:Se}}case"line":{const Y=Rt((U=d.lineStyle)==null?void 0:U.color)??N??w,ne={width:((G=d.lineStyle)==null?void 0:G.width)??Fs.width,opacity:((D=d.lineStyle)==null?void 0:D.opacity)??Fs.opacity,color:Y},{areaStyle:Se,...Ce}=d,fe=si(d.data),oe=tn(d.data,R,P);return{...Ce,rawData:d.data,data:oe,color:Y,lineStyle:ne,...d.areaStyle?{areaStyle:{opacity:d.areaStyle.opacity??Ns.opacity,color:Rt(d.areaStyle.color)??Y}}:{},sampling:R,samplingThreshold:P,rawBounds:fe}}case"bar":{const ce=si(d.data);return{...d,rawData:d.data,data:tn(d.data,R,P),color:I,sampling:R,samplingThreshold:P,rawBounds:ce}}case"scatter":{const ce=si(d.data),Y=Kl(d.mode)??ri.mode,ne=Ql(d.binSize)??ri.binSize,Se=eu(d.densityColormap)??ri.densityColormap,Ce=Jl(d.densityNormalization)??ri.densityNormalization;return{...d,rawData:d.data,data:tn(d.data,R,P),color:I,mode:Y,binSize:ne,densityColormap:Se,densityNormalization:Ce,sampling:R,samplingThreshold:P,rawBounds:ce}}case"pie":{const{sampling:ce,samplingThreshold:Y,...ne}=d,Se=(d.data??[]).map((Ce,fe)=>{const oe=Rt(Ce==null?void 0:Ce.color),ve=a.colorPalette[(h+fe)%a.colorPalette.length];return{...Ce,color:oe??ve}});return{...ne,color:I,data:Se}}case"candlestick":{su();const ce=tu(d.sampling)??dt.sampling,Y=Ms(d.samplingThreshold)??dt.samplingThreshold,ne={upColor:Rt((_=d.itemStyle)==null?void 0:_.upColor)??dt.itemStyle.upColor,downColor:Rt((X=d.itemStyle)==null?void 0:X.downColor)??dt.itemStyle.downColor,upBorderColor:Rt((Z=d.itemStyle)==null?void 0:Z.upBorderColor)??dt.itemStyle.upBorderColor,downBorderColor:Rt((V=d.itemStyle)==null?void 0:V.downBorderColor)??dt.itemStyle.downBorderColor,borderWidth:typeof((re=d.itemStyle)==null?void 0:re.borderWidth)=="number"&&Number.isFinite(d.itemStyle.borderWidth)?d.itemStyle.borderWidth:dt.itemStyle.borderWidth},Se=iu(d.data),Ce=ce==="ohlc"&&d.data.length>Y?hi(d.data,Y):d.data;return{...d,rawData:d.data,data:Ce,color:I,style:d.style??dt.style,itemStyle:ne,barWidth:d.barWidth??dt.barWidth,barMinWidth:d.barMinWidth??dt.barMinWidth,barMaxWidth:d.barMaxWidth??dt.barMaxWidth,sampling:ce,samplingThreshold:Y,rawBounds:Se}}default:return ru(d)}});return{grid:v,xAxis:M,yAxis:C,autoScroll:i,dataZoom:ql(e.dataZoom),animation:o,theme:a,palette:a.colorPalette,series:p}}const au=32+8,cu=e=>{var t;return((t=e.dataZoom)==null?void 0:t.some(n=>(n==null?void 0:n.type)==="slider"))??!1};function Is(e={}){const t={...ou(e),tooltip:e.tooltip};return cu(e)?{...t,grid:{...t.grid,bottom:t.grid.bottom+au}}:t}const ht=120,lu=1e3/60,uu=1.5;function Ts(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid seriesIndex ${t}: ${e}. Must be a non-negative integer.`)}function Ps(e,t){if(!Number.isInteger(e)||e<0)throw new Error(`Invalid pointCount ${t}: ${e}. Must be a non-negative integer.`)}function rt(e){return e instanceof Error?[e.message,e.stack]:[String(e),void 0]}class fu{constructor(){this.charts=new Map,this.messageHandler=null}onMessage(t){this.messageHandler=t}async handleMessage(t){try{switch(t.type){case"init":await this.initChart(t);break;case"setOption":this.handleSetOption(t.chartId,t.options);break;case"appendData":this.handleAppendData(t.chartId,t.seriesIndex,t.data,t.pointCount,t.stride);break;case"appendDataBatch":this.handleAppendDataBatch(t.chartId,t.items);break;case"resize":this.handleResize(t.chartId,t);break;case"forwardPointerEvent":this.handlePointerEvent(t.chartId,t.event);break;case"setZoomRange":this.handleSetZoomRange(t.chartId,t.start,t.end);break;case"setInteractionX":this.handleSetInteractionX(t.chartId,t.x,t.source);break;case"setAnimation":this.handleSetAnimation(t.chartId,t.enabled,t.config);break;case"setGPUTiming":this.handleSetGPUTiming(t.chartId,t.enabled);break;case"dispose":this.disposeChart(t.chartId);break;default:const n=t;this.emitError("","UNKNOWN",`Unknown message type: ${n.type}`,"handleMessage")}}catch(n){const i="chartId"in t?t.chartId:"",[r,s]=rt(n);this.emitError(i,"UNKNOWN",r,"handleMessage",s)}}async initChart(t){var i,r;let n=null;try{if(this.charts.has(t.chartId)){this.emitError(t.chartId,"UNKNOWN",`Chart with ID "${t.chartId}" already exists`,"init",void 0,t.messageId);return}if(t.devicePixelRatio<=0)throw new Error(`Invalid devicePixelRatio: ${t.devicePixelRatio}. Must be positive.`);const s={devicePixelRatio:t.devicePixelRatio,powerPreference:(i=t.gpuOptions)==null?void 0:i.powerPreference},o=js(t.canvas,s);let c=await Ks(o);const l=Is(t.options);n=new MessageChannel;const m={renderPending:!1,disposed:!1,deviceLost:!1,performance:{frameTimestamps:new Float64Array(ht),frameTimestampIndex:0,frameTimestampCount:0,totalFrames:0,totalDroppedFrames:0,consecutiveDroppedFrames:0,lastDropTimestamp:0,startTime:performance.now(),lastFrameTime:0,gpuTimingEnabled:!1,lastCPUTime:0,lastGPUTime:0}};c.device&&(c.device.lost.then(p=>{m.deviceLost=!0,this.emit({type:"deviceLost",chartId:t.chartId,reason:p.reason==="destroyed"?"destroyed":"unknown",message:p.message||p.reason||"Device lost during initialization"})}).catch(()=>{}),c.device.addEventListener("uncapturederror",p=>{const F=p.error instanceof GPUValidationError?`WebGPU Validation Error: ${p.error.message}`:p.error instanceof GPUOutOfMemoryError?`WebGPU Out of Memory: ${p.error.message}`:`WebGPU Error: ${p.error.message}`;this.emitError(t.chartId,"RENDER_ERROR",F,"uncaptured_gpu_error")}));const f=zl(c,l,{domOverlays:!1,onRequestRender:()=>{!m.renderPending&&!m.disposed&&n&&(m.renderPending=!0,n.port2.postMessage(null))},onTooltipUpdate:p=>{if(this.emit({type:"tooltipUpdate",chartId:t.chartId,data:p}),p&&p.params.length>0){const F=p.params[0];this.emit({type:"hoverChange",chartId:t.chartId,payload:{seriesIndex:F.seriesIndex,dataIndex:F.dataIndex,value:F.value,x:p.x,y:p.y}})}else this.emit({type:"hoverChange",chartId:t.chartId,payload:null})},onLegendUpdate:p=>{this.emit({type:"legendUpdate",chartId:t.chartId,items:p})},onAxisLabelsUpdate:(p,F)=>{this.emit({type:"axisLabelsUpdate",chartId:t.chartId,xLabels:p,yLabels:F})},onCrosshairMove:p=>{p!==null&&this.emit({type:"crosshairMove",chartId:t.chartId,x:p})},onClickData:p=>{if(!(!p.nearest&&!p.pieSlice&&!p.candlestick)){if(p.nearest){this.emit({type:"click",chartId:t.chartId,payload:{seriesIndex:p.nearest.seriesIndex,dataIndex:p.nearest.dataIndex,value:p.nearest.point,x:p.x,y:p.y}});return}if(p.pieSlice){this.emit({type:"click",chartId:t.chartId,payload:{seriesIndex:p.pieSlice.seriesIndex,dataIndex:p.pieSlice.dataIndex,value:[p.pieSlice.slice.value,0],x:p.x,y:p.y}});return}p.candlestick&&this.emit({type:"click",chartId:t.chartId,payload:{seriesIndex:p.candlestick.seriesIndex,dataIndex:p.candlestick.dataIndex,value:p.candlestick.point,x:p.x,y:p.y}})}},onDeviceLost:p=>{m.deviceLost=!0,this.emit({type:"deviceLost",chartId:t.chartId,reason:p==="destroyed"?"destroyed":"unknown",message:p})}});f.onZoomRangeChange(p=>{this.emit({type:"zoomChange",chartId:t.chartId,start:p.start,end:p.end})});const a={chartId:t.chartId,gpuContext:c,coordinator:f,canvas:t.canvas,renderChannel:n,state:m};this.charts.set(t.chartId,a);const v=f.getZoomRange();if(n){const p=t.chartId,F=f,b=m;n.port1.onmessage=()=>{if(!b.disposed&&!b.deviceLost){b.renderPending=!1;const x=b.performance,y=performance.now();try{x.frameTimestamps[x.frameTimestampIndex]=y,x.frameTimestampIndex=(x.frameTimestampIndex+1)%ht,x.frameTimestampCount<ht&&x.frameTimestampCount++,x.totalFrames++,x.lastFrameTime>0&&(y-x.lastFrameTime>lu*uu?(x.totalDroppedFrames++,x.consecutiveDroppedFrames++,x.lastDropTimestamp=y):x.consecutiveDroppedFrames=0),x.lastFrameTime=y,F.render();const h=performance.now()-y;x.lastCPUTime=h;const N=this.calculatePerformanceMetrics(x);this.emit({type:"performance-update",chartId:p,metrics:N})}catch(d){const[h,N]=rt(d);this.emitError(p,"RENDER_ERROR",h,"render",N)}}else b.deviceLost&&(b.renderPending=!1)}}const M=c.adapter?{adapter:"WebGPU Adapter",features:c.adapter.features?[...c.adapter.features]:[]}:void 0,C={gpuTimingSupported:((r=c.adapter)==null?void 0:r.features.has("timestamp-query"))??!1,highResTimerSupported:typeof performance<"u"&&typeof performance.now=="function",performanceMetricsSupported:!0};this.emit({type:"ready",chartId:t.chartId,messageId:t.messageId,capabilities:M,performanceCapabilities:C,initialZoomRange:v}),!m.renderPending&&!m.disposed&&n&&(m.renderPending=!0,n.port2.postMessage(null))}catch(s){if(n)try{n.port1.close(),n.port2.close()}catch{}const[o,c]=rt(s),l=o.includes("WebGPU")?"WEBGPU_INIT_FAILED":"UNKNOWN";this.emitError(t.chartId,l,o,"init",c,t.messageId)}}handleSetOption(t,n){try{const i=this.getChartInstance(t,"setOption"),r=Is(n);i.coordinator.setOptions(r)}catch(i){const[r,s]=rt(i);this.emitError(t,"UNKNOWN",r,"setOption",s)}}handleAppendData(t,n,i,r,s){try{Ts(n,"in appendData"),Ps(r,"in appendData");const o=this.getChartInstance(t,"appendData"),c=Rs(i,r,s);o.coordinator.appendData(n,c)}catch(o){const[c,l]=rt(o);this.emitError(t,"DATA_ERROR",c,"appendData",l)}}handleAppendDataBatch(t,n){try{const i=this.getChartInstance(t,"appendDataBatch"),r=n.length;for(let s=0;s<r;s++){const o=n[s];Ts(o.seriesIndex,`at batch index ${s}`),Ps(o.pointCount,`at batch index ${s}`)}for(let s=0;s<r;s++){const o=n[s],c=Rs(o.data,o.pointCount,o.stride);i.coordinator.appendData(o.seriesIndex,c)}}catch(i){const[r,s]=rt(i);this.emitError(t,"DATA_ERROR",r,"appendDataBatch",s)}}handleResize(t,n){try{const i=this.getChartInstance(t,"resize");if(i.state.deviceLost)throw new Error("Cannot resize: GPU device is lost");const{width:r,height:s,devicePixelRatio:o}=n;if(r<=0||s<=0)throw new Error(`Invalid dimensions: width=${r}, height=${s}. Must be positive.`);if(o<=0)throw new Error(`Invalid devicePixelRatio: ${o}. Must be positive.`);const c=Math.floor(r*o),l=Math.floor(s*o);if(c===0||l===0)throw new Error(`Computed canvas dimensions are zero: ${c}x${l}. CSS dimensions (${r}x${s}px) are too small for device pixel ratio ${o}. Minimum canvas size is 1px in CSS space.`);const u=i.gpuContext.device;if(!u)throw new Error("GPU device is not available");const m=u.limits.maxTextureDimension2D,f=Math.max(1,Math.min(c,m)),a=Math.max(1,Math.min(l,m));i.canvas.width=f,i.canvas.height=a;const v=i.gpuContext.canvasContext,M=i.gpuContext.preferredFormat;if(!v)throw new Error("Canvas context is not available");if(!M)throw new Error("Preferred texture format is not available");try{v.configure({device:u,format:M,alphaMode:i.gpuContext.alphaMode})}catch(C){throw new Error(`Failed to reconfigure canvas context: ${C instanceof Error?C.message:String(C)}`)}n.requestRender&&!i.state.renderPending&&!i.state.disposed&&(i.state.renderPending=!0,i.renderChannel.port2.postMessage(null))}catch(i){const[r,s]=rt(i);this.emitError(t,"RENDER_ERROR",r,"resize",s)}}handlePointerEvent(t,n){try{console.log("[ChartGPUWorkerController] Received pointer event:",{type:n.type,gridX:n.gridX,gridY:n.gridY,isInGrid:n.isInGrid}),this.getChartInstance(t,"forwardPointerEvent").coordinator.handlePointerEvent(n)}catch(i){const[r,s]=rt(i);this.emitError(t,"UNKNOWN",r,"forwardPointerEvent",s)}}handleSetZoomRange(t,n,i){try{if(n<0||n>100||i<0||i>100)throw new Error(`Invalid zoom range: [${n}, ${i}]. Values must be in [0, 100] (percent space).`);if(n>=i)throw new Error(`Invalid zoom range: start (${n}) must be less than end (${i}).`);this.getChartInstance(t,"setZoomRange").coordinator.setZoomRange(n,i)}catch(r){const[s,o]=rt(r);this.emitError(t,"UNKNOWN",s,"setZoomRange",o)}}handleSetInteractionX(t,n,i){try{this.getChartInstance(t,"setInteractionX").coordinator.setInteractionX(n,i)}catch(r){const[s,o]=rt(r);this.emitError(t,"UNKNOWN",s,"setInteractionX",o)}}handleSetAnimation(t,n,i){try{const r=this.getChartInstance(t,"setAnimation");n&&!r.state.renderPending&&!r.state.disposed&&(r.state.renderPending=!0,r.renderChannel.port2.postMessage(null))}catch(r){const[s,o]=rt(r);this.emitError(t,"UNKNOWN",s,"setAnimation",o)}}handleSetGPUTiming(t,n){try{const i=this.getChartInstance(t,"setGPUTiming");i.state.performance.gpuTimingEnabled=n}catch(i){const[r,s]=rt(i);this.emitError(t,"UNKNOWN",r,"setGPUTiming",s)}}calculatePerformanceMetrics(t){const n=this.calculateExactFPS(t),i=this.calculateFrameTimeStats(t),r={enabled:t.gpuTimingEnabled,cpuTime:t.lastCPUTime,gpuTime:t.lastGPUTime},s={used:0,peak:0,allocated:0},o={totalDrops:t.totalDroppedFrames,consecutiveDrops:t.consecutiveDroppedFrames,lastDropTimestamp:t.lastDropTimestamp},c=performance.now()-t.startTime;return{fps:n,frameTimeStats:i,gpuTiming:r,memory:s,frameDrops:o,totalFrames:t.totalFrames,elapsedTime:c}}calculateExactFPS(t){const n=t.frameTimestampCount;if(n<2)return 0;const i=t.frameTimestamps,r=(t.frameTimestampIndex-n+ht)%ht;let s=0;for(let l=1;l<n;l++){const u=(r+l-1)%ht,m=(r+l)%ht,f=i[m]-i[u];s+=f}const o=s/(n-1);return o>0?1e3/o:0}calculateFrameTimeStats(t){const n=t.frameTimestampCount;if(n<2)return{min:0,max:0,avg:0,p50:0,p95:0,p99:0};const i=t.frameTimestamps,r=(t.frameTimestampIndex-n+ht)%ht,s=new Array(n-1);let o=Number.POSITIVE_INFINITY,c=Number.NEGATIVE_INFINITY,l=0;for(let v=1;v<n;v++){const M=(r+v-1)%ht,C=(r+v)%ht,p=i[C]-i[M];s[v-1]=p,p<o&&(o=p),p>c&&(c=p),l+=p}const u=l/s.length;s.sort((v,M)=>v-M);const m=Math.floor(s.length*.5),f=Math.floor(s.length*.95),a=Math.floor(s.length*.99);return{min:o,max:c,avg:u,p50:s[m],p95:s[f],p99:s[a]}}disposeChart(t){const n=[];try{const i=this.charts.get(t);if(!i){this.emitError(t,"UNKNOWN",`Chart "${t}" not found`,"dispose");return}if(i.state.disposed){this.emitError(t,"UNKNOWN",`Chart "${t}" is already disposed`,"dispose");return}i.state.disposed=!0;try{i.renderChannel.port1.close(),i.renderChannel.port2.close()}catch(r){n.push(`Failed to close render channel: ${r}`)}try{i.coordinator.dispose()}catch(r){n.push(`Failed to dispose coordinator: ${r}`)}try{i.gpuContext=Js(i.gpuContext)}catch(r){n.push(`Failed to destroy GPU context: ${r}`)}this.charts.delete(t),this.emit({type:"disposed",chartId:t,cleanupErrors:n.length>0?n:void 0})}catch(i){const[r,s]=rt(i);this.emitError(t,"UNKNOWN",r,"dispose",s)}}dispose(){const t=[...this.charts.keys()];for(const n of t)this.disposeChart(n);this.messageHandler=null}getChartInstance(t,n){const i=this.charts.get(t);if(!i)throw new Error(`Chart "${t}" not found for operation "${n}"`);if(i.state.disposed)throw new Error(`Chart "${t}" is disposed and cannot perform "${n}"`);if(i.state.deviceLost)throw new Error(`Chart "${t}" GPU device is lost and cannot perform "${n}". Re-initialize the chart.`);return i}emit(t){this.messageHandler?this.messageHandler(t):console.warn("No message handler registered, dropping message:",t)}emitError(t,n,i,r,s,o){const c={type:"error",chartId:t,code:n,message:i,operation:r,stack:s,messageId:o};this.emit(c)}}function Rs(e,t,n){if(!e)throw new Error("Buffer is null or undefined");if(!Number.isInteger(t)||t<0)throw new Error(`Invalid pointCount: ${t}. Must be a non-negative integer.`);if(!Number.isInteger(n)||n<=0)throw new Error(`Invalid stride: ${n}. Must be a positive integer.`);if(e.byteLength===0&&t>0)throw new Error("Buffer is detached (byteLength = 0). The ArrayBuffer may have been transferred multiple times. Each ArrayBuffer can only be transferred once via postMessage.");if(e.byteLength%4!==0)throw new Error(`Buffer size (${e.byteLength} bytes) is not 4-byte aligned. WebGPU requires all buffer sizes to be multiples of 4 bytes.`);if(n%4!==0)throw new Error(`Stride (${n} bytes) is not 4-byte aligned. Float32 data requires stride to be a multiple of 4 bytes.`);const i=t*n;if(e.byteLength!==i)throw new Error(`Buffer size mismatch: expected ${i} bytes (${t} points × ${n} bytes), got ${e.byteLength} bytes. Difference: ${e.byteLength-i} bytes.`);const r=new Float32Array(e),s=n/4,o=t*s;if(r.length!==o)throw new Error(`Float32Array length mismatch: expected ${o} elements, got ${r.length} elements`);if(n===8){const c=new Array(t);for(let l=0,u=0;l<t;l++,u+=2)c[l]=[r[u],r[u+1]];return c}else if(n===20){const c=new Array(t);for(let l=0,u=0;l<t;l++,u+=5)c[l]=[r[u],r[u+1],r[u+4],r[u+3],r[u+2]];return c}else throw new Error(`Invalid stride: ${n} bytes. Expected 8 (DataPoint) or 20 (OHLCDataPoint). Received stride corresponds to ${n/4} floats per point.`)}const As=new fu;As.onMessage(e=>{self.postMessage(e)}),self.onmessage=async e=>{try{await As.handleMessage(e.data)}catch(t){self.postMessage({type:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,chartId:e.data.chartId})}},self.onerror=e=>{const t=e instanceof ErrorEvent?e.error:e;console.error("[ChartGPU Worker] Uncaught error:",t),self.postMessage({type:"error",message:t instanceof Error?t.message:String(t),stack:t instanceof Error?t.stack:void 0,chartId:"unknown"})},self.onunhandledrejection=e=>{console.error("[ChartGPU Worker] Unhandled promise rejection:",e.reason),self.postMessage({type:"error",message:e.reason instanceof Error?e.reason.message:String(e.reason),stack:e.reason instanceof Error?e.reason.stack:void 0,chartId:"unknown"})}})();
|
|
779
|
+
//# sourceMappingURL=worker-entry-Wg897auv.js.map
|