@awc-ui/core 1.0.0-beta → 1.0.0-beta.1
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/dist/components/p-6wZSqm_2.js +2 -0
- package/dist/components/{p-Bx5sxRqa.js.map → p-6wZSqm_2.js.map} +1 -1
- package/dist/components/p-7fN_yCXW.js +2 -0
- package/dist/components/{p-CJdqKSuf.js.map → p-7fN_yCXW.js.map} +1 -1
- package/dist/components/{p-G5m2pHZ2.js → p-B0Opn6dK.js} +2 -2
- package/dist/components/{p-pDrTJmeT.js → p-B3MWYEEJ.js} +2 -2
- package/dist/components/{p-DGGkdSZk.js → p-BwXpiUsu.js} +2 -2
- package/dist/{md3/p-B0NLeNWu.js → components/p-Bx6--dQF.js} +2 -2
- package/dist/components/{p-BIIp3Qod.js → p-C8EP4S21.js} +2 -2
- package/dist/components/{p-CWM3KSti.js → p-C_ogF68H.js} +2 -2
- package/dist/components/{p-BlwGYUkt.js → p-Ch2-tttM.js} +2 -2
- package/dist/components/p-DXXUoRSH.js +2 -0
- package/dist/components/{p-DWUCvzfU.js.map → p-DXXUoRSH.js.map} +1 -1
- package/dist/components/p-Dp-w93ot.js +2 -0
- package/dist/components/{p-BUYYCrGa.js.map → p-Dp-w93ot.js.map} +1 -1
- package/dist/{md3/p-CGStn3Iq.js → components/p-DvOKnoqK.js} +2 -2
- package/dist/components/{p-B7yMxWo-.js → p-DzPKu-Ma.js} +2 -2
- package/dist/components/{p-CXpXrhQH.js → p-RLxbNqRv.js} +2 -2
- package/dist/components/p-UdGDg2oJ.js +2 -0
- package/dist/components/{p-BujtL9xW.js.map → p-UdGDg2oJ.js.map} +1 -1
- package/dist/components/p-e2HRV63Y.js +2 -0
- package/dist/components/{p-CrlkPxeB.js.map → p-e2HRV63Y.js.map} +1 -1
- package/dist/components/p-stybaFzj.js +2 -0
- package/dist/components/{p-JbwZ84YK.js.map → p-stybaFzj.js.map} +1 -1
- package/dist/components/p-uTEkf0sE.js +2 -0
- package/dist/components/{p-BXwh1zjF.js.map → p-uTEkf0sE.js.map} +1 -1
- package/dist/esm/{a11y-C9_cZAF_.js → a11y-C6CRqodW.js} +3 -3
- package/dist/esm/{a11y-C9_cZAF_.js.map → a11y-C6CRqodW.js.map} +1 -1
- package/dist/esm/{bar-chart-IvBgAmmF.js → bar-chart-ZZrajEkM.js} +4 -4
- package/dist/esm/{bar-chart-IvBgAmmF.js.map → bar-chart-ZZrajEkM.js.map} +1 -1
- package/dist/esm/{chart-D1kP9gfW.js → chart-32olae06.js} +4 -4
- package/dist/esm/{chart-D1kP9gfW.js.map → chart-32olae06.js.map} +1 -1
- package/dist/esm/{hit-test-DFfwlMb9.js → hit-test-DHldf5Lm.js} +3 -3
- package/dist/esm/{hit-test-DFfwlMb9.js.map → hit-test-DHldf5Lm.js.map} +1 -1
- package/dist/esm/{rtl-CGStn3Iq.js → rtl-DvOKnoqK.js} +3 -3
- package/dist/esm/{rtl-CGStn3Iq.js.map → rtl-DvOKnoqK.js.map} +1 -1
- package/dist/md3/p-04e97f5d.entry.js +2 -0
- package/dist/md3/{p-ec14eaca.entry.js.map → p-04e97f5d.entry.js.map} +1 -1
- package/dist/md3/p-3cce1de3.entry.js +2 -0
- package/dist/md3/{p-2121c939.entry.js.map → p-3cce1de3.entry.js.map} +1 -1
- package/dist/md3/p-4d82132d.entry.js +2 -0
- package/dist/md3/{p-fe78659d.entry.js.map → p-4d82132d.entry.js.map} +1 -1
- package/dist/{components/p-Bu-m4Gm2.js → md3/p-Bx6--dQF.js} +2 -2
- package/dist/md3/{p-B0NLeNWu.js.map → p-Bx6--dQF.js.map} +1 -1
- package/dist/md3/{p-CWM3KSti.js → p-C_ogF68H.js} +2 -2
- package/dist/md3/{p-CWM3KSti.js.map → p-C_ogF68H.js.map} +1 -1
- package/dist/{components/p-CGStn3Iq.js → md3/p-DvOKnoqK.js} +2 -2
- package/dist/md3/{p-CGStn3Iq.js.map → p-DvOKnoqK.js.map} +1 -1
- package/dist/md3/{p-B7yMxWo-.js → p-DzPKu-Ma.js} +2 -2
- package/dist/md3/{p-B7yMxWo-.js.map → p-DzPKu-Ma.js.map} +1 -1
- package/dist/md3/{p-CXpXrhQH.js → p-RLxbNqRv.js} +2 -2
- package/dist/md3/{p-CXpXrhQH.js.map → p-RLxbNqRv.js.map} +1 -1
- package/dist/md3/{p-f6373c6c.entry.js → p-aaec2698.entry.js} +2 -2
- package/dist/md3/{p-9ff2d5d1.entry.js → p-c063c823.entry.js} +2 -2
- package/main-llm.md +2 -2
- package/package.json +24 -3
- package/dist/components/p-BUYYCrGa.js +0 -2
- package/dist/components/p-BXwh1zjF.js +0 -2
- package/dist/components/p-BujtL9xW.js +0 -2
- package/dist/components/p-Bx5sxRqa.js +0 -2
- package/dist/components/p-CJdqKSuf.js +0 -2
- package/dist/components/p-CrlkPxeB.js +0 -2
- package/dist/components/p-DWUCvzfU.js +0 -2
- package/dist/components/p-JbwZ84YK.js +0 -2
- package/dist/md3/p-2121c939.entry.js +0 -2
- package/dist/md3/p-ec14eaca.entry.js +0 -2
- package/dist/md3/p-fe78659d.entry.js +0 -2
- /package/dist/components/{p-G5m2pHZ2.js.map → p-B0Opn6dK.js.map} +0 -0
- /package/dist/components/{p-pDrTJmeT.js.map → p-B3MWYEEJ.js.map} +0 -0
- /package/dist/components/{p-DGGkdSZk.js.map → p-BwXpiUsu.js.map} +0 -0
- /package/dist/components/{p-Bu-m4Gm2.js.map → p-Bx6--dQF.js.map} +0 -0
- /package/dist/components/{p-BIIp3Qod.js.map → p-C8EP4S21.js.map} +0 -0
- /package/dist/components/{p-CWM3KSti.js.map → p-C_ogF68H.js.map} +0 -0
- /package/dist/components/{p-BlwGYUkt.js.map → p-Ch2-tttM.js.map} +0 -0
- /package/dist/components/{p-CGStn3Iq.js.map → p-DvOKnoqK.js.map} +0 -0
- /package/dist/components/{p-B7yMxWo-.js.map → p-DzPKu-Ma.js.map} +0 -0
- /package/dist/components/{p-CXpXrhQH.js.map → p-RLxbNqRv.js.map} +0 -0
- /package/dist/md3/{p-f6373c6c.entry.js.map → p-aaec2698.entry.js.map} +0 -0
- /package/dist/md3/{p-9ff2d5d1.entry.js.map → p-c063c823.entry.js.map} +0 -0
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as t,c as i,h as s,H as e,a as n}from"./p-DTaX19_O.js";import{c as a,r as o,d as r,b as h,a as l}from"./p-C_ogF68H.js";import{L as c}from"./p-RLxbNqRv.js";import{d,a as m,r as u,b as p,p as f}from"./p-DvOKnoqK.js";import"./p-DzPKu-Ma.js";const y=()=>`:host{--_block-size:var(--md-line-chart-block-size, auto);--_min-block-size:var(--md-line-chart-min-block-size, max(120px, calc(160px + var(--md-sys-density-scale, 0) * 8px)));--_aspect-ratio:var(--md-line-chart-aspect-ratio, 16 / 9);--_background:var(--md-line-chart-background, var(--md-sys-color-surface-container-low, #F7F2FA));--_padding:var(--md-line-chart-padding, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));--_shape:var(--md-line-chart-shape, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));--_empty-color:var(--md-line-chart-empty-color, var(--md-sys-color-on-surface-variant, #49454F));--_empty-background:var(--md-line-chart-empty-background, var(--_background));--_empty-font:var(--md-line-chart-empty-font, var(--md-sys-typescale-body-medium-font-family, Roboto, sans-serif));--_empty-font-size:var(--md-line-chart-empty-font-size, var(--md-sys-typescale-body-medium-font-size, 14px));--_empty-icon-size:var(--md-line-chart-empty-icon-size, 40px);--_zoom-size:var(--md-line-chart-zoom-size, 28px);--_zoom-track-color:var(--md-line-chart-zoom-track-color, var(--md-sys-color-surface-container-highest, #E6E0E9));--_zoom-window-color:var(--md-line-chart-zoom-window-color, var(--md-sys-color-secondary-container, #E8DEF8));--_zoom-handle-color:var(--md-line-chart-zoom-handle-color, var(--md-sys-color-primary, #6750A4));--_zoom-band-color:var(--md-line-chart-zoom-band-color, color-mix(in srgb, var(--md-sys-color-primary, #6750A4) 16%, transparent));--_zoom-pan-inset:10px;display:block;position:relative;inline-size:100%;block-size:var(--_block-size);min-block-size:var(--_min-block-size);background:var(--_background);padding:var(--_padding);border-radius:var(--_shape);box-sizing:border-box;aspect-ratio:var(--_aspect-ratio)}.md-line-chart__header,.md-line-chart__footer{display:contents}.md-line-chart__header>slot[name='header']::slotted(*),.md-line-chart__footer>slot[name='footer']::slotted(*){display:block;margin-block:8px}.md-line-chart__canvas{position:absolute;inset:var(--_padding);min-block-size:0;min-inline-size:0}.md-line-chart__empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;box-sizing:border-box;padding:24px;background:var(--_empty-background);border-radius:var(--_shape);color:var(--_empty-color);font-family:var(--_empty-font);font-size:var(--_empty-font-size);line-height:var(--md-sys-typescale-body-medium-line-height, 20px);pointer-events:none;text-align:center}.md-line-chart__loading{position:absolute;inset:0;z-index:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:12px;box-sizing:border-box;padding:24px;background:var(--_empty-background);border-radius:var(--_shape);color:var(--_empty-color);font-family:var(--_empty-font);font-size:var(--_empty-font-size);text-align:center}.md-line-chart__spinner{inline-size:var(--_empty-icon-size);block-size:var(--_empty-icon-size)}.md-line-chart__empty ::slotted(.material-symbols-outlined),.md-line-chart__empty ::slotted(.material-symbols-rounded),.md-line-chart__empty ::slotted(.material-symbols-sharp),.md-line-chart__empty ::slotted(.material-icons){font-size:var(--_empty-icon-size) !important;line-height:1;opacity:0.55}:host(.md-line-chart--zoom-slider) .md-line-chart__canvas{bottom:calc(var(--_padding) + var(--_zoom-size))}:host(.md-line-chart--zoom-drag) .md-line-chart__canvas{cursor:ew-resize}.md-line-chart__zoom{position:absolute;inset-inline:var(--_padding);bottom:var(--_padding);block-size:var(--_zoom-size);display:flex;align-items:center}.md-line-chart__zoom-slider{--md-slider-active-color:var(--_zoom-window-color);--md-slider-inactive-color:var(--_zoom-track-color);--md-slider-thumb-color:var(--_zoom-handle-color);--md-slider-thumb-height:var(--_zoom-size);--md-slider-track-height:12px}.md-line-chart__zoom-pan{position:absolute;inset-block:0;z-index:1;cursor:grab;touch-action:none}.md-line-chart__zoom-pan:active{cursor:grabbing}.md-line-chart__zoom-band{position:absolute;background:var(--_zoom-band-color);border-inline:1px solid var(--_zoom-handle-color);pointer-events:none}.md-line-chart__live{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}[part='legend'] button:focus-visible{outline:3px solid var(--md-sys-color-secondary, #625B71);outline-offset:2px;border-radius:6px}.md-line-chart__canvas:focus-visible{outline:3px solid var(--md-sys-color-secondary, #625B71);outline-offset:-3px;border-radius:4px}.md-line-chart__a11y-table{position:absolute;inline-size:1px;block-size:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}@media (forced-colors: active){:host{forced-color-adjust:auto}}:host([density='-1']){--md-sys-density-scale:-1}:host([density='-2']){--md-sys-density-scale:-2}:host([density='-3']){--md-sys-density-scale:-3}:host([density='-4']){--md-sys-density-scale:-4}`;const b=class{constructor(s){t(this,s);this.mdMarkerClick=i(this,"mdMarkerClick",7);this.mdLineClick=i(this,"mdLineClick",7);this.mdAreaClick=i(this,"mdAreaClick",7);this.mdAxisClick=i(this,"mdAxisClick",7);this.mdLegendClick=i(this,"mdLegendClick",7);this.mdHover=i(this,"mdHover",7);this.mdReady=i(this,"mdReady",7);this.mdZoom=i(this,"mdZoom",7);this.label="";this.titleAlign="start";this.series=[];this.curve="smooth";this.stack="none";this.connectNulls=false;this.showMarks=false;this.area=false;this.showLine=true;this.legend="top-end";this.tooltip="axis";this.grid="horizontal";this.axisTicks=false;this.inverted=false;this.showLabels=false;this.seriesLabels=false;this.zoom="none";this.locale="";this.labelEmpty="No data to display";this.labelPlot="Chart data. Use the arrow keys to move between points, Home and End for the first and last, Escape to leave.";this.labelPoint="%x%: %values%";this.labelZoomStart="Zoom range start";this.labelZoomEnd="Zoom range end";this.summary="";this.noAnimation=false;this.animation="expressive";this.loading=false;this.loadingLabel="Loading chart…";this.density=0;this.mounted=false;this.kbIndex=-1;this.announcement="";this.zoomWin=null;this.dragBand=null;this.grab=null;this.engine=null;this.ro=null;this.legendHidden=new Map;this.mergeCache=null;this.bindChartHost=t=>{this.chartHost=t};this.bindA11yTableHost=t=>{this.a11yTableHost=t};this.onPlotPointerDown=t=>{if(!this.zoomInside||t.button!==0||this.grab)return;if(!this.insidePlot(t))return;const i=this.hostX(t);this.grab={id:t.pointerId,kind:"band",x:i,win:this.win()};this.dragBand={x1:i,x2:i};const s=t.composedPath?.()[0]??t.target;s.setPointerCapture?.(t.pointerId)};this.onPointerMove=t=>{const i=this.grab;if(!i||i.id!==t.pointerId)return;if(i.kind==="band"){const s=this.plotRect();if(!s)return;this.dragBand={x1:i.x,x2:Math.min(Math.max(this.hostX(t),s.x),s.x+s.width)};return}const s=this.trackFrac(t.clientX);const e=this.trackFrac(i.x);if(s==null||e==null)return;const n=Math.max(1,this.dataLength()-1);const a=i.win.end-i.win.start;const o=Math.round((s-e)*n);const r=Math.min(Math.max(0,i.win.start+o),n-a);this.applyZoom(r,r+a)};this.onPointerUp=t=>{const i=this.grab;if(!i||i.id!==t.pointerId)return;this.grab=null;const s=this.dragBand;this.dragBand=null;if(i.kind!=="band"||!s)return;if(Math.abs(s.x2-s.x1)<8)return;const[e,n]=[this.indexAtX(s.x1),this.indexAtX(s.x2)].sort(((t,i)=>t-i));if(n-e>=1)this.applyZoom(e,n)};this.onPlotKeyDown=t=>{const i=Math.max(0,this.dataLength()-1);if(i<0)return;const s=typeof getComputedStyle==="function"&&getComputedStyle(this.el).direction==="rtl";const e=s?"ArrowLeft":"ArrowRight";const n=s?"ArrowRight":"ArrowLeft";let a=this.kbIndex;switch(t.key){case e:a=this.kbIndex<0?0:Math.min(i,this.kbIndex+1);break;case n:a=this.kbIndex<0?i:Math.max(0,this.kbIndex-1);break;case"Home":a=0;break;case"End":a=i;break;case"Escape":if(this.kbIndex<0)return;a=-1;break;case"Enter":case" ":if(this.kbIndex<0)return;this.mdAxisClick.emit(this.axisDetail(this.kbIndex,this.seriesValuesAt(this.kbIndex),t));t.preventDefault();return;default:return}t.preventDefault();this.moveKeyboardCursor(a)};this.onPlotBlur=()=>{if(this.kbIndex>=0)this.moveKeyboardCursor(-1)};this.onPlotDblClick=t=>{if(this.zoomInside&&this.zoomWin&&this.insidePlot(t))this.resetZoom()};this.onZoomPanDown=t=>{if(t.button!==0)return;t.stopPropagation();t.preventDefault();this.grab={id:t.pointerId,kind:"pan",x:t.clientX,win:this.win()};t.target.setPointerCapture?.(t.pointerId)};this.onZoomSliderInput=t=>{t.stopPropagation();const{valueStart:i,valueEnd:s}=t.detail??{};if(i==null||s==null)return;this.applyZoom(i,s)};this.onZoomSliderEvent=t=>t.stopPropagation()}componentDidLoad(){this.initChart();if(typeof window!=="undefined"&&window.matchMedia){this.themeMql=window.matchMedia("(prefers-color-scheme: dark)");this.themeListener=()=>this.applyEngine();this.themeMql.addEventListener?.("change",this.themeListener)}}disconnectedCallback(){this.ro?.disconnect();this.ro=null;this.engine?.dispose();this.engine=null;if(this.themeMql&&this.themeListener){this.themeMql.removeEventListener?.("change",this.themeListener);this.themeListener=undefined;this.themeMql=undefined}}onAnyPropChange(){this.applyEngine();this.rebuildA11yTable()}onLoadingChange(t,i){if(i&&!t)this.engine?.replay()}async resize(){this.engine?.resize()}async replay(){this.engine?.replay()}async toDataURL(){return this.engine?.toDataURL("image/png")??""}async getInstance(){return this.engine}initChart(){this.makeEngine();this.applyEngine();this.rebuildA11yTable();this.mounted=true;this.mdReady.emit()}makeEngine(){if(!this.chartHost)return;this.ro?.disconnect();this.ro=null;this.engine?.dispose();try{this.engine=new c(this.chartHost)}catch{this.engine=null}if(this.engine&&typeof ResizeObserver!=="undefined"){this.ro=new ResizeObserver((()=>this.engine?.resize()));this.ro.observe(this.chartHost)}}buildEngineTheme(t){return{background:t.background,textColor:t.textColor,textColorMuted:t.textColorMuted,axisLineColor:t.axisLineColor,gridLineColor:t.gridColor,surface:t.surface,fontFamily:t.fontFamily,labelSize:t.labelSize,titleSize:t.titleSize}}seriesKeys(){const t=new Map;return this.series.map(((i,s)=>{const e=i.id!=null?`id:${i.id}`:i.label!=null?`label:${i.label}`:`pos:${s}`;const n=t.get(e)??0;t.set(e,n+1);return n===0?e:`${e}#${n}`}))}rememberLegendToggle(t,i){const s=this.seriesKeys()[t];if(s==null)return;this.legendHidden.set(s,i);if(this.legendHidden.size>256){const t=this.legendHidden.keys().next().value;this.legendHidden.delete(t)}}get zoomInside(){return this.zoom==="inside"||this.zoom==="both"}get zoomSliderOn(){return this.zoom==="slider"||this.zoom==="both"}get merged(){const t=this.xAxis?.scale??"category";const i=this.xAxis?.data;const s=this.mergeCache;if(s&&s.series===this.series&&s.axis===i&&s.scale===t)return s.out;const e=a(this.series??[],i,t);this.mergeCache={series:this.series,axis:i,scale:t,out:e};return e}dataLength(){const t=this.merged;const i=t.data.reduce(((t,i)=>Math.max(t,i?.length??0)),0);return Math.max(i,t.xValues.length)}win(){const t=Math.max(0,this.dataLength()-1);const i=this.zoomWin;if(!i)return{start:0,end:t};const s=Math.min(Math.max(0,i.start),Math.max(0,t-1));return{start:s,end:Math.min(Math.max(s+1,i.end),t)}}applyZoom(t,i,s=false){const e=Math.max(0,this.dataLength()-1);const n=Math.min(Math.max(0,Math.round(t)),Math.max(0,e-1));const a=Math.min(Math.max(n+1,Math.round(i)),e);this.zoomWin=s?null:{start:n,end:a};this.applyEngine();this.rebuildA11yTable();this.mdZoom.emit({startIndex:s?0:n,endIndex:s?e:a,reset:s})}async setZoom(t,i){this.applyZoom(t,i)}async resetZoom(){this.applyZoom(0,0,true)}plotRect(){const t=this.engine?.getScene()?.plot;return t?{x:t.x,y:t.y,width:t.width,height:t.height}:null}canvasOffset(){const t=this.chartHost;if(!t)return{x:0,y:0};const i=this.el.getBoundingClientRect();const s=t.getBoundingClientRect();return{x:s.left-i.left,y:s.top-i.top}}zoomBandStyle(){const t=this.plotRect();if(!this.dragBand||!t)return undefined;const i=this.canvasOffset();const{x1:s,x2:e}=this.dragBand;return{left:`${i.x+Math.min(s,e)}px`,width:`${Math.abs(e-s)}px`,top:`${i.y+t.y}px`,height:`${t.height}px`}}indexAtX(t){const i=this.engine?.getScene();const s=this.win();if(!i?.xPositions?.length)return s.start;let e=0;let n=Infinity;i.xPositions.forEach(((i,s)=>{const a=Math.abs(i-t);if(a<n){n=a;e=s}}));return s.start+e}hostX(t){return t.clientX-(this.chartHost??this.el).getBoundingClientRect().left}insidePlot(t){const i=this.plotRect();if(!i)return false;const s=(this.chartHost??this.el).getBoundingClientRect();const e=t.clientX-s.left;const n=t.clientY-s.top;return e>=i.x&&e<=i.x+i.width&&n>=i.y&&n<=i.y+i.height}moveKeyboardCursor(t){this.kbIndex=t;this.engine?.focusIndex(t);if(t<0){this.announcement="";return}const i=this.merged;const s=i.xValues[t];const e=this.xAxis?.valueFormatter?this.xAxis.valueFormatter(s):d(s??t+1,this.locale);const n=t=>this.valueFormatter?this.valueFormatter(t):t.toLocaleString(this.locale||undefined);const a=this.seriesValuesAt(t).filter((t=>t.value!=null)).map((t=>`${t.label} ${n(t.value)}`)).join(", ");this.announcement=this.labelPoint.replace("%x%",e).replace("%values%",a);this.mdHover.emit({dataIndex:t,axisValue:s,seriesIndices:this.visibleSeriesIndices()})}sliderTrackRect(){const t=this.el.shadowRoot?.querySelector(".md-line-chart__zoom-slider");if(!t)return null;const i=t.getBoundingClientRect();if(!i.width)return null;return{left:i.left,width:i.width,rtl:getComputedStyle(this.el).direction==="rtl"}}trackFrac(t){const i=this.sliderTrackRect();if(!i)return null;const s=(t-i.left)/i.width;return Math.min(Math.max(i.rtl?1-s:s,0),1)}buildSpec(t){const i=this.stack==="percentage";const s=t=>this.valueFormatter?this.valueFormatter(t):t.toLocaleString(this.locale||undefined);const e=this.seriesKeys();const n=this.zoomWin?this.win():null;const a=t=>t&&n?t.slice(n.start,n.end+1):t;const r=t=>{if(!t||!n)return t;const i={};for(const[s,e]of Object.entries(t)){const t=Number(s)-n.start;if(t>=0&&t<=n.end-n.start)i[t]=e}return i};const h=this.merged;const l=this.series.map(((i,s)=>{const l=e[s];const c=this.legendHidden.get(l);const d=h.toMerged[s];const u=i.dashAfter!=null&&d?d[i.dashAfter]:i.dashAfter;if(i.hidden!==undefined)this.legendHidden.delete(l);return{label:i.label??`Series ${s+1}`,color:m(this.el,i.color,f(t.palette,s)),data:a(h.data[s])??h.data[s]??[],curve:i.curve??this.curve,connectNulls:i.connectNulls??this.connectNulls,showMarks:i.showMarks??this.showMarks,hidden:i.hidden??c??false,dash:i.dash,symbol:i.symbol,pointSymbols:r(o(i.pointSymbols,d)),yAxisIndex:i.yAxisIndex,dashAfter:u!=null&&u>=0&&n?u-n.start:u,hollow:i.hollow,stroke:i.stroke??(this.showLine?undefined:false),lineWidth:i.lineWidth??this.lineWidth,markSize:i.markSize??this.markSize}}));return{series:l,title:this.label||undefined,subtitle:this.subtitle||undefined,markLines:this.markLines?.map((t=>{const i=n!=null&&(this.xAxis?.scale??"category")==="category"&&typeof t.value==="number";const s=i?t.value-n.start:t.value;return{value:s,label:t.label,color:t.color!=null?m(this.el,t.color,t.color):undefined,dash:t.dash,offscreen:i&&(Number(s)<0||Number(s)>n.end-n.start)}})).filter((t=>!t.offscreen)).map((({offscreen:t,...i})=>i)),titleAlign:this.titleAlign,xValues:a(h.xValues)??[],xScale:this.xAxis?.scale??"category",xFormatter:this.xAxis?.valueFormatter??(t=>d(t,this.locale)),xLabel:this.xAxis?.label,xHidden:this.xAxis?.hidden,xHideTicks:this.xAxis?.hideTicks,xDash:this.xAxis?.dash,xGridDash:this.xAxis?.gridDash,xBands:u(this.el,this.xAxis?.bands),yBands:u(this.el,this.yAxis?.bands),xBreaks:this.xAxis?.breaks,yBreaks:this.yAxis?.breaks,yScale:this.yAxis?.scale??"value",yMin:i?0:this.yAxis?.min,yMax:i?100:this.yAxis?.max,yFormatter:i?t=>`${Math.round(t)}%`:s,yTickFormatter:!i&&this.yAxis?.valueFormatter?t=>this.yAxis.valueFormatter(t):undefined,yLabel:this.yAxis?.label,yHidden:this.yAxis?.hidden,yHideTicks:this.yAxis?.hideTicks,yDash:this.yAxis?.dash,yGridDash:this.yAxis?.gridDash,yAxes:this.yAxes?.length?this.yAxes.map((t=>({scale:t.scale??"value",min:t.min,max:t.max,formatter:t.valueFormatter?i=>t.valueFormatter(i):t=>t.toLocaleString(this.locale||undefined),label:t.label,position:t.position,hidden:t.hidden,hideTicks:t.hideTicks,color:t.color!=null?m(this.el,t.color,t.color):undefined,bands:u(this.el,t.bands),dash:t.dash,gridDash:t.gridDash}))):undefined,stack:this.stack,area:this.area,legend:this.legend,gridY:this.grid==="horizontal"||this.grid==="both",gridX:this.grid==="vertical"||this.grid==="both",axisTicks:this.axisTicks,inverted:this.inverted,showLabels:this.showLabels,seriesLabels:this.seriesLabels,animation:this.noAnimation?"none":this.animation,animationDuration:this.animationDuration}}applyEngine(){if(!this.engine)return;const t=p(this.el);this.engine.setSpec(this.buildSpec(t),this.buildEngineTheme(t),{onHover:t=>{if(t<0)return;const i=t+(this.zoomWin?this.win().start:0);this.mdHover.emit({dataIndex:i,axisValue:this.merged.xValues[i],seriesIndices:this.visibleSeriesIndices()})},onLegendClick:t=>{this.rememberLegendToggle(t.seriesIndex,!!t.hidden);this.mdLegendClick.emit({seriesIndex:t.seriesIndex,seriesId:this.series[t.seriesIndex]?.id,selected:!t.hidden})},onPointClick:(t,i,s)=>{const e=this.clickDetail(t,i,s);if(e)this.mdMarkerClick.emit(e)},onLineClick:(t,i,s)=>{const e=this.clickDetail(t,i,s);if(e)this.mdLineClick.emit(e)},onAreaClick:(t,i,s)=>{const e=this.clickDetail(t,i,s);if(e)this.mdAreaClick.emit(e)},onAxisClick:(t,i,s)=>this.mdAxisClick.emit(this.axisDetail(t,i,s))});this.engine.setHoverEnabled(this.tooltip!=="none");this.engine.setTooltip({render:this.tooltipRenderer,missingFormatter:this.valueFormatter,trigger:this.tooltip==="item"?"item":"axis"})}clickDetail(t,i,s){const e=this.series[t];if(!e)return null;const n=i+(this.zoomWin?this.win().start:0);const a=this.ownIndex(t,n);return{seriesIndex:t,seriesId:e.id,dataIndex:a>=0?a:n,value:a>=0?r(e.data[a]):null,axisValue:this.merged.xValues[n],nativeEvent:s,series:e}}ownIndex(t,i){const s=this.merged.toOwn[t];return s?s[i]??-1:i}seriesValuesAt(t){const i=this.engine?.getScene()?.hoverPoints??[];return i.map((i=>({seriesIndex:i.seriesIndex,label:i.label,value:i.byIndex[t]?.value??null})))}axisDetail(t,i,s){const e=t+(this.zoomWin?this.win().start:0);const n=i.map((t=>{const i=this.ownIndex(t.seriesIndex,e);return{seriesIndex:t.seriesIndex,seriesId:this.series[t.seriesIndex]?.id,label:t.label,dataIndex:t.value==null?-1:i,value:t.value}}));return{dataIndex:e,axisValue:this.merged.xValues[e],seriesValues:n,nativeEvent:s}}visibleSeriesIndices(){const t=this.engine?.getScene()?.hoverPoints;if(t)return t.map((t=>t.seriesIndex));const i=this.seriesKeys();return this.series.map(((t,i)=>i)).filter((t=>!(this.series[t].hidden??this.legendHidden.get(i[t])??false)))}rebuildA11yTable(){if(!this.a11yTableHost)return;const t=this.merged;this.a11yTableHost.innerHTML=h({title:this.label,xAxisLabel:this.xAxis?.label,xAxisData:t.xValues,xValueFormatter:this.xAxis?.valueFormatter??(t=>d(t,this.locale)),locale:this.locale,labels:this.tableLabels,series:this.series.map(((i,s)=>({label:i.label,data:t.data[s]??[]}))),valueFormatter:this.valueFormatter})}renderZoomSlider(){const t=Math.max(1,this.dataLength()-1);const i=this.win();const e=i=>i/t*100;const n=t=>String(this.xAxis?.data?.[t]??t);return s("div",{class:"md-line-chart__zoom",part:"zoom"},s("md-slider",{class:"md-line-chart__zoom-slider",part:"zoom-slider",exportparts:"track: zoom-track, track-active: zoom-window, thumb-knob: zoom-handle",range:true,controlled:true,min:0,max:t,step:1,valueStart:i.start,valueEnd:i.end,ariaLabelStart:this.labelZoomStart,ariaLabelEnd:this.labelZoomEnd,valueStartText:n(i.start),valueEndText:n(i.end),onMdInput:this.onZoomSliderInput,onMdChange:this.onZoomSliderEvent,onMdDragStart:this.onZoomSliderEvent,onMdDragEnd:this.onZoomSliderEvent,onMdFocus:this.onZoomSliderEvent,onMdBlur:this.onZoomSliderEvent}),s("div",{class:"md-line-chart__zoom-pan",part:"zoom-pan",style:{insetInlineStart:`calc(${e(i.start)}% + var(--_zoom-pan-inset))`,inlineSize:`max(0px, calc(${e(i.end)-e(i.start)}% - 2 * var(--_zoom-pan-inset)))`},onPointerDown:this.onZoomPanDown}))}render(){const t=this.merged.xValues;const i=this.summary||l({title:this.label,chartType:this.area?"area":"line",seriesCount:this.series.length,xMin:t[0],xMax:t[t.length-1],locale:this.locale});const n=this.series.length===0&&!this.loading;return s(e,{key:"d9a1a408606f3561ab600a9e11978ed9f6fb5308",class:{"md-line-chart":true,"md-line-chart--empty":n,"md-line-chart--loading":this.loading,"md-line-chart--mounted":this.mounted,"md-line-chart--zoom-slider":this.zoomSliderOn,"md-line-chart--zoom-drag":this.zoomInside},role:"figure","aria-label":i,"aria-busy":this.loading?"true":null,style:this.heightProp?{blockSize:this.heightProp}:undefined,onPointerDown:this.onPlotPointerDown,onPointerMove:this.onPointerMove,onPointerUp:this.onPointerUp,onPointerCancel:this.onPointerUp,onDblClick:this.onPlotDblClick},s("header",{key:"7d3982cb8d3a9a69f95554943898a214d221c734",class:"md-line-chart__header",part:"header"},s("slot",{key:"fc1a089066350f40fa9c30b1984294017cd5dbbb",name:"header"})),s("div",{key:"e4818930f4ba554326a7e7720075fcf211fe17b0",class:"md-line-chart__canvas",part:"canvas",ref:t=>this.bindChartHost(t),tabindex:n?undefined:"0",role:n?undefined:"application","aria-label":n?undefined:this.labelPlot,onKeyDown:this.onPlotKeyDown,onBlur:this.onPlotBlur}),n&&s("div",{key:"d056e1034d7cbf6a61a46256c7f271cb0343ce7b",class:"md-line-chart__empty",part:"empty"},s("slot",{key:"d3af8ff195e4973432ae6fcf683e96f70bd1ccab",name:"empty"},this.labelEmpty)),this.loading&&s("div",{key:"3b26dd9069ebf17abd58d1c77e14828019e0a4e2",class:"md-line-chart__loading",part:"loading",role:"status"},s("slot",{key:"d36d29dafcc655bd30d7bcbac13ae6c18a594839",name:"loader"},s("slot",{key:"47153fb58d0e11132e466e724ab587caa576c263",name:"loading"},s("md-progress-indicator",{key:"60c443fa744ac9ab1ef58afad715799059009326",class:"md-line-chart__spinner",variant:"circular",indeterminate:true,label:this.loadingLabel}),s("span",{key:"505c3a377627e288969725420ac2db4b7329b57d",class:"md-line-chart__loading-text"},this.loadingLabel)))),this.dragBand&&Math.abs(this.dragBand.x2-this.dragBand.x1)>1&&s("div",{key:"8b496a56977f724f86c43167fffa3ff7d07caf75",class:"md-line-chart__zoom-band",part:"zoom-band",style:this.zoomBandStyle()}),this.zoomSliderOn&&this.renderZoomSlider(),s("footer",{key:"83a5255e217e7d74c2707d69d39b25c014ab3d1c",class:"md-line-chart__footer",part:"footer"},s("slot",{key:"9690127eb42f33b825d016f8cd85261cc62a74e7",name:"footer"})),s("div",{key:"9d31b766915dbc6031b5e2f43b69b949d45e4f44",class:"md-line-chart__a11y-table",ref:t=>this.bindA11yTableHost(t)}),s("div",{key:"2038de7cd5eca21af587cfa14a13edf08a73c750",class:"md-line-chart__live",role:"status","aria-live":"polite","aria-atomic":"true"},this.announcement))}get el(){return n(this)}static get watchers(){return{series:[{onAnyPropChange:0}],xAxis:[{onAnyPropChange:0}],yAxis:[{onAnyPropChange:0}],yAxes:[{onAnyPropChange:0}],curve:[{onAnyPropChange:0}],stack:[{onAnyPropChange:0}],area:[{onAnyPropChange:0}],showLine:[{onAnyPropChange:0}],legend:[{onAnyPropChange:0}],tooltip:[{onAnyPropChange:0}],grid:[{onAnyPropChange:0}],axisTicks:[{onAnyPropChange:0}],inverted:[{onAnyPropChange:0}],showLabels:[{onAnyPropChange:0}],seriesLabels:[{onAnyPropChange:0}],connectNulls:[{onAnyPropChange:0}],showMarks:[{onAnyPropChange:0}],lineWidth:[{onAnyPropChange:0}],markSize:[{onAnyPropChange:0}],label:[{onAnyPropChange:0}],subtitle:[{onAnyPropChange:0}],markLines:[{onAnyPropChange:0}],titleAlign:[{onAnyPropChange:0}],animation:[{onAnyPropChange:0}],animationDuration:[{onAnyPropChange:0}],tooltipRenderer:[{onAnyPropChange:0}],valueFormatter:[{onAnyPropChange:0}],loading:[{onLoadingChange:0}]}}};b.style=y();export{b as md_line_chart};
|
|
2
|
+
//# sourceMappingURL=p-4d82132d.entry.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["mdLineChartCss","MdLineChart","constructor","hostRef","this","label","titleAlign","series","curve","stack","connectNulls","showMarks","area","showLine","legend","tooltip","grid","axisTicks","inverted","showLabels","seriesLabels","zoom","locale","labelEmpty","labelPlot","labelPoint","labelZoomStart","labelZoomEnd","summary","noAnimation","animation","loading","loadingLabel","density","mounted","kbIndex","announcement","zoomWin","dragBand","grab","engine","ro","legendHidden","Map","mergeCache","bindChartHost","el","chartHost","bindA11yTableHost","a11yTableHost","onPlotPointerDown","e","zoomInside","button","insidePlot","x","hostX","id","pointerId","kind","win","x1","x2","target","composedPath","setPointerCapture","onPointerMove","g","plot","plotRect","Math","min","max","width","frac","trackFrac","clientX","originFrac","last","dataLength","span","end","start","delta","round","s","applyZoom","onPointerUp","band","abs","a","b","indexAtX","sort","m","n","onPlotKeyDown","rtl","getComputedStyle","direction","forward","back","next","key","mdAxisClick","emit","axisDetail","seriesValuesAt","preventDefault","moveKeyboardCursor","onPlotBlur","onPlotDblClick","resetZoom","onZoomPanDown","stopPropagation","onZoomSliderInput","valueStart","valueEnd","detail","onZoomSliderEvent","componentDidLoad","initChart","window","matchMedia","themeMql","themeListener","applyEngine","addEventListener","disconnectedCallback","disconnect","dispose","removeEventListener","undefined","onAnyPropChange","rebuildA11yTable","onLoadingChange","now","before","replay","resize","toDataURL","getInstance","makeEngine","mdReady","LineChartEngine","ResizeObserver","observe","buildEngineTheme","t","background","textColor","textColorMuted","axisLineColor","gridLineColor","gridColor","surface","fontFamily","labelSize","titleSize","seriesKeys","seen","map","i","base","get","set","rememberLegendToggle","seriesIndex","hidden","size","oldest","keys","value","delete","zoomSliderOn","merged","scale","xAxis","axis","data","c","out","normalizeSeriesX","reduce","acc","d","length","xValues","w","reset","mdZoom","startIndex","endIndex","setZoom","p","getScene","y","height","canvasOffset","canvas","host","getBoundingClientRect","box","left","top","zoomBandStyle","off","scene","xPositions","best","bestD","Infinity","forEach","px","clientY","focusIndex","xRaw","xText","valueFormatter","defaultValueFormatter","yFmt","v","toLocaleString","values","filter","sv","join","replace","mdHover","dataIndex","axisValue","seriesIndices","visibleSeriesIndices","sliderTrackRect","slider","shadowRoot","querySelector","r","track","raw","buildSpec","percentage","zw","cut","arr","slice","rebaseMap","rec","k","Object","entries","Number","remembered","toMerged","dashAt","dashAfter","color","resolveSeriesColor","pickPaletteColor","palette","dash","symbol","pointSymbols","remapIndexRecord","yAxisIndex","hollow","stroke","lineWidth","markSize","title","subtitle","markLines","ml","indexed","offscreen","_drop","xScale","xFormatter","xLabel","xHidden","xHideTicks","hideTicks","xDash","xGridDash","gridDash","xBands","resolveAxisBands","bands","yBands","yAxis","xBreaks","breaks","yBreaks","yScale","yMin","yMax","yFormatter","yTickFormatter","yLabel","yHidden","yHideTicks","yDash","yGridDash","yAxes","formatter","position","gridY","gridX","animationDuration","readMdChartTheme","setSpec","onHover","idx","onLegendClick","item","mdLegendClick","seriesId","selected","onPointClick","si","di","clickDetail","mdMarkerClick","onLineClick","mdLineClick","onAreaClick","mdAreaClick","onAxisClick","setHoverEnabled","setTooltip","render","tooltipRenderer","missingFormatter","trigger","own","ownIndex","datumY","nativeEvent","toOwn","hp","hoverPoints","h","byIndex","seriesValues","_","innerHTML","buildDataTableHtml","xAxisLabel","xAxisData","xValueFormatter","labels","tableLabels","renderZoomSlider","pct","fmt","String","class","part","exportparts","range","controlled","step","ariaLabelStart","ariaLabelEnd","valueStartText","valueEndText","onMdInput","onMdChange","onMdDragStart","onMdDragEnd","onMdFocus","onMdBlur","style","insetInlineStart","inlineSize","onPointerDown","buildChartSummary","chartType","seriesCount","xMin","xMax","empty","Host","role","heightProp","blockSize","onPointerCancel","onDblClick","name","ref","tabindex","onKeyDown","onBlur","variant","indeterminate"],"sources":["src/components/md-line-chart/md-line-chart.css?tag=md-line-chart&encapsulation=shadow","src/components/md-line-chart/md-line-chart.tsx"],"sourcesContent":["/* ==========================================================\n md-line-chart — Material Design 3 line chart\n Spec: https://m3.material.io/styles/charts/overview\n\n PUBLIC CSS CUSTOM PROPERTIES (override per-instance):\n --md-line-chart-block-size Chart block-size (default: aspect-ratio driven)\n --md-line-chart-min-block-size Floor for the chart's height (default: 160px)\n --md-line-chart-aspect-ratio Width:height ratio (default: 16/9)\n --md-line-chart-background Surface behind the chart (default: --md-sys-color-surface-container-low;\n set `transparent` to sit flush on the page)\n --md-line-chart-padding Inset padding around the canvas (default: 16px)\n --md-line-chart-shape Container corner radius (default: --md-sys-shape-corner-large)\n --md-line-chart-empty-color Empty-state text colour\n --md-line-chart-empty-background Empty-state surface (default: the chart's own background)\n --md-line-chart-empty-font Empty-state font FAMILY — not a font shorthand\n --md-line-chart-empty-font-size Empty-state font size (default: 14px)\n --md-line-chart-empty-icon-size Slotted Material Symbols icon size (default: 40px)\n --md-line-chart-zoom-size Height reserved for the zoom slider (default: 28px)\n --md-line-chart-zoom-track-color Zoom slider track colour (md-slider inactive track)\n --md-line-chart-zoom-window-color Zoom slider selected-window colour (md-slider active track)\n --md-line-chart-zoom-handle-color Zoom slider thumb + drag-band edge colour\n --md-line-chart-zoom-band-color Drag-to-zoom selection fill\n (the zoom slider is an md-slider — its own --md-slider-* variables also\n apply, scoped to .md-line-chart__zoom-slider)\n --md-chart-axis-color Axis-line colour (default: --md-sys-color-outline)\n --md-chart-grid-color Gridline colour (default: --md-sys-color-outline-variant)\n\n CSS PARTS:\n header Header slot wrapper (title, toolbar)\n canvas Plot canvas container\n empty Empty-state container\n zoom Zoom slider container\n zoom-slider The md-slider itself\n zoom-track Zoom slider track (forwarded)\n zoom-window Selected window / active track (forwarded)\n zoom-handle Zoom slider thumb (forwarded)\n zoom-pan Drag-to-pan grip over the window\n zoom-band Drag-to-zoom selection band\n footer Footer slot wrapper (caption, legend)\n\n SLOTS:\n header Renders above the plot\n empty Empty-state content (overrides default text)\n footer Renders below the plot\n ========================================================== */\n\n:host {\n --_block-size: var(--md-line-chart-block-size, auto);\n --_min-block-size: var(--md-line-chart-min-block-size, max(120px, calc(160px + var(--md-sys-density-scale, 0) * 8px)));\n --_aspect-ratio: var(--md-line-chart-aspect-ratio, 16 / 9);\n --_background: var(--md-line-chart-background, var(--md-sys-color-surface-container-low, #F7F2FA));\n --_padding: var(--md-line-chart-padding, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));\n --_shape: var(--md-line-chart-shape, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));\n --_empty-color: var(--md-line-chart-empty-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_empty-background: var(--md-line-chart-empty-background, var(--_background));\n --_empty-font: var(--md-line-chart-empty-font, var(--md-sys-typescale-body-medium-font-family, Roboto, sans-serif));\n --_empty-font-size: var(--md-line-chart-empty-font-size, var(--md-sys-typescale-body-medium-font-size, 14px));\n --_empty-icon-size: var(--md-line-chart-empty-icon-size, 40px);\n --_zoom-size: var(--md-line-chart-zoom-size, 28px);\n --_zoom-track-color: var(--md-line-chart-zoom-track-color, var(--md-sys-color-surface-container-highest, #E6E0E9));\n --_zoom-window-color: var(--md-line-chart-zoom-window-color, var(--md-sys-color-secondary-container, #E8DEF8));\n --_zoom-handle-color: var(--md-line-chart-zoom-handle-color, var(--md-sys-color-primary, #6750A4));\n --_zoom-band-color: var(--md-line-chart-zoom-band-color, color-mix(in srgb, var(--md-sys-color-primary, #6750A4) 16%, transparent));\n /* Clearance kept at each end of the pan grip so the thumbs stay grabbable. */\n --_zoom-pan-inset: 10px;\n\n display: block;\n position: relative;\n inline-size: 100%;\n block-size: var(--_block-size);\n min-block-size: var(--_min-block-size);\n background: var(--_background);\n padding: var(--_padding);\n border-radius: var(--_shape);\n box-sizing: border-box;\n /* aspect-ratio + 100% inline-size = fluid responsive sizing,\n no JS measurements needed for the host's box. ECharts\n inside still uses ResizeObserver to react to those CSS\n dimension changes. */\n aspect-ratio: var(--_aspect-ratio);\n}\n\n/* Header / footer wrappers — only take vertical space when\n their slot has content (Stencil slots are empty by default,\n so the `:not(:empty)` check works after slot assignment). */\n.md-line-chart__header,\n.md-line-chart__footer {\n display: contents;\n}\n\n.md-line-chart__header > slot[name='header']::slotted(*),\n.md-line-chart__footer > slot[name='footer']::slotted(*) {\n display: block;\n margin-block: 8px;\n}\n\n/* Plot surface — fills the host so ECharts has a measurable\n box to size against. `min-block-size: 0` lets it shrink\n inside a flex parent without overflowing. */\n.md-line-chart__canvas {\n position: absolute;\n inset: var(--_padding);\n min-block-size: 0;\n min-inline-size: 0;\n}\n\n/* Empty state — overlaid on the canvas so the host's box keeps its\n full responsive size and the message centres. */\n.md-line-chart__empty {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n padding: 24px;\n /* Mirrors the chart's own container — same surface and corner radius. The\n engine still draws a phantom 0-1 axis for an empty series, so an OPAQUE\n surface here masks that ghost grid instead of letting it show through\n behind the message. Column layout stacks a slotted icon above the text. */\n background: var(--_empty-background);\n border-radius: var(--_shape);\n color: var(--_empty-color);\n font-family: var(--_empty-font);\n font-size: var(--_empty-font-size);\n line-height: var(--md-sys-typescale-body-medium-line-height, 20px);\n pointer-events: none;\n text-align: center;\n}\n\n/* Loading state — the same opaque overlay as the empty state (it has to mask\n the phantom 0-1 axis the engine draws while there is no data), with the\n default indicator + label stacked in the middle. Slot `loading` replaces the\n content; the box keeps its size either way. */\n.md-line-chart__loading {\n position: absolute;\n inset: 0;\n z-index: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n padding: 24px;\n background: var(--_empty-background);\n border-radius: var(--_shape);\n color: var(--_empty-color);\n font-family: var(--_empty-font);\n font-size: var(--_empty-font-size);\n text-align: center;\n}\n\n.md-line-chart__spinner {\n /* Sized against the empty-state icon so a loading chart and an empty one\n read as the same family. */\n inline-size: var(--_empty-icon-size);\n block-size: var(--_empty-icon-size);\n}\n\n/* A slotted icon (e.g. a Material Symbols span) gets a sensible size and the\n muted empty-state colour without the consumer restyling it. */\n.md-line-chart__empty ::slotted(.material-symbols-outlined),\n.md-line-chart__empty ::slotted(.material-symbols-rounded),\n.md-line-chart__empty ::slotted(.material-symbols-sharp),\n.md-line-chart__empty ::slotted(.material-icons) {\n /* Document-level .material-symbols rules outrank ::slotted() in the cascade,\n so the size needs !important to win (same reason md-icon-button does it). */\n font-size: var(--_empty-icon-size) !important;\n line-height: 1;\n opacity: 0.55;\n}\n\n/* ── Zoom ──────────────────────────────────────────────────\n The slider sits inside the host's padding at the bottom, and the plot gives\n up exactly that much height (the canvas is inset by --_padding, so its bottom\n is pushed up by the slider's height). */\n:host(.md-line-chart--zoom-slider) .md-line-chart__canvas {\n bottom: calc(var(--_padding) + var(--_zoom-size));\n}\n\n:host(.md-line-chart--zoom-drag) .md-line-chart__canvas {\n /* Signals the plot is draggable; the band itself is pointer-transparent. */\n cursor: ew-resize;\n}\n\n.md-line-chart__zoom {\n position: absolute;\n inset-inline: var(--_padding);\n bottom: var(--_padding);\n block-size: var(--_zoom-size);\n display: flex;\n align-items: center;\n}\n\n/* The house slider draws the track and thumbs; the chart only maps its own\n public zoom tokens onto the slider's and sizes it to the reserved band. */\n.md-line-chart__zoom-slider {\n --md-slider-active-color: var(--_zoom-window-color);\n --md-slider-inactive-color: var(--_zoom-track-color);\n --md-slider-thumb-color: var(--_zoom-handle-color);\n /* Full-height thumbs in a band that is shorter than the MD3 default (44px),\n so the slider never overflows into the plot. */\n --md-slider-thumb-height: var(--_zoom-size);\n --md-slider-track-height: 12px;\n}\n\n/* Pan grip over the selected window: drag it to move the window without\n resizing. Inset at both ends (see renderZoomSlider) so a press near a thumb\n still reaches the slider's rail and resizes. */\n.md-line-chart__zoom-pan {\n position: absolute;\n inset-block: 0;\n z-index: 1;\n cursor: grab;\n touch-action: none;\n}\n\n.md-line-chart__zoom-pan:active {\n cursor: grabbing;\n}\n\n/* Live drag selection over the plot. */\n.md-line-chart__zoom-band {\n position: absolute;\n background: var(--_zoom-band-color);\n border-inline: 1px solid var(--_zoom-handle-color);\n pointer-events: none;\n}\n\n/* Screen-reader-only data table. Visually hidden but readable\n by AT; positioned absolute so it doesn't disturb layout.\n Uses the standard \"sr-only\" pattern (1px box with overflow\n hidden) — `display:none` would hide it from AT too. */\n/* Same visually-hidden technique as the data table below: readable by AT,\n invisible on screen, and out of the layout. */\n.md-line-chart__live {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* The plot takes focus for keyboard navigation, so it needs a visible ring —\n inset, because the canvas fills its box and an outset ring would be clipped\n by the host's padding. */\n/* The legend chips are engine-created buttons styled inline, and inline styles\n can't express :focus-visible — so their focus ring comes from here. Same\n neutral outline as the plot's, rather than the browser's blue default. */\n[part='legend'] button:focus-visible {\n /* Same ring md-button uses, so focus looks the same wherever it lands. */\n outline: 3px solid var(--md-sys-color-secondary, #625B71);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n.md-line-chart__canvas:focus-visible {\n /* Same ring as md-button. Inset, because the canvas fills its box and an\n outward ring would be clipped by the host's padding. */\n outline: 3px solid var(--md-sys-color-secondary, #625B71);\n outline-offset: -3px;\n border-radius: 4px;\n}\n\n.md-line-chart__a11y-table {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* Forced-colors (Windows high-contrast): we let ECharts use\n the system's CanvasText / Highlight colours by NOT pinning\n our own colour vars, so the chart inherits readable contrast\n automatically. Reduced-motion is handled in the theme reader\n (motion-duration → 0) so no animation overrides needed here. */\n@media (forced-colors: active) {\n :host {\n forced-color-adjust: auto;\n }\n}\n\n/* ==========================================================\n DENSITY (local override)\n Maps the local `density` prop onto the same --md-sys-density-scale signal a\n global `data-density` ancestor sets. Declared on :host, so a local rung wins\n over the inherited global one. Every density-sensitive value in this file\n derives from that single signal by calc — never add a fixed per-rung ladder.\n ========================================================== */\n:host([density='-1']) { --md-sys-density-scale: -1; }\n:host([density='-2']) { --md-sys-density-scale: -2; }\n:host([density='-3']) { --md-sys-density-scale: -3; }\n:host([density='-4']) { --md-sys-density-scale: -4; }\n","import {\n Component,\n Host,\n h,\n Prop,\n State,\n Event,\n EventEmitter,\n Element,\n Method,\n Watch,\n} from '@stencil/core';\nimport {\n buildChartSummary,\n buildDataTableHtml,\n datumY,\n defaultValueFormatter,\n normalizeSeriesX,\n pickPaletteColor,\n readMdChartTheme,\n remapIndexRecord,\n resolveAxisBands,\n resolveSeriesColor,\n LineChartEngine,\n type AxisSeriesValue,\n type EngineTheme,\n type LineChartSpec,\n type MdChartAnimation,\n type MdChartAxis,\n type MdChartAxisClickDetail,\n type MdChartAxisSeriesValue,\n type MdChartAxisValue,\n type MdChartClickDetail,\n type MdChartHoverDetail,\n type MdChartLegendPosition,\n type MdChartMarkLine,\n type MdChartStackMode,\n type MdChartTitleAlign,\n type MdChartTooltipRenderer,\n type MdChartTooltipTrigger,\n type MdChartXYSeries,\n type NormalizedSeriesX,\n} from '../../utils/charts';\n\n/**\n * md-line-chart — Material Design 3 line chart rendered by the\n * in-house chart engine (Canvas2D + a DOM text overlay). No\n * ECharts.\n *\n * Pattern parity with MUI X Charts:\n * • multi-series with per-series colour / label / curve\n * • category, time, value, log scales\n * • curve types: linear / smooth / monotone / step variants\n * • stacking: normal / percentage\n * • markers, area fills, gap bridging (`connectNulls`)\n * • legend with toggle + custom position\n * • hover crosshair + tooltip\n * • emits `mdMarkerClick`, `mdLineClick`, `mdAreaClick`, `mdAxisClick`,\n * `mdLegendClick`, `mdHover`\n *\n * MD3 expressive layer on top:\n * • palette resolves to `--md-sys-color-*` tokens\n * • dark theme + brand re-themes via CSS variables only\n * • a11y: role=\"figure\" + screen-reader-only data table\n * • fully responsive via ResizeObserver\n */\n@Component({\n tag: 'md-line-chart',\n styleUrl: 'md-line-chart.css',\n shadow: true,\n})\nexport class MdLineChart {\n @Element() el!: HTMLElement;\n\n /** Optional chart title rendered above the plot. */\n @Prop() label: string = '';\n\n /** Optional sub-title rendered under the title in the muted text colour. */\n @Prop() subtitle: string | undefined;\n\n /** Vertical reference lines across the plot (e.g. a \"current time\" divider). */\n @Prop() markLines: MdChartMarkLine[] | undefined;\n\n /** Title alignment over the plot: `start` (left), `center`, or `end` (right). */\n @Prop({ attribute: 'title-align' }) titleAlign: MdChartTitleAlign = 'start';\n\n /**\n * Series array. Each entry is one line. Empty → empty state.\n *\n * `data` is either a bare list of y values, positioned by index against\n * `xAxis.data`, or a list of points carrying their own x —\n * `{ x: '2021-11-13', y: 0.12 }` / `['2021-11-13', 0.12]`. Points are what\n * irregular data needs: uneven sampling, or several series measured on\n * completely different dates. Set `xAxis.scale = 'time'` (or `'value'`) so\n * the gaps render proportionally; series carrying their own x need no\n * `xAxis.data` at all.\n */\n @Prop() series: MdChartXYSeries[] = [];\n\n /** X-axis configuration. */\n @Prop() xAxis: MdChartAxis | undefined;\n\n /** Y-axis configuration. */\n @Prop() yAxis: MdChartAxis | undefined;\n\n /**\n * Multiple independent value (y) axes. When set (non-empty), each series is\n * measured against `yAxes[series.yAxisIndex ?? 0]`, and the axes stack outward\n * from the plot (first → left, rest → right, or per each axis' `position`).\n * Supersedes the single `yAxis`. Each axis keeps its own `min`/`max`/`scale`/\n * `valueFormatter`/`label`.\n */\n @Prop() yAxes: MdChartAxis[] | undefined;\n\n /** Default curve interpolation. Overridable per-series. */\n @Prop() curve: 'linear' | 'smooth' | 'monotone' | 'step' | 'step-before' | 'step-middle' = 'smooth';\n\n /** Stacking strategy. */\n @Prop() stack: MdChartStackMode = 'none';\n\n /** Whether `null` values are bridged with a straight line. */\n @Prop({ attribute: 'connect-nulls' }) connectNulls: boolean = false;\n\n /** Show data-point markers on every series by default. */\n @Prop({ attribute: 'show-marks' }) showMarks: boolean = false;\n\n /** Line stroke width in px, for every series. Default 2.5; a per-series\n * `series[].lineWidth` overrides it. */\n @Prop({ attribute: 'line-width' }) lineWidth?: number;\n /** Marker RADIUS in px, for every series. Overrides the per-symbol default; a\n * per-series `series[].markSize` wins. */\n @Prop({ attribute: 'mark-size' }) markSize?: number;\n\n /** Render the line area as a filled gradient below the line. */\n @Prop() area: boolean = false;\n\n /**\n * Draw the line for each series. Default `true`. Set `false` for a fill-only\n * chart (with `area`) or a marks-only chart — handy when a high `fillOpacity`\n * makes the same-coloured line vanish into the fill. A per-series\n * `series[].stroke` still wins over this.\n */\n @Prop({ attribute: 'show-line' }) showLine: boolean = true;\n\n /** Legend position. `'none'` hides the legend. */\n @Prop({ reflect: true }) legend: MdChartLegendPosition | 'none' = 'top-end';\n\n /** Tooltip interaction model. */\n @Prop() tooltip: MdChartTooltipTrigger = 'axis';\n\n /** Gridlines: horizontal (y ticks), vertical (x ticks), both, or none. */\n @Prop() grid: 'none' | 'horizontal' | 'vertical' | 'both' = 'horizontal';\n\n /** Draw small perpendicular tick marks on the axes. */\n @Prop({ attribute: 'axis-ticks' }) axisTicks: boolean = false;\n\n /** Transpose the axes — the x-axis data runs vertically and the values run\n * horizontally (e.g. a temperature-by-altitude spline). Best with `curve=\"smooth\"`. */\n @Prop() inverted: boolean = false;\n\n /** Print each point's value as a data label beside its marker. */\n @Prop({ attribute: 'show-labels' }) showLabels: boolean = false;\n\n /** Label each series at its last point with its name (follows the line end). */\n @Prop({ attribute: 'series-labels' }) seriesLabels: boolean = false;\n\n /**\n * Interactive zoom over the x range.\n * • `inside` — drag horizontally across the plot to zoom into that span;\n * double-click anywhere in the plot to reset.\n * • `slider` — an `md-slider` in range mode under the plot: drag either\n * thumb to resize the window, click the track to jump the nearest thumb,\n * drag the window itself to pan. Thumbs are focusable and take\n * Arrow/Home/End/PageUp/PageDown.\n * • `both` — both of the above.\n *\n * Zoom is a *view* over the data: `series`/`xAxis` are untouched, and\n * `mdHover`/`mdMarkerClick` keep reporting absolute indices into your data.\n */\n @Prop() zoom: 'none' | 'inside' | 'slider' | 'both' = 'none';\n\n /**\n * BCP-47 locale for the DEFAULT number / date formatting — axis ticks,\n * tooltip values and the screen-reader table. Empty follows the browser.\n * An explicit `valueFormatter` / `xAxis.valueFormatter` always wins, so a\n * consumer that formats its own values is unaffected.\n */\n @Prop() locale: string = '';\n\n /**\n * Text shown when there is no data. The `empty` slot still overrides it —\n * this is the prop form, for handing a string straight from a dictionary.\n */\n @Prop({ attribute: 'label-empty' }) labelEmpty: string = 'No data to display';\n\n /**\n * Instructions announced when the plot receives keyboard focus. The plot is\n * focusable so a keyboard user can walk the data with the arrow keys; this\n * is what tells them so.\n */\n @Prop({ attribute: 'label-plot' }) labelPlot: string =\n 'Chart data. Use the arrow keys to move between points, Home and End for the first and last, Escape to leave.';\n\n /**\n * Template for the live announcement made as keyboard focus moves. `%x%` is\n * the axis value and `%values%` the series readings at it.\n */\n @Prop({ attribute: 'label-point' }) labelPoint: string = '%x%: %values%';\n\n /** Accessible label for the zoom slider's start thumb. */\n @Prop({ attribute: 'label-zoom-start' }) labelZoomStart: string = 'Zoom range start';\n\n /** Accessible label for the zoom slider's end thumb. */\n @Prop({ attribute: 'label-zoom-end' }) labelZoomEnd: string = 'Zoom range end';\n\n /**\n * Replaces the generated `aria-label` outright. The default summary is\n * assembled in English (\"Revenue, Line chart, with 2 series, from Jan to\n * Dec.\"); rather than translate it piecewise, hand over the whole sentence\n * built in your own language.\n */\n @Prop() summary: string = '';\n\n /**\n * Translatable chrome for the screen-reader data table. `%shown%` and\n * `%total%` are substituted in `truncated`.\n */\n @Prop() tableLabels?: { x?: string; index?: string; series?: string; truncated?: string };\n\n /**\n * Format raw Y values for tooltips / a11y table.\n *\n * The tooltip also asks it about series with NO value at the hovered x —\n * `null` when the series has a null datum there, `undefined` when it has no\n * datum at all. Return `''` (or leave those cases unhandled) to keep the\n * default behaviour of omitting the series; return a string to show a row\n * for it — e.g. `(v) => (v === null ? 'no reading' : v === undefined ? '—' : v + ' m')`.\n */\n @Prop() valueFormatter?: (value: number | null | undefined) => string;\n\n /**\n * Replace the tooltip's content with your own. Receives everything the chart\n * knows about the hovered x — the axis value + its formatted label, and per\n * visible series the index, label, colour, raw and formatted value, and\n * whether it is the emphasised one — split into `series` (has a reading here)\n * and `missing` (does not).\n *\n * Return a DOM `Node` (what React / Vue / Angular renderers produce), a\n * string (inserted as TEXT, never parsed as markup), `{ unsafeHtml }` to opt\n * into raw HTML, `undefined` to fall back to the built-in tooltip, or `null`\n * for no tooltip at this x. The engine keeps positioning it, and it is still\n * the `tooltip` CSS part.\n */\n @Prop() tooltipRenderer?: MdChartTooltipRenderer;\n\n /** Force a specific height (CSS length). */\n @Prop({ attribute: 'height' }) heightProp?: string;\n\n /** Disable all animation (shorthand for `animation=\"none\"`). */\n @Prop({ attribute: 'no-animation' }) noAnimation: boolean = false;\n\n /** Entry-animation variant: `expressive` (default), `grow`, `fade`, `draw`, or `none`. */\n @Prop() animation: MdChartAnimation = 'expressive';\n\n /** Entry-animation duration override in ms (≤ 0 disables). */\n @Prop({ attribute: 'animation-duration' }) animationDuration?: number;\n\n\n /**\n * Data is still on its way — the chart covers the plot with a loader instead\n * of drawing an empty (or stale) axis, and marks itself `aria-busy`.\n *\n * Set it while the fetch is in flight and clear it when `series` arrives; the\n * entry animation replays on the way out, so the data draws itself in rather\n * than appearing fully formed. Slot `loading` to replace the default\n * indicator with your own skeleton.\n */\n @Prop({ reflect: true }) loading: boolean = false;\n\n /** Accessible + visible text under the loader. */\n @Prop({ attribute: 'loading-label' }) loadingLabel: string = 'Loading chart…';\n\n /**\n * Local density rung. Drives the same `--md-sys-density-scale` signal that a\n * global `data-density` ancestor sets, so a local value simply overrides the\n * inherited one. 0 = default, -4 = ultra-compact.\n */\n @Prop({ reflect: true }) density: 0 | -1 | -2 | -3 | -4 = 0;\n\n /** Fires on marker click. `dataIndex` addresses the clicked series' own\n * `data` array (its point index, for series that carry their own x). */\n @Event() mdMarkerClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when a series' drawn line is clicked *between* its data points (a\n * click on a point emits `mdMarkerClick` instead). `dataIndex` is the point\n * the click is nearest along x. */\n @Event() mdLineClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when a series' filled area is clicked (`area` charts only) — the\n * region between that series' line and its baseline, excluding its line and\n * points. `dataIndex` is the point the click is nearest along x. */\n @Event() mdAreaClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when the plot background is clicked (inside the plot, but not on a\n * mark, line or area): the nearest x position plus every visible series'\n * value there. */\n @Event() mdAxisClick!: EventEmitter<MdChartAxisClickDetail>;\n\n /** Fires when a legend entry is clicked. */\n @Event() mdLegendClick!: EventEmitter<{ seriesIndex: number; seriesId?: string; selected: boolean }>;\n\n /** Fires (throttled to rAF) as the pointer crosses the plot. */\n @Event() mdHover!: EventEmitter<MdChartHoverDetail>;\n\n /** Fires after the chart finishes its initial render. */\n @Event() mdReady!: EventEmitter<void>;\n\n /** Fires when the zoom window changes (drag, slider or `setZoom`/`resetZoom`). */\n @Event() mdZoom!: EventEmitter<{ startIndex: number; endIndex: number; reset: boolean }>;\n\n @State() private mounted = false;\n\n /** Index the keyboard cursor sits on, or -1 when the plot isn't focused. */\n @State() private kbIndex = -1;\n\n /** Text for the aria-live region — what a screen reader speaks on move. */\n @State() private announcement = '';\n\n /** Visible index window, or null for the full range. */\n @State() private zoomWin: { start: number; end: number } | null = null;\n\n /** Live drag rectangle (plot-relative px) while selecting a range to zoom. */\n @State() private dragBand: { x1: number; x2: number } | null = null;\n\n /**\n * Pointer id + origin of an in-progress gesture: `band` is a drag across the\n * plot, `pan` is a drag of the zoom window. (Resizing the window is the\n * slider's own gesture — see `renderZoomSlider`.)\n */\n private grab: { id: number; kind: 'band' | 'pan'; x: number; win: { start: number; end: number } } | null = null;\n\n private engine: LineChartEngine | null = null;\n private ro: ResizeObserver | null = null;\n private chartHost?: HTMLDivElement;\n private a11yTableHost?: HTMLDivElement;\n private themeMql?: MediaQueryList;\n private themeListener?: () => void;\n /**\n * Legend-toggle memory, keyed by series identity (id → label → position).\n * A legend click self-toggles the engine, but a live-updating consumer that\n * re-feeds `series` every frame (e.g. a line-race) would otherwise rebuild the\n * spec with the prop's `hidden` and lose the toggle. We remember the toggle\n * here and re-apply it in `buildSpec`, so visibility survives data updates\n * (ECharts-style), while an explicit `series[i].hidden` prop still wins.\n */\n private legendHidden = new Map<string, boolean>();\n\n /** Memo for {@link merged}, keyed on the identity of what it was built from. */\n private mergeCache: {\n series: unknown;\n axis: unknown;\n scale: string;\n out: NormalizedSeriesX;\n } | null = null;\n\n // ─────────────────── lifecycle ───────────────────\n\n componentDidLoad() {\n this.initChart();\n if (typeof window !== 'undefined' && window.matchMedia) {\n this.themeMql = window.matchMedia('(prefers-color-scheme: dark)');\n this.themeListener = () => this.applyEngine();\n this.themeMql.addEventListener?.('change', this.themeListener);\n }\n }\n\n disconnectedCallback() {\n this.ro?.disconnect();\n this.ro = null;\n this.engine?.dispose();\n this.engine = null;\n if (this.themeMql && this.themeListener) {\n this.themeMql.removeEventListener?.('change', this.themeListener);\n this.themeListener = undefined;\n this.themeMql = undefined;\n }\n }\n\n @Watch('series')\n @Watch('xAxis')\n @Watch('yAxis')\n @Watch('yAxes')\n @Watch('curve')\n @Watch('stack')\n @Watch('area')\n @Watch('showLine')\n @Watch('legend')\n @Watch('tooltip')\n @Watch('grid')\n @Watch('axisTicks')\n @Watch('inverted')\n @Watch('showLabels')\n @Watch('seriesLabels')\n @Watch('connectNulls')\n @Watch('showMarks')\n @Watch('lineWidth')\n @Watch('markSize')\n @Watch('label')\n @Watch('subtitle')\n @Watch('markLines')\n @Watch('titleAlign')\n @Watch('animation')\n @Watch('animationDuration')\n @Watch('tooltipRenderer')\n @Watch('valueFormatter')\n onAnyPropChange() {\n this.applyEngine();\n this.rebuildA11yTable();\n }\n\n /**\n * Coming OUT of the loading state, replay the entry motion so the data that\n * just arrived draws itself in instead of appearing fully formed behind the\n * fading loader. (Going in needs nothing — the loader covers the plot.)\n */\n @Watch('loading')\n onLoadingChange(now: boolean, before: boolean) {\n if (before && !now) this.engine?.replay();\n }\n\n // ─────────────────── public API ───────────────────\n\n /** Force a resize — useful after the chart was hidden then shown. */\n @Method()\n async resize(): Promise<void> {\n this.engine?.resize();\n }\n\n /** Replay the entry animation from the start (uses the current `animation`). */\n @Method()\n async replay(): Promise<void> {\n this.engine?.replay();\n }\n\n /** Render the current frame to a PNG data URL. */\n @Method()\n async toDataURL(): Promise<string> {\n return this.engine?.toDataURL('image/png') ?? '';\n }\n\n /** Return the underlying chart engine for advanced cases. */\n @Method()\n async getInstance(): Promise<LineChartEngine | null> {\n return this.engine;\n }\n\n // ─────────────────── internals ───────────────────\n\n private bindChartHost = (el?: HTMLDivElement) => {\n this.chartHost = el;\n };\n\n private bindA11yTableHost = (el?: HTMLDivElement) => {\n this.a11yTableHost = el;\n };\n\n private initChart() {\n this.makeEngine();\n this.applyEngine();\n this.rebuildA11yTable();\n this.mounted = true;\n this.mdReady.emit();\n }\n\n /** (Re)create the engine on the selected backend + wire its ResizeObserver. */\n private makeEngine() {\n if (!this.chartHost) return;\n this.ro?.disconnect();\n this.ro = null;\n this.engine?.dispose();\n try {\n this.engine = new LineChartEngine(this.chartHost);\n } catch {\n // No usable DOM (mock-doc / SSR / no canvas). Stay mounted;\n // ResizeObserver / a prop change will retry in a real browser.\n this.engine = null;\n }\n if (this.engine && typeof ResizeObserver !== 'undefined') {\n this.ro = new ResizeObserver(() => this.engine?.resize());\n this.ro.observe(this.chartHost);\n }\n }\n\n\n private buildEngineTheme(t: ReturnType<typeof readMdChartTheme>): EngineTheme {\n return {\n background: t.background,\n textColor: t.textColor,\n textColorMuted: t.textColorMuted,\n axisLineColor: t.axisLineColor,\n gridLineColor: t.gridColor,\n surface: t.surface,\n fontFamily: t.fontFamily,\n labelSize: t.labelSize,\n titleSize: t.titleSize,\n };\n }\n\n /**\n * Collision-free identity per series for the legend-toggle memory. Prefers a\n * consumer `id`, else `label`, else positional index; duplicates of the same\n * base are disambiguated by occurrence (`#1`, `#2`, …) so two same-labelled\n * series never share one memory slot (a click on one would otherwise hide\n * both). A unique id/label stays stable across a re-fed reorder.\n */\n private seriesKeys(): string[] {\n const seen = new Map<string, number>();\n return this.series.map((s, i) => {\n const base = s.id != null ? `id:${s.id}` : s.label != null ? `label:${s.label}` : `pos:${i}`;\n const n = seen.get(base) ?? 0;\n seen.set(base, n + 1);\n return n === 0 ? base : `${base}#${n}`;\n });\n }\n\n /** Record a legend toggle so `buildSpec` re-applies it across series re-feeds. */\n private rememberLegendToggle(seriesIndex: number, hidden: boolean): void {\n const key = this.seriesKeys()[seriesIndex];\n if (key == null) return;\n this.legendHidden.set(key, hidden);\n // Backstop against unbounded growth (only legend clicks add entries, so this\n // realistically never trips): evict the oldest toggle.\n if (this.legendHidden.size > 256) {\n const oldest = this.legendHidden.keys().next().value as string;\n this.legendHidden.delete(oldest);\n }\n }\n\n // ─────────────────── zoom ───────────────────\n\n private get zoomInside(): boolean {\n return this.zoom === 'inside' || this.zoom === 'both';\n }\n\n private get zoomSliderOn(): boolean {\n return this.zoom === 'slider' || this.zoom === 'both';\n }\n\n /**\n * Series merged onto one x axis (see `utils/charts/xy.ts`). Pass-through\n * unless a series carries its own x, and memoised on the identity of the\n * inputs so a render / hover / zoom trio doesn't re-merge the same feed.\n */\n private get merged(): NormalizedSeriesX {\n const scale = this.xAxis?.scale ?? 'category';\n const axis = this.xAxis?.data;\n const c = this.mergeCache;\n if (c && c.series === this.series && c.axis === axis && c.scale === scale) return c.out;\n const out = normalizeSeriesX(this.series ?? [], axis, scale);\n this.mergeCache = { series: this.series, axis, scale, out };\n return out;\n }\n\n /** Number of datapoints along x — the longest series, or the axis if longer. */\n private dataLength(): number {\n const m = this.merged;\n const s = m.data.reduce((acc, d) => Math.max(acc, d?.length ?? 0), 0);\n return Math.max(s, m.xValues.length);\n }\n\n /** Current window, defaulted to the full range and clamped to the data. */\n private win(): { start: number; end: number } {\n const last = Math.max(0, this.dataLength() - 1);\n const w = this.zoomWin;\n if (!w) return { start: 0, end: last };\n // Keep at least two points visible, else there is no line to draw.\n const start = Math.min(Math.max(0, w.start), Math.max(0, last - 1));\n return { start, end: Math.min(Math.max(start + 1, w.end), last) };\n }\n\n private applyZoom(start: number, end: number, reset = false): void {\n const last = Math.max(0, this.dataLength() - 1);\n const s = Math.min(Math.max(0, Math.round(start)), Math.max(0, last - 1));\n const e = Math.min(Math.max(s + 1, Math.round(end)), last);\n this.zoomWin = reset ? null : { start: s, end: e };\n this.applyEngine();\n this.rebuildA11yTable();\n this.mdZoom.emit({ startIndex: reset ? 0 : s, endIndex: reset ? last : e, reset });\n }\n\n /** Zoom to an absolute index range. */\n @Method()\n async setZoom(startIndex: number, endIndex: number): Promise<void> {\n this.applyZoom(startIndex, endIndex);\n }\n\n /** Drop the zoom window and show the full range. */\n @Method()\n async resetZoom(): Promise<void> {\n this.applyZoom(0, 0, true);\n }\n\n /**\n * Plot rect in CANVAS coordinates, from the live scene.\n *\n * The engine lays the scene out relative to the canvas box, which the host's\n * padding insets from the host box — so canvas and host space differ by that\n * padding. Everything that compares against the scene (`indexAtX` reads\n * `scene.xPositions`, which is canvas-space too) converts the pointer INTO\n * this space via `hostX`; only the drag band, positioned against the host,\n * converts back out.\n */\n private plotRect(): { x: number; y: number; width: number; height: number } | null {\n const p = this.engine?.getScene()?.plot;\n return p ? { x: p.x, y: p.y, width: p.width, height: p.height } : null;\n }\n\n /** Offset of the canvas box inside the host box — canvas space → host space. */\n private canvasOffset(): { x: number; y: number } {\n const canvas = this.chartHost;\n if (!canvas) return { x: 0, y: 0 };\n const host = this.el.getBoundingClientRect();\n const box = canvas.getBoundingClientRect();\n return { x: box.left - host.left, y: box.top - host.top };\n }\n\n /** Drag-band geometry, converted from canvas space back out to host space. */\n private zoomBandStyle(): { [key: string]: string } | undefined {\n const plot = this.plotRect();\n if (!this.dragBand || !plot) return undefined;\n const off = this.canvasOffset();\n const { x1, x2 } = this.dragBand;\n return {\n left: `${off.x + Math.min(x1, x2)}px`,\n width: `${Math.abs(x2 - x1)}px`,\n top: `${off.y + plot.y}px`,\n height: `${plot.height}px`,\n };\n }\n\n /** Map a canvas-relative x to the nearest ABSOLUTE data index. */\n private indexAtX(hostX: number): number {\n const scene = this.engine?.getScene();\n const w = this.win();\n if (!scene?.xPositions?.length) return w.start;\n let best = 0;\n let bestD = Infinity;\n scene.xPositions.forEach((px, i) => {\n const d = Math.abs(px - hostX);\n if (d < bestD) {\n bestD = d;\n best = i;\n }\n });\n return w.start + best;\n }\n\n /** Pointer x in CANVAS coordinates — the space `plotRect`/`xPositions` use. */\n private hostX(e: MouseEvent): number {\n return e.clientX - (this.chartHost ?? this.el).getBoundingClientRect().left;\n }\n\n /** Is the event over the plot itself (as opposed to the header, zoom slider, footer)? */\n private insidePlot(e: MouseEvent): boolean {\n const plot = this.plotRect();\n if (!plot) return false;\n const box = (this.chartHost ?? this.el).getBoundingClientRect();\n const x = e.clientX - box.left;\n const y = e.clientY - box.top;\n return x >= plot.x && x <= plot.x + plot.width && y >= plot.y && y <= plot.y + plot.height;\n }\n\n private onPlotPointerDown = (e: PointerEvent) => {\n if (!this.zoomInside || e.button !== 0 || this.grab) return;\n if (!this.insidePlot(e)) return;\n const x = this.hostX(e);\n this.grab = { id: e.pointerId, kind: 'band', x, win: this.win() };\n this.dragBand = { x1: x, x2: x };\n // Capture so the gesture survives the pointer leaving the plot — on the\n // element really under the pointer, NOT on `e.target`. This listener sits on\n // the host, so the shadow-internal target is retargeted to the host itself,\n // and capturing there sends the whole gesture — including the `click` that\n // closes it — to the host, where the engine's plot canvas never sees it. That\n // silently killed every chart click event whenever zoom was on.\n const target = (e.composedPath?.()[0] as HTMLElement | undefined) ?? (e.target as HTMLElement);\n target.setPointerCapture?.(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent) => {\n const g = this.grab;\n if (!g || g.id !== e.pointerId) return;\n if (g.kind === 'band') {\n const plot = this.plotRect();\n if (!plot) return;\n this.dragBand = { x1: g.x, x2: Math.min(Math.max(this.hostX(e), plot.x), plot.x + plot.width) };\n return;\n }\n // Pan: shift the window by the pointer's travel along the slider track,\n // keeping its span. Fractions of the full range, so it tracks the thumbs.\n const frac = this.trackFrac(e.clientX);\n const originFrac = this.trackFrac(g.x);\n if (frac == null || originFrac == null) return;\n const last = Math.max(1, this.dataLength() - 1);\n const span = g.win.end - g.win.start;\n const delta = Math.round((frac - originFrac) * last);\n const s = Math.min(Math.max(0, g.win.start + delta), last - span);\n this.applyZoom(s, s + span);\n };\n\n private onPointerUp = (e: PointerEvent) => {\n const g = this.grab;\n if (!g || g.id !== e.pointerId) return;\n this.grab = null;\n const band = this.dragBand;\n this.dragBand = null;\n if (g.kind !== 'band' || !band) return;\n // A tiny drag is a click, not a zoom — leave the view alone so marker\n // clicks and tooltips keep working.\n if (Math.abs(band.x2 - band.x1) < 8) return;\n // In RTL the plot is mirrored, so the LEFT edge of the band is the LATER\n // index — order by index, not by pixel, or the window comes out reversed.\n const [a, b] = [this.indexAtX(band.x1), this.indexAtX(band.x2)].sort((m, n) => m - n);\n if (b - a >= 1) this.applyZoom(a, b);\n };\n\n /**\n * Walk the data with the keyboard. The chart's information was previously\n * reachable only by hovering, which no keyboard or screen-reader user can\n * do; this gives them the same crosshair, tooltip and values.\n *\n * Arrow keys follow the READING direction, so in RTL, Left advances — the\n * plot is mirrored and an arrow that moved \"back\" visually would be wrong.\n */\n private onPlotKeyDown = (e: KeyboardEvent) => {\n const last = Math.max(0, this.dataLength() - 1);\n if (last < 0) return;\n const rtl = typeof getComputedStyle === 'function' && getComputedStyle(this.el).direction === 'rtl';\n const forward = rtl ? 'ArrowLeft' : 'ArrowRight';\n const back = rtl ? 'ArrowRight' : 'ArrowLeft';\n let next = this.kbIndex;\n switch (e.key) {\n case forward:\n next = this.kbIndex < 0 ? 0 : Math.min(last, this.kbIndex + 1);\n break;\n case back:\n next = this.kbIndex < 0 ? last : Math.max(0, this.kbIndex - 1);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = last;\n break;\n case 'Escape':\n if (this.kbIndex < 0) return;\n next = -1;\n break;\n case 'Enter':\n case ' ':\n if (this.kbIndex < 0) return;\n // Keyboard parity with clicking the plot background: the focus is on an\n // x position, not one series, which is exactly what mdAxisClick reports.\n this.mdAxisClick.emit(this.axisDetail(this.kbIndex, this.seriesValuesAt(this.kbIndex), e));\n e.preventDefault();\n return;\n default:\n return;\n }\n e.preventDefault();\n this.moveKeyboardCursor(next);\n };\n\n private onPlotBlur = () => {\n if (this.kbIndex >= 0) this.moveKeyboardCursor(-1);\n };\n\n /** Move the keyboard cursor, mirroring it into the hover UI and the live region. */\n private moveKeyboardCursor(next: number) {\n this.kbIndex = next;\n this.engine?.focusIndex(next);\n if (next < 0) {\n this.announcement = '';\n return;\n }\n const m = this.merged;\n const xRaw = m.xValues[next];\n const xText = this.xAxis?.valueFormatter\n ? this.xAxis.valueFormatter(xRaw)\n : defaultValueFormatter(xRaw ?? next + 1, this.locale);\n const yFmt = (v: number) =>\n this.valueFormatter ? this.valueFormatter(v) : v.toLocaleString(this.locale || undefined);\n const values = this.seriesValuesAt(next)\n .filter((sv: AxisSeriesValue) => sv.value != null)\n .map((sv: AxisSeriesValue) => `${sv.label} ${yFmt(sv.value as number)}`)\n .join(', ');\n this.announcement = this.labelPoint.replace('%x%', xText).replace('%values%', values);\n this.mdHover.emit({ dataIndex: next, axisValue: xRaw, seriesIndices: this.visibleSeriesIndices() });\n }\n\n private onPlotDblClick = (e: MouseEvent) => {\n // Plot only: a double-click on the zoom slider is two track clicks, not a\n // request to throw the window away.\n if (this.zoomInside && this.zoomWin && this.insidePlot(e)) this.resetZoom();\n };\n\n /**\n * The zoom slider's track box. `md-slider` maps 0→100% across its own host\n * box (surface and rail both flex to fill it), so the host rect *is* the\n * track — measuring it keeps the pan gesture in step with the thumbs.\n */\n private sliderTrackRect(): { left: number; width: number; rtl: boolean } | null {\n const slider = this.el.shadowRoot?.querySelector('.md-line-chart__zoom-slider');\n if (!slider) return null;\n const r = slider.getBoundingClientRect();\n if (!r.width) return null;\n return { left: r.left, width: r.width, rtl: getComputedStyle(this.el).direction === 'rtl' };\n }\n\n /** Client x → fraction along the zoom track (RTL-aware, as md-slider is). */\n private trackFrac(clientX: number): number | null {\n const track = this.sliderTrackRect();\n if (!track) return null;\n const raw = (clientX - track.left) / track.width;\n return Math.min(Math.max(track.rtl ? 1 - raw : raw, 0), 1);\n }\n\n private onZoomPanDown = (e: PointerEvent) => {\n if (e.button !== 0) return;\n // Keep it away from the plot-drag handler on the host, and from the\n // slider's own rail (which would resize instead of pan).\n e.stopPropagation();\n e.preventDefault();\n this.grab = { id: e.pointerId, kind: 'pan', x: e.clientX, win: this.win() };\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\n };\n\n /** md-slider drives the window while a thumb moves (continuous). */\n private onZoomSliderInput = (e: CustomEvent<{ valueStart?: number; valueEnd?: number }>) => {\n // md-slider's events are composed, so they would surface on the chart's own\n // host and look like chart events to a consumer. Stop them here.\n e.stopPropagation();\n const { valueStart, valueEnd } = e.detail ?? {};\n if (valueStart == null || valueEnd == null) return;\n this.applyZoom(valueStart, valueEnd);\n };\n\n /** Swallow the slider's remaining composed events (see above). mdInput has\n * already applied the window, so the commit needs no second applyZoom. */\n private onZoomSliderEvent = (e: Event) => e.stopPropagation();\n\n private buildSpec(t: ReturnType<typeof readMdChartTheme>): LineChartSpec {\n const percentage = this.stack === 'percentage';\n const yFmt = (v: number) =>\n this.valueFormatter ? this.valueFormatter(v) : v.toLocaleString(this.locale || undefined);\n // Re-apply remembered legend toggles by identity. We do NOT prune here: a\n // series that blips out of the feed for a frame must keep its toggle when it\n // returns. Growth is bounded in rememberLegendToggle instead.\n const keys = this.seriesKeys();\n // Zoom is a view: slice what the engine draws, leave `this.series` alone.\n // Anything index-addressed (dashAfter, pointSymbols, markIndices, markLines\n // on a category axis) is rebased into window coordinates, and anything that\n // falls outside the window is dropped.\n const zw = this.zoomWin ? this.win() : null;\n const cut = <T,>(arr: T[] | undefined): T[] | undefined =>\n arr && zw ? arr.slice(zw.start, zw.end + 1) : arr;\n const rebaseMap = <T,>(rec: Record<number, T> | undefined): Record<number, T> | undefined => {\n if (!rec || !zw) return rec;\n const out: Record<number, T> = {};\n for (const [k, v] of Object.entries(rec)) {\n const i = Number(k) - zw.start;\n if (i >= 0 && i <= zw.end - zw.start) out[i] = v;\n }\n return out;\n };\n // Series that carry their own x are merged onto one axis first; index-\n // addressed options (pointSymbols, dashAfter) are rebased onto it before\n // the zoom window rebases them again.\n const m = this.merged;\n const series = this.series.map((s, i) => {\n const key = keys[i];\n const remembered = this.legendHidden.get(key);\n const toMerged = m.toMerged[i];\n const dashAt = s.dashAfter != null && toMerged ? toMerged[s.dashAfter] : s.dashAfter;\n // An explicit `hidden` prop takes control: it wins AND clears the legend\n // memory, so the consumer's value sticks across later omitted-hidden frames\n // (a 'show all' reset isn't silently re-hidden on the next frame).\n if (s.hidden !== undefined) this.legendHidden.delete(key);\n return {\n label: s.label ?? `Series ${i + 1}`,\n color: resolveSeriesColor(this.el, s.color, pickPaletteColor(t.palette, i)),\n data: cut(m.data[i]) ?? m.data[i] ?? [],\n curve: s.curve ?? this.curve,\n connectNulls: s.connectNulls ?? this.connectNulls,\n showMarks: s.showMarks ?? this.showMarks,\n hidden: s.hidden ?? remembered ?? false,\n dash: s.dash,\n symbol: s.symbol,\n pointSymbols: rebaseMap(remapIndexRecord(s.pointSymbols, toMerged)),\n yAxisIndex: s.yAxisIndex,\n dashAfter: dashAt != null && dashAt >= 0 && zw ? dashAt - zw.start : dashAt,\n hollow: s.hollow,\n stroke: s.stroke ?? (this.showLine ? undefined : false),\n lineWidth: s.lineWidth ?? this.lineWidth,\n markSize: s.markSize ?? this.markSize,\n };\n });\n return {\n series,\n title: this.label || undefined,\n subtitle: this.subtitle || undefined,\n markLines: this.markLines\n ?.map((ml) => {\n // On a category axis the value IS an index, so it rebases with the\n // window; on a value axis it is a real x value and must not move.\n const indexed = zw != null && (this.xAxis?.scale ?? 'category') === 'category' && typeof ml.value === 'number';\n const value = indexed ? (ml.value as number) - zw!.start : ml.value;\n return {\n value,\n label: ml.label,\n color: ml.color != null ? resolveSeriesColor(this.el, ml.color, ml.color) : undefined,\n dash: ml.dash,\n // Rebased out of view — dropped below rather than drawn at the edge.\n offscreen: indexed && (Number(value) < 0 || Number(value) > zw!.end - zw!.start),\n };\n })\n .filter((ml) => !ml.offscreen)\n .map(({ offscreen: _drop, ...ml }) => ml),\n titleAlign: this.titleAlign,\n xValues: cut(m.xValues) ?? [],\n xScale: this.xAxis?.scale ?? 'category',\n xFormatter: this.xAxis?.valueFormatter ?? ((v: MdChartAxisValue) => defaultValueFormatter(v, this.locale)),\n xLabel: this.xAxis?.label,\n xHidden: this.xAxis?.hidden,\n xHideTicks: this.xAxis?.hideTicks,\n xDash: this.xAxis?.dash,\n xGridDash: this.xAxis?.gridDash,\n xBands: resolveAxisBands(this.el, this.xAxis?.bands),\n yBands: resolveAxisBands(this.el, this.yAxis?.bands),\n xBreaks: this.xAxis?.breaks,\n yBreaks: this.yAxis?.breaks,\n yScale: this.yAxis?.scale ?? 'value',\n yMin: percentage ? 0 : this.yAxis?.min,\n yMax: percentage ? 100 : this.yAxis?.max,\n yFormatter: percentage ? (v: number) => `${Math.round(v)}%` : yFmt,\n // The axis can format independently of the values (bare numbers on the\n // axis, units in the tooltip); unset → the axis follows `valueFormatter`.\n yTickFormatter:\n !percentage && this.yAxis?.valueFormatter ? (v: number) => this.yAxis!.valueFormatter!(v) : undefined,\n yLabel: this.yAxis?.label,\n yHidden: this.yAxis?.hidden,\n yHideTicks: this.yAxis?.hideTicks,\n yDash: this.yAxis?.dash,\n yGridDash: this.yAxis?.gridDash,\n yAxes: this.yAxes?.length\n ? this.yAxes.map((a) => ({\n scale: a.scale ?? 'value',\n min: a.min,\n max: a.max,\n formatter: a.valueFormatter\n ? (v: number) => a.valueFormatter!(v)\n : (v: number) => v.toLocaleString(this.locale || undefined),\n label: a.label,\n position: a.position,\n hidden: a.hidden,\n hideTicks: a.hideTicks,\n color: a.color != null ? resolveSeriesColor(this.el, a.color, a.color) : undefined,\n bands: resolveAxisBands(this.el, a.bands),\n dash: a.dash,\n gridDash: a.gridDash,\n }))\n : undefined,\n stack: this.stack,\n area: this.area,\n legend: this.legend,\n gridY: this.grid === 'horizontal' || this.grid === 'both',\n gridX: this.grid === 'vertical' || this.grid === 'both',\n axisTicks: this.axisTicks,\n inverted: this.inverted,\n showLabels: this.showLabels,\n seriesLabels: this.seriesLabels,\n animation: this.noAnimation ? 'none' : this.animation,\n animationDuration: this.animationDuration,\n };\n }\n\n private applyEngine() {\n if (!this.engine) return;\n const t = readMdChartTheme(this.el);\n this.engine.setSpec(this.buildSpec(t), this.buildEngineTheme(t), {\n onHover: (idx) => {\n if (idx < 0) return;\n // The engine indexes the sliced view; consumers get absolute indices.\n const abs = idx + (this.zoomWin ? this.win().start : 0);\n this.mdHover.emit({\n dataIndex: abs,\n axisValue: this.merged.xValues[abs],\n seriesIndices: this.visibleSeriesIndices(),\n });\n },\n onLegendClick: (item) => {\n // Remember the toggle so it survives a live consumer re-feeding `series`\n // every frame (the engine self-toggles; buildSpec re-applies this).\n this.rememberLegendToggle(item.seriesIndex, !!item.hidden);\n this.mdLegendClick.emit({\n seriesIndex: item.seriesIndex,\n seriesId: this.series[item.seriesIndex]?.id,\n selected: !item.hidden,\n });\n },\n onPointClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdMarkerClick.emit(d);\n },\n onLineClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdLineClick.emit(d);\n },\n onAreaClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdAreaClick.emit(d);\n },\n onAxisClick: (di, values, e) => this.mdAxisClick.emit(this.axisDetail(di, values, e)),\n });\n // Honour the tooltip prop — the engine only exposes a hover on/off toggle.\n this.engine.setHoverEnabled(this.tooltip !== 'none');\n this.engine.setTooltip({\n render: this.tooltipRenderer,\n missingFormatter: this.valueFormatter,\n // `item` reports only the series under the cursor; `axis` lists them all.\n trigger: this.tooltip === 'item' ? 'item' : 'axis',\n });\n }\n\n /**\n * The payload shared by the three per-series click events (marker / line /\n * area). The engine reports indices into what it drew, so both the zoom\n * window and the merge onto one x axis are undone here: `dataIndex` addresses\n * the consumer's OWN array (for a series carrying its own x, that's its point\n * index, not the merged one).\n */\n private clickDetail(si: number, di: number, e: PointerEvent): MdChartClickDetail<MdChartXYSeries> | null {\n const s = this.series[si];\n if (!s) return null;\n const abs = di + (this.zoomWin ? this.win().start : 0);\n const own = this.ownIndex(si, abs);\n return {\n seriesIndex: si,\n seriesId: s.id,\n dataIndex: own >= 0 ? own : abs,\n value: own >= 0 ? datumY(s.data[own]) : null,\n axisValue: this.merged.xValues[abs],\n nativeEvent: e,\n series: s,\n };\n }\n\n /** Index into series `si`'s own `data` for an absolute (merged) x index, or\n * -1 when that series has no point there. */\n private ownIndex(si: number, abs: number): number {\n const toOwn = this.merged.toOwn[si];\n return toOwn ? toOwn[abs] ?? -1 : abs;\n }\n\n /** `mdAxisClick`'s payload: the x the click is nearest, plus the reading of\n * every visible series there (the rows the tooltip would show). */\n /**\n * Every visible series' reading at a data index, in the shape the axis-click\n * detail and the keyboard announcement both want. Read from the live scene,\n * so a legend-toggled series is excluded exactly as it is on screen.\n */\n private seriesValuesAt(di: number): AxisSeriesValue[] {\n const hp = this.engine?.getScene()?.hoverPoints ?? [];\n return hp.map((h) => ({\n seriesIndex: h.seriesIndex,\n label: h.label,\n value: h.byIndex[di]?.value ?? null,\n }));\n }\n\n private axisDetail(di: number, values: AxisSeriesValue[], e: PointerEvent | KeyboardEvent): MdChartAxisClickDetail {\n const abs = di + (this.zoomWin ? this.win().start : 0);\n const seriesValues: MdChartAxisSeriesValue[] = values.map((v) => {\n const own = this.ownIndex(v.seriesIndex, abs);\n return {\n seriesIndex: v.seriesIndex,\n seriesId: this.series[v.seriesIndex]?.id,\n label: v.label,\n dataIndex: v.value == null ? -1 : own,\n value: v.value,\n };\n });\n return { dataIndex: abs, axisValue: this.merged.xValues[abs], seriesValues, nativeEvent: e };\n }\n\n /** Visible (non-toggled-off) series indices — reads the engine's live state so\n * an uncontrolled legend toggle is reflected, falling back to the prop. */\n private visibleSeriesIndices(): number[] {\n const hp = this.engine?.getScene()?.hoverPoints;\n if (hp) return hp.map((h) => h.seriesIndex);\n const keys = this.seriesKeys();\n return this.series\n .map((_, i) => i)\n .filter((i) => !(this.series[i].hidden ?? this.legendHidden.get(keys[i]) ?? false));\n }\n\n private rebuildA11yTable() {\n if (!this.a11yTableHost) return;\n // The table mirrors what's drawn, so it reads the merged axis: one row per\n // x, and a series with no sample at that x gets an empty cell.\n const m = this.merged;\n this.a11yTableHost.innerHTML = buildDataTableHtml({\n title: this.label,\n xAxisLabel: this.xAxis?.label,\n xAxisData: m.xValues,\n xValueFormatter: this.xAxis?.valueFormatter ?? ((v: MdChartAxisValue) => defaultValueFormatter(v, this.locale)),\n locale: this.locale,\n labels: this.tableLabels,\n series: this.series.map((s, i) => ({ label: s.label, data: m.data[i] ?? [] })),\n valueFormatter: this.valueFormatter,\n });\n }\n\n // ─────────────────── render ───────────────────\n\n /**\n * Range slider under the plot — the house `md-slider` in range mode, so the\n * thumbs, track, keyboard support and theming all come from the design\n * system. The chart stays the source of truth (`controlled`) because it\n * clamps the window to at least two points; on top of it sits a pan grip,\n * which is the one gesture a plain slider has no notion of.\n */\n private renderZoomSlider() {\n const last = Math.max(1, this.dataLength() - 1);\n const w = this.win();\n const pct = (i: number) => (i / last) * 100;\n const fmt = (i: number) => String(this.xAxis?.data?.[i] ?? i);\n return (\n <div class=\"md-line-chart__zoom\" part=\"zoom\">\n <md-slider\n class=\"md-line-chart__zoom-slider\"\n part=\"zoom-slider\"\n exportparts=\"track: zoom-track, track-active: zoom-window, thumb-knob: zoom-handle\"\n range\n controlled\n min={0}\n max={last}\n step={1}\n valueStart={w.start}\n valueEnd={w.end}\n ariaLabelStart={this.labelZoomStart}\n ariaLabelEnd={this.labelZoomEnd}\n valueStartText={fmt(w.start)}\n valueEndText={fmt(w.end)}\n onMdInput={this.onZoomSliderInput}\n onMdChange={this.onZoomSliderEvent}\n onMdDragStart={this.onZoomSliderEvent}\n onMdDragEnd={this.onZoomSliderEvent}\n onMdFocus={this.onZoomSliderEvent}\n onMdBlur={this.onZoomSliderEvent}\n ></md-slider>\n\n {/* Pan grip over the selected window. Inset at both ends so the thumbs\n stay grabbable, and it collapses to nothing on a narrow window. */}\n <div\n class=\"md-line-chart__zoom-pan\"\n part=\"zoom-pan\"\n style={{\n insetInlineStart: `calc(${pct(w.start)}% + var(--_zoom-pan-inset))`,\n inlineSize: `max(0px, calc(${pct(w.end) - pct(w.start)}% - 2 * var(--_zoom-pan-inset)))`,\n }}\n onPointerDown={this.onZoomPanDown}\n ></div>\n </div>\n );\n }\n\n render() {\n // Merged, so the announced range covers series that carry their own x.\n const xValues = this.merged.xValues;\n const summary =\n this.summary ||\n buildChartSummary({\n title: this.label,\n chartType: this.area ? 'area' : 'line',\n seriesCount: this.series.length,\n xMin: xValues[0] as MdChartAxisValue | undefined,\n xMax: xValues[xValues.length - 1] as MdChartAxisValue | undefined,\n locale: this.locale,\n });\n\n // While loading, the loader owns the box — an empty-state message under it\n // would just be the wrong answer to \"where is my data?\".\n const empty = this.series.length === 0 && !this.loading;\n\n return (\n <Host\n class={{\n 'md-line-chart': true,\n 'md-line-chart--empty': empty,\n 'md-line-chart--loading': this.loading,\n 'md-line-chart--mounted': this.mounted,\n 'md-line-chart--zoom-slider': this.zoomSliderOn,\n 'md-line-chart--zoom-drag': this.zoomInside,\n }}\n role=\"figure\"\n aria-label={summary}\n aria-busy={this.loading ? 'true' : null}\n style={this.heightProp ? { blockSize: this.heightProp } : undefined}\n onPointerDown={this.onPlotPointerDown}\n onPointerMove={this.onPointerMove}\n onPointerUp={this.onPointerUp}\n onPointerCancel={this.onPointerUp}\n onDblClick={this.onPlotDblClick}\n >\n <header class=\"md-line-chart__header\" part=\"header\">\n <slot name=\"header\"></slot>\n </header>\n\n {/* The plot is focusable so the data is reachable without a pointer:\n arrow keys walk the points, and each move is mirrored into the\n hover UI (for sighted keyboard users) and the live region (for\n screen readers). role=application stops a screen reader's browse\n mode from swallowing the arrow keys. */}\n <div\n class=\"md-line-chart__canvas\"\n part=\"canvas\"\n ref={el => this.bindChartHost(el as HTMLDivElement)}\n tabindex={empty ? undefined : '0'}\n role={empty ? undefined : 'application'}\n aria-label={empty ? undefined : this.labelPlot}\n onKeyDown={this.onPlotKeyDown}\n onBlur={this.onPlotBlur}\n ></div>\n\n {empty && (\n <div class=\"md-line-chart__empty\" part=\"empty\">\n <slot name=\"empty\">{this.labelEmpty}</slot>\n </div>\n )}\n\n {/* Loader — same opaque overlay as the empty state, so the phantom axis\n the engine draws for absent data can't show through. */}\n {this.loading && (\n <div class=\"md-line-chart__loading\" part=\"loading\" role=\"status\">\n {/* `loader` is the library-wide name for \"swap the loading affordance\";\n `loading` is kept as the older alias. Nesting them means either\n works — the outer slot falls back to the inner one, which falls\n back to the default below — and `loader` wins if both are given. */}\n <slot name=\"loader\">\n <slot name=\"loading\">\n <md-progress-indicator\n class=\"md-line-chart__spinner\"\n variant=\"circular\"\n indeterminate\n label={this.loadingLabel}\n ></md-progress-indicator>\n <span class=\"md-line-chart__loading-text\">{this.loadingLabel}</span>\n </slot>\n </slot>\n </div>\n )}\n\n {/* Drag-to-zoom band — purely visual, so it never eats pointer events. */}\n {this.dragBand && Math.abs(this.dragBand.x2 - this.dragBand.x1) > 1 && (\n <div\n class=\"md-line-chart__zoom-band\"\n part=\"zoom-band\"\n style={this.zoomBandStyle()}\n ></div>\n )}\n\n {this.zoomSliderOn && this.renderZoomSlider()}\n\n <footer class=\"md-line-chart__footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n\n {/* Screen-reader-only data table — the readable equivalent of\n the canvas plot (role=figure hides descendants from AT). */}\n <div\n class=\"md-line-chart__a11y-table\"\n ref={el => this.bindA11yTableHost(el as HTMLDivElement)}\n ></div>\n\n {/* Narrates the keyboard cursor. Polite so it waits for the reader to\n finish rather than interrupting every arrow press. */}\n <div class=\"md-line-chart__live\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {this.announcement}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"kPAAA,MAAMA,EAAiB,IAAM,y2J,MCuEhBC,EAAW,MALxB,WAAAC,CAAAC,G,gUASUC,KAAAC,MAAgB,GASYD,KAAAE,WAAgC,QAa5DF,KAAAG,OAA4B,GAkB5BH,KAAAI,MAAmF,SAGnFJ,KAAAK,MAA0B,OAGIL,KAAAM,aAAwB,MAG3BN,KAAAO,UAAqB,MAUhDP,KAAAQ,KAAgB,MAQUR,KAAAS,SAAoB,KAG7BT,KAAAU,OAAyC,UAG1DV,KAAAW,QAAiC,OAGjCX,KAAAY,KAAoD,aAGzBZ,KAAAa,UAAqB,MAIhDb,KAAAc,SAAoB,MAGQd,KAAAe,WAAsB,MAGpBf,KAAAgB,aAAwB,MAetDhB,KAAAiB,KAA8C,OAQ9CjB,KAAAkB,OAAiB,GAMWlB,KAAAmB,WAAqB,qBAOtBnB,KAAAoB,UACjC,+GAMkCpB,KAAAqB,WAAqB,gBAGhBrB,KAAAsB,eAAyB,mBAG3BtB,KAAAuB,aAAuB,iBAQtDvB,KAAAwB,QAAkB,GAsCWxB,KAAAyB,YAAuB,MAGpDzB,KAAA0B,UAA8B,aAeb1B,KAAA2B,QAAmB,MAGN3B,KAAA4B,aAAuB,iBAOpC5B,KAAA6B,QAAiC,EAiCzC7B,KAAA8B,QAAU,MAGV9B,KAAA+B,SAAU,EAGV/B,KAAAgC,aAAe,GAGfhC,KAAAiC,QAAiD,KAGjDjC,KAAAkC,SAA8C,KAOvDlC,KAAAmC,KAAoG,KAEpGnC,KAAAoC,OAAiC,KACjCpC,KAAAqC,GAA4B,KAa5BrC,KAAAsC,aAAe,IAAIC,IAGnBvC,KAAAwC,WAKG,KA+FHxC,KAAAyC,cAAiBC,IACvB1C,KAAK2C,UAAYD,CAAE,EAGb1C,KAAA4C,kBAAqBF,IAC3B1C,KAAK6C,cAAgBH,CAAE,EAiNjB1C,KAAA8C,kBAAqBC,IAC3B,IAAK/C,KAAKgD,YAAcD,EAAEE,SAAW,GAAKjD,KAAKmC,KAAM,OACrD,IAAKnC,KAAKkD,WAAWH,GAAI,OACzB,MAAMI,EAAInD,KAAKoD,MAAML,GACrB/C,KAAKmC,KAAO,CAAEkB,GAAIN,EAAEO,UAAWC,KAAM,OAAQJ,IAAGK,IAAKxD,KAAKwD,OAC1DxD,KAAKkC,SAAW,CAAEuB,GAAIN,EAAGO,GAAIP,GAO7B,MAAMQ,EAAUZ,EAAEa,iBAAiB,IAAmCb,EAAEY,OACxEA,EAAOE,oBAAoBd,EAAEO,UAAU,EAGjCtD,KAAA8D,cAAiBf,IACvB,MAAMgB,EAAI/D,KAAKmC,KACf,IAAK4B,GAAKA,EAAEV,KAAON,EAAEO,UAAW,OAChC,GAAIS,EAAER,OAAS,OAAQ,CACrB,MAAMS,EAAOhE,KAAKiE,WAClB,IAAKD,EAAM,OACXhE,KAAKkC,SAAW,CAAEuB,GAAIM,EAAEZ,EAAGO,GAAIQ,KAAKC,IAAID,KAAKE,IAAIpE,KAAKoD,MAAML,GAAIiB,EAAKb,GAAIa,EAAKb,EAAIa,EAAKK,QACvF,M,CAIF,MAAMC,EAAOtE,KAAKuE,UAAUxB,EAAEyB,SAC9B,MAAMC,EAAazE,KAAKuE,UAAUR,EAAEZ,GACpC,GAAImB,GAAQ,MAAQG,GAAc,KAAM,OACxC,MAAMC,EAAOR,KAAKE,IAAI,EAAGpE,KAAK2E,aAAe,GAC7C,MAAMC,EAAOb,EAAEP,IAAIqB,IAAMd,EAAEP,IAAIsB,MAC/B,MAAMC,EAAQb,KAAKc,OAAOV,EAAOG,GAAcC,GAC/C,MAAMO,EAAIf,KAAKC,IAAID,KAAKE,IAAI,EAAGL,EAAEP,IAAIsB,MAAQC,GAAQL,EAAOE,GAC5D5E,KAAKkF,UAAUD,EAAGA,EAAIL,EAAK,EAGrB5E,KAAAmF,YAAepC,IACrB,MAAMgB,EAAI/D,KAAKmC,KACf,IAAK4B,GAAKA,EAAEV,KAAON,EAAEO,UAAW,OAChCtD,KAAKmC,KAAO,KACZ,MAAMiD,EAAOpF,KAAKkC,SAClBlC,KAAKkC,SAAW,KAChB,GAAI6B,EAAER,OAAS,SAAW6B,EAAM,OAGhC,GAAIlB,KAAKmB,IAAID,EAAK1B,GAAK0B,EAAK3B,IAAM,EAAG,OAGrC,MAAO6B,EAAGC,GAAK,CAACvF,KAAKwF,SAASJ,EAAK3B,IAAKzD,KAAKwF,SAASJ,EAAK1B,KAAK+B,MAAK,CAACC,EAAGC,IAAMD,EAAIC,IACnF,GAAIJ,EAAID,GAAK,EAAGtF,KAAKkF,UAAUI,EAAGC,EAAE,EAW9BvF,KAAA4F,cAAiB7C,IACvB,MAAM2B,EAAOR,KAAKE,IAAI,EAAGpE,KAAK2E,aAAe,GAC7C,GAAID,EAAO,EAAG,OACd,MAAMmB,SAAaC,mBAAqB,YAAcA,iBAAiB9F,KAAK0C,IAAIqD,YAAc,MAC9F,MAAMC,EAAUH,EAAM,YAAc,aACpC,MAAMI,EAAOJ,EAAM,aAAe,YAClC,IAAIK,EAAOlG,KAAK+B,QAChB,OAAQgB,EAAEoD,KACR,KAAKH,EACHE,EAAOlG,KAAK+B,QAAU,EAAI,EAAImC,KAAKC,IAAIO,EAAM1E,KAAK+B,QAAU,GAC5D,MACF,KAAKkE,EACHC,EAAOlG,KAAK+B,QAAU,EAAI2C,EAAOR,KAAKE,IAAI,EAAGpE,KAAK+B,QAAU,GAC5D,MACF,IAAK,OACHmE,EAAO,EACP,MACF,IAAK,MACHA,EAAOxB,EACP,MACF,IAAK,SACH,GAAI1E,KAAK+B,QAAU,EAAG,OACtBmE,GAAO,EACP,MACF,IAAK,QACL,IAAK,IACH,GAAIlG,KAAK+B,QAAU,EAAG,OAGtB/B,KAAKoG,YAAYC,KAAKrG,KAAKsG,WAAWtG,KAAK+B,QAAS/B,KAAKuG,eAAevG,KAAK+B,SAAUgB,IACvFA,EAAEyD,iBACF,OACF,QACE,OAEJzD,EAAEyD,iBACFxG,KAAKyG,mBAAmBP,EAAK,EAGvBlG,KAAA0G,WAAa,KACnB,GAAI1G,KAAK+B,SAAW,EAAG/B,KAAKyG,oBAAmB,EAAG,EA0B5CzG,KAAA2G,eAAkB5D,IAGxB,GAAI/C,KAAKgD,YAAchD,KAAKiC,SAAWjC,KAAKkD,WAAWH,GAAI/C,KAAK4G,WAAW,EAwBrE5G,KAAA6G,cAAiB9D,IACvB,GAAIA,EAAEE,SAAW,EAAG,OAGpBF,EAAE+D,kBACF/D,EAAEyD,iBACFxG,KAAKmC,KAAO,CAAEkB,GAAIN,EAAEO,UAAWC,KAAM,MAAOJ,EAAGJ,EAAEyB,QAAShB,IAAKxD,KAAKwD,OACnET,EAAEY,OAAuBE,oBAAoBd,EAAEO,UAAU,EAIpDtD,KAAA+G,kBAAqBhE,IAG3BA,EAAE+D,kBACF,MAAME,WAAEA,EAAUC,SAAEA,GAAalE,EAAEmE,QAAU,GAC7C,GAAIF,GAAc,MAAQC,GAAY,KAAM,OAC5CjH,KAAKkF,UAAU8B,EAAYC,EAAS,EAK9BjH,KAAAmH,kBAAqBpE,GAAaA,EAAE+D,iBA4b7C,CA75BC,gBAAAM,GACEpH,KAAKqH,YACL,UAAWC,SAAW,aAAeA,OAAOC,WAAY,CACtDvH,KAAKwH,SAAWF,OAAOC,WAAW,gCAClCvH,KAAKyH,cAAgB,IAAMzH,KAAK0H,cAChC1H,KAAKwH,SAASG,mBAAmB,SAAU3H,KAAKyH,c,EAIpD,oBAAAG,GACE5H,KAAKqC,IAAIwF,aACT7H,KAAKqC,GAAK,KACVrC,KAAKoC,QAAQ0F,UACb9H,KAAKoC,OAAS,KACd,GAAIpC,KAAKwH,UAAYxH,KAAKyH,cAAe,CACvCzH,KAAKwH,SAASO,sBAAsB,SAAU/H,KAAKyH,eACnDzH,KAAKyH,cAAgBO,UACrBhI,KAAKwH,SAAWQ,S,EA+BpB,eAAAC,GACEjI,KAAK0H,cACL1H,KAAKkI,kB,CASP,eAAAC,CAAgBC,EAAcC,GAC5B,GAAIA,IAAWD,EAAKpI,KAAKoC,QAAQkG,Q,CAOnC,YAAMC,GACJvI,KAAKoC,QAAQmG,Q,CAKf,YAAMD,GACJtI,KAAKoC,QAAQkG,Q,CAKf,eAAME,GACJ,OAAOxI,KAAKoC,QAAQoG,UAAU,cAAgB,E,CAKhD,iBAAMC,GACJ,OAAOzI,KAAKoC,M,CAaN,SAAAiF,GACNrH,KAAK0I,aACL1I,KAAK0H,cACL1H,KAAKkI,mBACLlI,KAAK8B,QAAU,KACf9B,KAAK2I,QAAQtC,M,CAIP,UAAAqC,GACN,IAAK1I,KAAK2C,UAAW,OACrB3C,KAAKqC,IAAIwF,aACT7H,KAAKqC,GAAK,KACVrC,KAAKoC,QAAQ0F,UACb,IACE9H,KAAKoC,OAAS,IAAIwG,EAAgB5I,KAAK2C,U,CACvC,MAGA3C,KAAKoC,OAAS,I,CAEhB,GAAIpC,KAAKoC,eAAiByG,iBAAmB,YAAa,CACxD7I,KAAKqC,GAAK,IAAIwG,gBAAe,IAAM7I,KAAKoC,QAAQmG,WAChDvI,KAAKqC,GAAGyG,QAAQ9I,KAAK2C,U,EAKjB,gBAAAoG,CAAiBC,GACvB,MAAO,CACLC,WAAYD,EAAEC,WACdC,UAAWF,EAAEE,UACbC,eAAgBH,EAAEG,eAClBC,cAAeJ,EAAEI,cACjBC,cAAeL,EAAEM,UACjBC,QAASP,EAAEO,QACXC,WAAYR,EAAEQ,WACdC,UAAWT,EAAES,UACbC,UAAWV,EAAEU,U,CAWT,UAAAC,GACN,MAAMC,EAAO,IAAIrH,IACjB,OAAOvC,KAAKG,OAAO0J,KAAI,CAAC5E,EAAG6E,KACzB,MAAMC,EAAO9E,EAAE5B,IAAM,KAAO,MAAM4B,EAAE5B,KAAO4B,EAAEhF,OAAS,KAAO,SAASgF,EAAEhF,QAAU,OAAO6J,IACzF,MAAMnE,EAAIiE,EAAKI,IAAID,IAAS,EAC5BH,EAAKK,IAAIF,EAAMpE,EAAI,GACnB,OAAOA,IAAM,EAAIoE,EAAO,GAAGA,KAAQpE,GAAG,G,CAKlC,oBAAAuE,CAAqBC,EAAqBC,GAChD,MAAMjE,EAAMnG,KAAK2J,aAAaQ,GAC9B,GAAIhE,GAAO,KAAM,OACjBnG,KAAKsC,aAAa2H,IAAI9D,EAAKiE,GAG3B,GAAIpK,KAAKsC,aAAa+H,KAAO,IAAK,CAChC,MAAMC,EAAStK,KAAKsC,aAAaiI,OAAOrE,OAAOsE,MAC/CxK,KAAKsC,aAAamI,OAAOH,E,EAM7B,cAAYtH,GACV,OAAOhD,KAAKiB,OAAS,UAAYjB,KAAKiB,OAAS,M,CAGjD,gBAAYyJ,GACV,OAAO1K,KAAKiB,OAAS,UAAYjB,KAAKiB,OAAS,M,CAQjD,UAAY0J,GACV,MAAMC,EAAQ5K,KAAK6K,OAAOD,OAAS,WACnC,MAAME,EAAO9K,KAAK6K,OAAOE,KACzB,MAAMC,EAAIhL,KAAKwC,WACf,GAAIwI,GAAKA,EAAE7K,SAAWH,KAAKG,QAAU6K,EAAEF,OAASA,GAAQE,EAAEJ,QAAUA,EAAO,OAAOI,EAAEC,IACpF,MAAMA,EAAMC,EAAiBlL,KAAKG,QAAU,GAAI2K,EAAMF,GACtD5K,KAAKwC,WAAa,CAAErC,OAAQH,KAAKG,OAAQ2K,OAAMF,QAAOK,OACtD,OAAOA,C,CAID,UAAAtG,GACN,MAAMe,EAAI1F,KAAK2K,OACf,MAAM1F,EAAIS,EAAEqF,KAAKI,QAAO,CAACC,EAAKC,IAAMnH,KAAKE,IAAIgH,EAAKC,GAAGC,QAAU,IAAI,GACnE,OAAOpH,KAAKE,IAAIa,EAAGS,EAAE6F,QAAQD,O,CAIvB,GAAA9H,GACN,MAAMkB,EAAOR,KAAKE,IAAI,EAAGpE,KAAK2E,aAAe,GAC7C,MAAM6G,EAAIxL,KAAKiC,QACf,IAAKuJ,EAAG,MAAO,CAAE1G,MAAO,EAAGD,IAAKH,GAEhC,MAAMI,EAAQZ,KAAKC,IAAID,KAAKE,IAAI,EAAGoH,EAAE1G,OAAQZ,KAAKE,IAAI,EAAGM,EAAO,IAChE,MAAO,CAAEI,QAAOD,IAAKX,KAAKC,IAAID,KAAKE,IAAIU,EAAQ,EAAG0G,EAAE3G,KAAMH,G,CAGpD,SAAAQ,CAAUJ,EAAeD,EAAa4G,EAAQ,OACpD,MAAM/G,EAAOR,KAAKE,IAAI,EAAGpE,KAAK2E,aAAe,GAC7C,MAAMM,EAAIf,KAAKC,IAAID,KAAKE,IAAI,EAAGF,KAAKc,MAAMF,IAASZ,KAAKE,IAAI,EAAGM,EAAO,IACtE,MAAM3B,EAAImB,KAAKC,IAAID,KAAKE,IAAIa,EAAI,EAAGf,KAAKc,MAAMH,IAAOH,GACrD1E,KAAKiC,QAAUwJ,EAAQ,KAAO,CAAE3G,MAAOG,EAAGJ,IAAK9B,GAC/C/C,KAAK0H,cACL1H,KAAKkI,mBACLlI,KAAK0L,OAAOrF,KAAK,CAAEsF,WAAYF,EAAQ,EAAIxG,EAAG2G,SAAUH,EAAQ/G,EAAO3B,EAAG0I,S,CAK5E,aAAMI,CAAQF,EAAoBC,GAChC5L,KAAKkF,UAAUyG,EAAYC,E,CAK7B,eAAMhF,GACJ5G,KAAKkF,UAAU,EAAG,EAAG,K,CAaf,QAAAjB,GACN,MAAM6H,EAAI9L,KAAKoC,QAAQ2J,YAAY/H,KACnC,OAAO8H,EAAI,CAAE3I,EAAG2I,EAAE3I,EAAG6I,EAAGF,EAAEE,EAAG3H,MAAOyH,EAAEzH,MAAO4H,OAAQH,EAAEG,QAAW,I,CAI5D,YAAAC,GACN,MAAMC,EAASnM,KAAK2C,UACpB,IAAKwJ,EAAQ,MAAO,CAAEhJ,EAAG,EAAG6I,EAAG,GAC/B,MAAMI,EAAOpM,KAAK0C,GAAG2J,wBACrB,MAAMC,EAAMH,EAAOE,wBACnB,MAAO,CAAElJ,EAAGmJ,EAAIC,KAAOH,EAAKG,KAAMP,EAAGM,EAAIE,IAAMJ,EAAKI,I,CAI9C,aAAAC,GACN,MAAMzI,EAAOhE,KAAKiE,WAClB,IAAKjE,KAAKkC,WAAa8B,EAAM,OAAOgE,UACpC,MAAM0E,EAAM1M,KAAKkM,eACjB,MAAMzI,GAAEA,EAAEC,GAAEA,GAAO1D,KAAKkC,SACxB,MAAO,CACLqK,KAAM,GAAGG,EAAIvJ,EAAIe,KAAKC,IAAIV,EAAIC,OAC9BW,MAAO,GAAGH,KAAKmB,IAAI3B,EAAKD,OACxB+I,IAAK,GAAGE,EAAIV,EAAIhI,EAAKgI,MACrBC,OAAQ,GAAGjI,EAAKiI,W,CAKZ,QAAAzG,CAASpC,GACf,MAAMuJ,EAAQ3M,KAAKoC,QAAQ2J,WAC3B,MAAMP,EAAIxL,KAAKwD,MACf,IAAKmJ,GAAOC,YAAYtB,OAAQ,OAAOE,EAAE1G,MACzC,IAAI+H,EAAO,EACX,IAAIC,EAAQC,SACZJ,EAAMC,WAAWI,SAAQ,CAACC,EAAInD,KAC5B,MAAMuB,EAAInH,KAAKmB,IAAI4H,EAAK7J,GACxB,GAAIiI,EAAIyB,EAAO,CACbA,EAAQzB,EACRwB,EAAO/C,C,KAGX,OAAO0B,EAAE1G,MAAQ+H,C,CAIX,KAAAzJ,CAAML,GACZ,OAAOA,EAAEyB,SAAWxE,KAAK2C,WAAa3C,KAAK0C,IAAI2J,wBAAwBE,I,CAIjE,UAAArJ,CAAWH,GACjB,MAAMiB,EAAOhE,KAAKiE,WAClB,IAAKD,EAAM,OAAO,MAClB,MAAMsI,GAAOtM,KAAK2C,WAAa3C,KAAK0C,IAAI2J,wBACxC,MAAMlJ,EAAIJ,EAAEyB,QAAU8H,EAAIC,KAC1B,MAAMP,EAAIjJ,EAAEmK,QAAUZ,EAAIE,IAC1B,OAAOrJ,GAAKa,EAAKb,GAAKA,GAAKa,EAAKb,EAAIa,EAAKK,OAAS2H,GAAKhI,EAAKgI,GAAKA,GAAKhI,EAAKgI,EAAIhI,EAAKiI,M,CA4G9E,kBAAAxF,CAAmBP,GACzBlG,KAAK+B,QAAUmE,EACflG,KAAKoC,QAAQ+K,WAAWjH,GACxB,GAAIA,EAAO,EAAG,CACZlG,KAAKgC,aAAe,GACpB,M,CAEF,MAAM0D,EAAI1F,KAAK2K,OACf,MAAMyC,EAAO1H,EAAE6F,QAAQrF,GACvB,MAAMmH,EAAQrN,KAAK6K,OAAOyC,eACtBtN,KAAK6K,MAAMyC,eAAeF,GAC1BG,EAAsBH,GAAQlH,EAAO,EAAGlG,KAAKkB,QACjD,MAAMsM,EAAQC,GACZzN,KAAKsN,eAAiBtN,KAAKsN,eAAeG,GAAKA,EAAEC,eAAe1N,KAAKkB,QAAU8G,WACjF,MAAM2F,EAAS3N,KAAKuG,eAAeL,GAChC0H,QAAQC,GAAwBA,EAAGrD,OAAS,OAC5CX,KAAKgE,GAAwB,GAAGA,EAAG5N,SAASuN,EAAKK,EAAGrD,WACpDsD,KAAK,MACR9N,KAAKgC,aAAehC,KAAKqB,WAAW0M,QAAQ,MAAOV,GAAOU,QAAQ,WAAYJ,GAC9E3N,KAAKgO,QAAQ3H,KAAK,CAAE4H,UAAW/H,EAAMgI,UAAWd,EAAMe,cAAenO,KAAKoO,wB,CAcpE,eAAAC,GACN,MAAMC,EAAStO,KAAK0C,GAAG6L,YAAYC,cAAc,+BACjD,IAAKF,EAAQ,OAAO,KACpB,MAAMG,EAAIH,EAAOjC,wBACjB,IAAKoC,EAAEpK,MAAO,OAAO,KACrB,MAAO,CAAEkI,KAAMkC,EAAElC,KAAMlI,MAAOoK,EAAEpK,MAAOwB,IAAKC,iBAAiB9F,KAAK0C,IAAIqD,YAAc,M,CAI9E,SAAAxB,CAAUC,GAChB,MAAMkK,EAAQ1O,KAAKqO,kBACnB,IAAKK,EAAO,OAAO,KACnB,MAAMC,GAAOnK,EAAUkK,EAAMnC,MAAQmC,EAAMrK,MAC3C,OAAOH,KAAKC,IAAID,KAAKE,IAAIsK,EAAM7I,IAAM,EAAI8I,EAAMA,EAAK,GAAI,E,CA2BlD,SAAAC,CAAU5F,GAChB,MAAM6F,EAAa7O,KAAKK,QAAU,aAClC,MAAMmN,EAAQC,GACZzN,KAAKsN,eAAiBtN,KAAKsN,eAAeG,GAAKA,EAAEC,eAAe1N,KAAKkB,QAAU8G,WAIjF,MAAMuC,EAAOvK,KAAK2J,aAKlB,MAAMmF,EAAK9O,KAAKiC,QAAUjC,KAAKwD,MAAQ,KACvC,MAAMuL,EAAWC,GACfA,GAAOF,EAAKE,EAAIC,MAAMH,EAAGhK,MAAOgK,EAAGjK,IAAM,GAAKmK,EAChD,MAAME,EAAiBC,IACrB,IAAKA,IAAQL,EAAI,OAAOK,EACxB,MAAMlE,EAAyB,GAC/B,IAAK,MAAOmE,EAAG3B,KAAM4B,OAAOC,QAAQH,GAAM,CACxC,MAAMrF,EAAIyF,OAAOH,GAAKN,EAAGhK,MACzB,GAAIgF,GAAK,GAAKA,GAAKgF,EAAGjK,IAAMiK,EAAGhK,MAAOmG,EAAInB,GAAK2D,C,CAEjD,OAAOxC,CAAG,EAKZ,MAAMvF,EAAI1F,KAAK2K,OACf,MAAMxK,EAASH,KAAKG,OAAO0J,KAAI,CAAC5E,EAAG6E,KACjC,MAAM3D,EAAMoE,EAAKT,GACjB,MAAM0F,EAAaxP,KAAKsC,aAAa0H,IAAI7D,GACzC,MAAMsJ,EAAW/J,EAAE+J,SAAS3F,GAC5B,MAAM4F,EAASzK,EAAE0K,WAAa,MAAQF,EAAWA,EAASxK,EAAE0K,WAAa1K,EAAE0K,UAI3E,GAAI1K,EAAEmF,SAAWpC,UAAWhI,KAAKsC,aAAamI,OAAOtE,GACrD,MAAO,CACLlG,MAAOgF,EAAEhF,OAAS,UAAU6J,EAAI,IAChC8F,MAAOC,EAAmB7P,KAAK0C,GAAIuC,EAAE2K,MAAOE,EAAiB9G,EAAE+G,QAASjG,IACxEiB,KAAMgE,EAAIrJ,EAAEqF,KAAKjB,KAAOpE,EAAEqF,KAAKjB,IAAM,GACrC1J,MAAO6E,EAAE7E,OAASJ,KAAKI,MACvBE,aAAc2E,EAAE3E,cAAgBN,KAAKM,aACrCC,UAAW0E,EAAE1E,WAAaP,KAAKO,UAC/B6J,OAAQnF,EAAEmF,QAAUoF,GAAc,MAClCQ,KAAM/K,EAAE+K,KACRC,OAAQhL,EAAEgL,OACVC,aAAchB,EAAUiB,EAAiBlL,EAAEiL,aAAcT,IACzDW,WAAYnL,EAAEmL,WACdT,UAAWD,GAAU,MAAQA,GAAU,GAAKZ,EAAKY,EAASZ,EAAGhK,MAAQ4K,EACrEW,OAAQpL,EAAEoL,OACVC,OAAQrL,EAAEqL,SAAWtQ,KAAKS,SAAWuH,UAAY,OACjDuI,UAAWtL,EAAEsL,WAAavQ,KAAKuQ,UAC/BC,SAAUvL,EAAEuL,UAAYxQ,KAAKwQ,SAC9B,IAEH,MAAO,CACLrQ,SACAsQ,MAAOzQ,KAAKC,OAAS+H,UACrB0I,SAAU1Q,KAAK0Q,UAAY1I,UAC3B2I,UAAW3Q,KAAK2Q,WACZ9G,KAAK+G,IAGL,MAAMC,EAAU/B,GAAM,OAAS9O,KAAK6K,OAAOD,OAAS,cAAgB,mBAAqBgG,EAAGpG,QAAU,SACtG,MAAMA,EAAQqG,EAAWD,EAAGpG,MAAmBsE,EAAIhK,MAAQ8L,EAAGpG,MAC9D,MAAO,CACLA,QACAvK,MAAO2Q,EAAG3Q,MACV2P,MAAOgB,EAAGhB,OAAS,KAAOC,EAAmB7P,KAAK0C,GAAIkO,EAAGhB,MAAOgB,EAAGhB,OAAS5H,UAC5EgI,KAAMY,EAAGZ,KAETc,UAAWD,IAAYtB,OAAO/E,GAAS,GAAK+E,OAAO/E,GAASsE,EAAIjK,IAAMiK,EAAIhK,OAC3E,IAEF8I,QAAQgD,IAAQA,EAAGE,YACnBjH,KAAI,EAAGiH,UAAWC,KAAUH,KAASA,IACxC1Q,WAAYF,KAAKE,WACjBqL,QAASwD,EAAIrJ,EAAE6F,UAAY,GAC3ByF,OAAQhR,KAAK6K,OAAOD,OAAS,WAC7BqG,WAAYjR,KAAK6K,OAAOyC,gBAAc,CAAMG,GAAwBF,EAAsBE,EAAGzN,KAAKkB,SAClGgQ,OAAQlR,KAAK6K,OAAO5K,MACpBkR,QAASnR,KAAK6K,OAAOT,OACrBgH,WAAYpR,KAAK6K,OAAOwG,UACxBC,MAAOtR,KAAK6K,OAAOmF,KACnBuB,UAAWvR,KAAK6K,OAAO2G,SACvBC,OAAQC,EAAiB1R,KAAK0C,GAAI1C,KAAK6K,OAAO8G,OAC9CC,OAAQF,EAAiB1R,KAAK0C,GAAI1C,KAAK6R,OAAOF,OAC9CG,QAAS9R,KAAK6K,OAAOkH,OACrBC,QAAShS,KAAK6R,OAAOE,OACrBE,OAAQjS,KAAK6R,OAAOjH,OAAS,QAC7BsH,KAAMrD,EAAa,EAAI7O,KAAK6R,OAAO1N,IACnCgO,KAAMtD,EAAa,IAAM7O,KAAK6R,OAAOzN,IACrCgO,WAAYvD,EAAcpB,GAAc,GAAGvJ,KAAKc,MAAMyI,MAAQD,EAG9D6E,gBACGxD,GAAc7O,KAAK6R,OAAOvE,eAAkBG,GAAczN,KAAK6R,MAAOvE,eAAgBG,GAAKzF,UAC9FsK,OAAQtS,KAAK6R,OAAO5R,MACpBsS,QAASvS,KAAK6R,OAAOzH,OACrBoI,WAAYxS,KAAK6R,OAAOR,UACxBoB,MAAOzS,KAAK6R,OAAO7B,KACnB0C,UAAW1S,KAAK6R,OAAOL,SACvBmB,MAAO3S,KAAK2S,OAAOrH,OACftL,KAAK2S,MAAM9I,KAAKvE,IAAC,CACfsF,MAAOtF,EAAEsF,OAAS,QAClBzG,IAAKmB,EAAEnB,IACPC,IAAKkB,EAAElB,IACPwO,UAAWtN,EAAEgI,eACRG,GAAcnI,EAAEgI,eAAgBG,GAChCA,GAAcA,EAAEC,eAAe1N,KAAKkB,QAAU8G,WACnD/H,MAAOqF,EAAErF,MACT4S,SAAUvN,EAAEuN,SACZzI,OAAQ9E,EAAE8E,OACViH,UAAW/L,EAAE+L,UACbzB,MAAOtK,EAAEsK,OAAS,KAAOC,EAAmB7P,KAAK0C,GAAI4C,EAAEsK,MAAOtK,EAAEsK,OAAS5H,UACzE2J,MAAOD,EAAiB1R,KAAK0C,GAAI4C,EAAEqM,OACnC3B,KAAM1K,EAAE0K,KACRwB,SAAUlM,EAAEkM,aAEdxJ,UACJ3H,MAAOL,KAAKK,MACZG,KAAMR,KAAKQ,KACXE,OAAQV,KAAKU,OACboS,MAAO9S,KAAKY,OAAS,cAAgBZ,KAAKY,OAAS,OACnDmS,MAAO/S,KAAKY,OAAS,YAAcZ,KAAKY,OAAS,OACjDC,UAAWb,KAAKa,UAChBC,SAAUd,KAAKc,SACfC,WAAYf,KAAKe,WACjBC,aAAchB,KAAKgB,aACnBU,UAAW1B,KAAKyB,YAAc,OAASzB,KAAK0B,UAC5CsR,kBAAmBhT,KAAKgT,kB,CAIpB,WAAAtL,GACN,IAAK1H,KAAKoC,OAAQ,OAClB,MAAM4G,EAAIiK,EAAiBjT,KAAK0C,IAChC1C,KAAKoC,OAAO8Q,QAAQlT,KAAK4O,UAAU5F,GAAIhJ,KAAK+I,iBAAiBC,GAAI,CAC/DmK,QAAUC,IACR,GAAIA,EAAM,EAAG,OAEb,MAAM/N,EAAM+N,GAAOpT,KAAKiC,QAAUjC,KAAKwD,MAAMsB,MAAQ,GACrD9E,KAAKgO,QAAQ3H,KAAK,CAChB4H,UAAW5I,EACX6I,UAAWlO,KAAK2K,OAAOY,QAAQlG,GAC/B8I,cAAenO,KAAKoO,wBACpB,EAEJiF,cAAgBC,IAGdtT,KAAKkK,qBAAqBoJ,EAAKnJ,cAAemJ,EAAKlJ,QACnDpK,KAAKuT,cAAclN,KAAK,CACtB8D,YAAamJ,EAAKnJ,YAClBqJ,SAAUxT,KAAKG,OAAOmT,EAAKnJ,cAAc9G,GACzCoQ,UAAWH,EAAKlJ,QAChB,EAEJsJ,aAAc,CAACC,EAAIC,EAAI7Q,KACrB,MAAMsI,EAAIrL,KAAK6T,YAAYF,EAAIC,EAAI7Q,GACnC,GAAIsI,EAAGrL,KAAK8T,cAAczN,KAAKgF,EAAE,EAEnC0I,YAAa,CAACJ,EAAIC,EAAI7Q,KACpB,MAAMsI,EAAIrL,KAAK6T,YAAYF,EAAIC,EAAI7Q,GACnC,GAAIsI,EAAGrL,KAAKgU,YAAY3N,KAAKgF,EAAE,EAEjC4I,YAAa,CAACN,EAAIC,EAAI7Q,KACpB,MAAMsI,EAAIrL,KAAK6T,YAAYF,EAAIC,EAAI7Q,GACnC,GAAIsI,EAAGrL,KAAKkU,YAAY7N,KAAKgF,EAAE,EAEjC8I,YAAa,CAACP,EAAIjG,EAAQ5K,IAAM/C,KAAKoG,YAAYC,KAAKrG,KAAKsG,WAAWsN,EAAIjG,EAAQ5K,MAGpF/C,KAAKoC,OAAOgS,gBAAgBpU,KAAKW,UAAY,QAC7CX,KAAKoC,OAAOiS,WAAW,CACrBC,OAAQtU,KAAKuU,gBACbC,iBAAkBxU,KAAKsN,eAEvBmH,QAASzU,KAAKW,UAAY,OAAS,OAAS,Q,CAWxC,WAAAkT,CAAYF,EAAYC,EAAY7Q,GAC1C,MAAMkC,EAAIjF,KAAKG,OAAOwT,GACtB,IAAK1O,EAAG,OAAO,KACf,MAAMI,EAAMuO,GAAM5T,KAAKiC,QAAUjC,KAAKwD,MAAMsB,MAAQ,GACpD,MAAM4P,EAAM1U,KAAK2U,SAAShB,EAAItO,GAC9B,MAAO,CACL8E,YAAawJ,EACbH,SAAUvO,EAAE5B,GACZ4K,UAAWyG,GAAO,EAAIA,EAAMrP,EAC5BmF,MAAOkK,GAAO,EAAIE,EAAO3P,EAAE8F,KAAK2J,IAAQ,KACxCxG,UAAWlO,KAAK2K,OAAOY,QAAQlG,GAC/BwP,YAAa9R,EACb5C,OAAQ8E,E,CAMJ,QAAA0P,CAAShB,EAAYtO,GAC3B,MAAMyP,EAAQ9U,KAAK2K,OAAOmK,MAAMnB,GAChC,OAAOmB,EAAQA,EAAMzP,KAAQ,EAAKA,C,CAU5B,cAAAkB,CAAeqN,GACrB,MAAMmB,EAAK/U,KAAKoC,QAAQ2J,YAAYiJ,aAAe,GACnD,OAAOD,EAAGlL,KAAKoL,IAAC,CACd9K,YAAa8K,EAAE9K,YACflK,MAAOgV,EAAEhV,MACTuK,MAAOyK,EAAEC,QAAQtB,IAAKpJ,OAAS,Q,CAI3B,UAAAlE,CAAWsN,EAAYjG,EAA2B5K,GACxD,MAAMsC,EAAMuO,GAAM5T,KAAKiC,QAAUjC,KAAKwD,MAAMsB,MAAQ,GACpD,MAAMqQ,EAAyCxH,EAAO9D,KAAK4D,IACzD,MAAMiH,EAAM1U,KAAK2U,SAASlH,EAAEtD,YAAa9E,GACzC,MAAO,CACL8E,YAAasD,EAAEtD,YACfqJ,SAAUxT,KAAKG,OAAOsN,EAAEtD,cAAc9G,GACtCpD,MAAOwN,EAAExN,MACTgO,UAAWR,EAAEjD,OAAS,MAAO,EAAKkK,EAClClK,MAAOiD,EAAEjD,MACV,IAEH,MAAO,CAAEyD,UAAW5I,EAAK6I,UAAWlO,KAAK2K,OAAOY,QAAQlG,GAAM8P,eAAcN,YAAa9R,E,CAKnF,oBAAAqL,GACN,MAAM2G,EAAK/U,KAAKoC,QAAQ2J,YAAYiJ,YACpC,GAAID,EAAI,OAAOA,EAAGlL,KAAKoL,GAAMA,EAAE9K,cAC/B,MAAMI,EAAOvK,KAAK2J,aAClB,OAAO3J,KAAKG,OACT0J,KAAI,CAACuL,EAAGtL,IAAMA,IACd8D,QAAQ9D,KAAQ9J,KAAKG,OAAO2J,GAAGM,QAAUpK,KAAKsC,aAAa0H,IAAIO,EAAKT,KAAO,Q,CAGxE,gBAAA5B,GACN,IAAKlI,KAAK6C,cAAe,OAGzB,MAAM6C,EAAI1F,KAAK2K,OACf3K,KAAK6C,cAAcwS,UAAYC,EAAmB,CAChD7E,MAAOzQ,KAAKC,MACZsV,WAAYvV,KAAK6K,OAAO5K,MACxBuV,UAAW9P,EAAE6F,QACbkK,gBAAiBzV,KAAK6K,OAAOyC,gBAAc,CAAMG,GAAwBF,EAAsBE,EAAGzN,KAAKkB,SACvGA,OAAQlB,KAAKkB,OACbwU,OAAQ1V,KAAK2V,YACbxV,OAAQH,KAAKG,OAAO0J,KAAI,CAAC5E,EAAG6E,KAAC,CAAQ7J,MAAOgF,EAAEhF,MAAO8K,KAAMrF,EAAEqF,KAAKjB,IAAM,OACxEwD,eAAgBtN,KAAKsN,gB,CAajB,gBAAAsI,GACN,MAAMlR,EAAOR,KAAKE,IAAI,EAAGpE,KAAK2E,aAAe,GAC7C,MAAM6G,EAAIxL,KAAKwD,MACf,MAAMqS,EAAO/L,GAAeA,EAAIpF,EAAQ,IACxC,MAAMoR,EAAOhM,GAAciM,OAAO/V,KAAK6K,OAAOE,OAAOjB,IAAMA,GAC3D,OACEmL,EAAA,OAAKe,MAAM,sBAAsBC,KAAK,QACpChB,EAAA,aACEe,MAAM,6BACNC,KAAK,cACLC,YAAY,wEACZC,MAAK,KACLC,WAAU,KACVjS,IAAK,EACLC,IAAKM,EACL2R,KAAM,EACNrP,WAAYwE,EAAE1G,MACdmC,SAAUuE,EAAE3G,IACZyR,eAAgBtW,KAAKsB,eACrBiV,aAAcvW,KAAKuB,aACnBiV,eAAgBV,EAAItK,EAAE1G,OACtB2R,aAAcX,EAAItK,EAAE3G,KACpB6R,UAAW1W,KAAK+G,kBAChB4P,WAAY3W,KAAKmH,kBACjByP,cAAe5W,KAAKmH,kBACpB0P,YAAa7W,KAAKmH,kBAClB2P,UAAW9W,KAAKmH,kBAChB4P,SAAU/W,KAAKmH,oBAKjB8N,EAAA,OACEe,MAAM,0BACNC,KAAK,WACLe,MAAO,CACLC,iBAAkB,QAAQpB,EAAIrK,EAAE1G,oCAChCoS,WAAY,iBAAiBrB,EAAIrK,EAAE3G,KAAOgR,EAAIrK,EAAE1G,0CAElDqS,cAAenX,KAAK6G,gB,CAM5B,MAAAyN,GAEE,MAAM/I,EAAUvL,KAAK2K,OAAOY,QAC5B,MAAM/J,EACJxB,KAAKwB,SACL4V,EAAkB,CAChB3G,MAAOzQ,KAAKC,MACZoX,UAAWrX,KAAKQ,KAAO,OAAS,OAChC8W,YAAatX,KAAKG,OAAOmL,OACzBiM,KAAMhM,EAAQ,GACdiM,KAAMjM,EAAQA,EAAQD,OAAS,GAC/BpK,OAAQlB,KAAKkB,SAKjB,MAAMuW,EAAQzX,KAAKG,OAAOmL,SAAW,IAAMtL,KAAK2B,QAEhD,OACEsT,EAACyC,EAAI,CAAAvR,IAAA,2CACH6P,MAAO,CACL,gBAAiB,KACjB,uBAAwByB,EACxB,yBAA0BzX,KAAK2B,QAC/B,yBAA0B3B,KAAK8B,QAC/B,6BAA8B9B,KAAK0K,aACnC,2BAA4B1K,KAAKgD,YAEnC2U,KAAK,SAAQ,aACDnW,EAAO,YACRxB,KAAK2B,QAAU,OAAS,KACnCqV,MAAOhX,KAAK4X,WAAa,CAAEC,UAAW7X,KAAK4X,YAAe5P,UAC1DmP,cAAenX,KAAK8C,kBACpBgB,cAAe9D,KAAK8D,cACpBqB,YAAanF,KAAKmF,YAClB2S,gBAAiB9X,KAAKmF,YACtB4S,WAAY/X,KAAK2G,gBAEjBsO,EAAA,UAAA9O,IAAA,2CAAQ6P,MAAM,wBAAwBC,KAAK,UACzChB,EAAA,QAAA9O,IAAA,2CAAM6R,KAAK,YAQb/C,EAAA,OAAA9O,IAAA,2CACE6P,MAAM,wBACNC,KAAK,SACLgC,IAAKvV,GAAM1C,KAAKyC,cAAcC,GAC9BwV,SAAUT,EAAQzP,UAAY,IAC9B2P,KAAMF,EAAQzP,UAAY,cAAa,aAC3ByP,EAAQzP,UAAYhI,KAAKoB,UACrC+W,UAAWnY,KAAK4F,cAChBwS,OAAQpY,KAAK0G,aAGd+Q,GACCxC,EAAA,OAAA9O,IAAA,2CAAK6P,MAAM,uBAAuBC,KAAK,SACrChB,EAAA,QAAA9O,IAAA,2CAAM6R,KAAK,SAAShY,KAAKmB,aAM5BnB,KAAK2B,SACJsT,EAAA,OAAA9O,IAAA,2CAAK6P,MAAM,yBAAyBC,KAAK,UAAU0B,KAAK,UAKtD1C,EAAA,QAAA9O,IAAA,2CAAM6R,KAAK,UACT/C,EAAA,QAAA9O,IAAA,2CAAM6R,KAAK,WACX/C,EAAA,yBAAA9O,IAAA,2CACE6P,MAAM,yBACNqC,QAAQ,WACRC,cAAa,KACbrY,MAAOD,KAAK4B,eAEdqT,EAAA,QAAA9O,IAAA,2CAAM6P,MAAM,+BAA+BhW,KAAK4B,iBAOrD5B,KAAKkC,UAAYgC,KAAKmB,IAAIrF,KAAKkC,SAASwB,GAAK1D,KAAKkC,SAASuB,IAAM,GAChEwR,EAAA,OAAA9O,IAAA,2CACE6P,MAAM,2BACNC,KAAK,YACLe,MAAOhX,KAAKyM,kBAIfzM,KAAK0K,cAAgB1K,KAAK4V,mBAE3BX,EAAA,UAAA9O,IAAA,2CAAQ6P,MAAM,wBAAwBC,KAAK,UACzChB,EAAA,QAAA9O,IAAA,2CAAM6R,KAAK,YAKb/C,EAAA,OAAA9O,IAAA,2CACE6P,MAAM,4BACNiC,IAAKvV,GAAM1C,KAAK4C,kBAAkBF,KAKpCuS,EAAA,OAAA9O,IAAA,2CAAK6P,MAAM,sBAAsB2B,KAAK,SAAQ,YAAW,SAAQ,cAAa,QAC3E3X,KAAKgC,c","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["mdLineChartCss","MdLineChart","constructor","hostRef","this","label","titleAlign","series","curve","stack","connectNulls","showMarks","area","showLine","legend","tooltip","grid","axisTicks","inverted","showLabels","seriesLabels","zoom","locale","labelEmpty","labelPlot","labelPoint","labelZoomStart","labelZoomEnd","summary","noAnimation","animation","loading","loadingLabel","density","mounted","kbIndex","announcement","zoomWin","dragBand","grab","engine","ro","legendHidden","Map","mergeCache","bindChartHost","el","chartHost","bindA11yTableHost","a11yTableHost","onPlotPointerDown","e","zoomInside","button","insidePlot","x","hostX","id","pointerId","kind","win","x1","x2","target","composedPath","setPointerCapture","onPointerMove","g","plot","plotRect","Math","min","max","width","frac","trackFrac","clientX","originFrac","last","dataLength","span","end","start","delta","round","s","applyZoom","onPointerUp","band","abs","a","b","indexAtX","sort","m","n","onPlotKeyDown","rtl","getComputedStyle","direction","forward","back","next","key","mdAxisClick","emit","axisDetail","seriesValuesAt","preventDefault","moveKeyboardCursor","onPlotBlur","onPlotDblClick","resetZoom","onZoomPanDown","stopPropagation","onZoomSliderInput","valueStart","valueEnd","detail","onZoomSliderEvent","componentDidLoad","initChart","window","matchMedia","themeMql","themeListener","applyEngine","addEventListener","disconnectedCallback","disconnect","dispose","removeEventListener","undefined","onAnyPropChange","rebuildA11yTable","onLoadingChange","now","before","replay","resize","toDataURL","getInstance","makeEngine","mdReady","LineChartEngine","ResizeObserver","observe","buildEngineTheme","t","background","textColor","textColorMuted","axisLineColor","gridLineColor","gridColor","surface","fontFamily","labelSize","titleSize","seriesKeys","seen","map","i","base","get","set","rememberLegendToggle","seriesIndex","hidden","size","oldest","keys","value","delete","zoomSliderOn","merged","scale","xAxis","axis","data","c","out","normalizeSeriesX","reduce","acc","d","length","xValues","w","reset","mdZoom","startIndex","endIndex","setZoom","p","getScene","y","height","canvasOffset","canvas","host","getBoundingClientRect","box","left","top","zoomBandStyle","off","scene","xPositions","best","bestD","Infinity","forEach","px","clientY","focusIndex","xRaw","xText","valueFormatter","defaultValueFormatter","yFmt","v","toLocaleString","values","filter","sv","join","replace","mdHover","dataIndex","axisValue","seriesIndices","visibleSeriesIndices","sliderTrackRect","slider","shadowRoot","querySelector","r","track","raw","buildSpec","percentage","zw","cut","arr","slice","rebaseMap","rec","k","Object","entries","Number","remembered","toMerged","dashAt","dashAfter","color","resolveSeriesColor","pickPaletteColor","palette","dash","symbol","pointSymbols","remapIndexRecord","yAxisIndex","hollow","stroke","lineWidth","markSize","title","subtitle","markLines","ml","indexed","offscreen","_drop","xScale","xFormatter","xLabel","xHidden","xHideTicks","hideTicks","xDash","xGridDash","gridDash","xBands","resolveAxisBands","bands","yBands","yAxis","xBreaks","breaks","yBreaks","yScale","yMin","yMax","yFormatter","yTickFormatter","yLabel","yHidden","yHideTicks","yDash","yGridDash","yAxes","formatter","position","gridY","gridX","animationDuration","readMdChartTheme","setSpec","onHover","idx","onLegendClick","item","mdLegendClick","seriesId","selected","onPointClick","si","di","clickDetail","mdMarkerClick","onLineClick","mdLineClick","onAreaClick","mdAreaClick","onAxisClick","setHoverEnabled","setTooltip","render","tooltipRenderer","missingFormatter","trigger","own","ownIndex","datumY","nativeEvent","toOwn","hp","hoverPoints","h","byIndex","seriesValues","_","innerHTML","buildDataTableHtml","xAxisLabel","xAxisData","xValueFormatter","labels","tableLabels","renderZoomSlider","pct","fmt","String","class","part","exportparts","range","controlled","step","ariaLabelStart","ariaLabelEnd","valueStartText","valueEndText","onMdInput","onMdChange","onMdDragStart","onMdDragEnd","onMdFocus","onMdBlur","style","insetInlineStart","inlineSize","onPointerDown","buildChartSummary","chartType","seriesCount","xMin","xMax","empty","Host","role","heightProp","blockSize","onPointerCancel","onDblClick","name","ref","tabindex","onKeyDown","onBlur","variant","indeterminate"],"sources":["src/components/md-line-chart/md-line-chart.css?tag=md-line-chart&encapsulation=shadow","src/components/md-line-chart/md-line-chart.tsx"],"sourcesContent":["/* ==========================================================\n md-line-chart — Material Design 3 line chart\n Spec: https://m3.material.io/styles/charts/overview\n\n PUBLIC CSS CUSTOM PROPERTIES (override per-instance):\n --md-line-chart-block-size Chart block-size (default: aspect-ratio driven)\n --md-line-chart-min-block-size Floor for the chart's height (default: 160px)\n --md-line-chart-aspect-ratio Width:height ratio (default: 16/9)\n --md-line-chart-background Surface behind the chart (default: --md-sys-color-surface-container-low;\n set `transparent` to sit flush on the page)\n --md-line-chart-padding Inset padding around the canvas (default: 16px)\n --md-line-chart-shape Container corner radius (default: --md-sys-shape-corner-large)\n --md-line-chart-empty-color Empty-state text colour\n --md-line-chart-empty-background Empty-state surface (default: the chart's own background)\n --md-line-chart-empty-font Empty-state font FAMILY — not a font shorthand\n --md-line-chart-empty-font-size Empty-state font size (default: 14px)\n --md-line-chart-empty-icon-size Slotted Material Symbols icon size (default: 40px)\n --md-line-chart-zoom-size Height reserved for the zoom slider (default: 28px)\n --md-line-chart-zoom-track-color Zoom slider track colour (md-slider inactive track)\n --md-line-chart-zoom-window-color Zoom slider selected-window colour (md-slider active track)\n --md-line-chart-zoom-handle-color Zoom slider thumb + drag-band edge colour\n --md-line-chart-zoom-band-color Drag-to-zoom selection fill\n (the zoom slider is an md-slider — its own --md-slider-* variables also\n apply, scoped to .md-line-chart__zoom-slider)\n --md-chart-axis-color Axis-line colour (default: --md-sys-color-outline)\n --md-chart-grid-color Gridline colour (default: --md-sys-color-outline-variant)\n\n CSS PARTS:\n header Header slot wrapper (title, toolbar)\n canvas Plot canvas container\n empty Empty-state container\n zoom Zoom slider container\n zoom-slider The md-slider itself\n zoom-track Zoom slider track (forwarded)\n zoom-window Selected window / active track (forwarded)\n zoom-handle Zoom slider thumb (forwarded)\n zoom-pan Drag-to-pan grip over the window\n zoom-band Drag-to-zoom selection band\n footer Footer slot wrapper (caption, legend)\n\n SLOTS:\n header Renders above the plot\n empty Empty-state content (overrides default text)\n footer Renders below the plot\n ========================================================== */\n\n:host {\n --_block-size: var(--md-line-chart-block-size, auto);\n --_min-block-size: var(--md-line-chart-min-block-size, max(120px, calc(160px + var(--md-sys-density-scale, 0) * 8px)));\n --_aspect-ratio: var(--md-line-chart-aspect-ratio, 16 / 9);\n --_background: var(--md-line-chart-background, var(--md-sys-color-surface-container-low, #F7F2FA));\n --_padding: var(--md-line-chart-padding, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));\n --_shape: var(--md-line-chart-shape, max(8px, calc(16px + var(--md-sys-density-scale, 0) * 2px)));\n --_empty-color: var(--md-line-chart-empty-color, var(--md-sys-color-on-surface-variant, #49454F));\n --_empty-background: var(--md-line-chart-empty-background, var(--_background));\n --_empty-font: var(--md-line-chart-empty-font, var(--md-sys-typescale-body-medium-font-family, Roboto, sans-serif));\n --_empty-font-size: var(--md-line-chart-empty-font-size, var(--md-sys-typescale-body-medium-font-size, 14px));\n --_empty-icon-size: var(--md-line-chart-empty-icon-size, 40px);\n --_zoom-size: var(--md-line-chart-zoom-size, 28px);\n --_zoom-track-color: var(--md-line-chart-zoom-track-color, var(--md-sys-color-surface-container-highest, #E6E0E9));\n --_zoom-window-color: var(--md-line-chart-zoom-window-color, var(--md-sys-color-secondary-container, #E8DEF8));\n --_zoom-handle-color: var(--md-line-chart-zoom-handle-color, var(--md-sys-color-primary, #6750A4));\n --_zoom-band-color: var(--md-line-chart-zoom-band-color, color-mix(in srgb, var(--md-sys-color-primary, #6750A4) 16%, transparent));\n /* Clearance kept at each end of the pan grip so the thumbs stay grabbable. */\n --_zoom-pan-inset: 10px;\n\n display: block;\n position: relative;\n inline-size: 100%;\n block-size: var(--_block-size);\n min-block-size: var(--_min-block-size);\n background: var(--_background);\n padding: var(--_padding);\n border-radius: var(--_shape);\n box-sizing: border-box;\n /* aspect-ratio + 100% inline-size = fluid responsive sizing,\n no JS measurements needed for the host's box. ECharts\n inside still uses ResizeObserver to react to those CSS\n dimension changes. */\n aspect-ratio: var(--_aspect-ratio);\n}\n\n/* Header / footer wrappers — only take vertical space when\n their slot has content (Stencil slots are empty by default,\n so the `:not(:empty)` check works after slot assignment). */\n.md-line-chart__header,\n.md-line-chart__footer {\n display: contents;\n}\n\n.md-line-chart__header > slot[name='header']::slotted(*),\n.md-line-chart__footer > slot[name='footer']::slotted(*) {\n display: block;\n margin-block: 8px;\n}\n\n/* Plot surface — fills the host so ECharts has a measurable\n box to size against. `min-block-size: 0` lets it shrink\n inside a flex parent without overflowing. */\n.md-line-chart__canvas {\n position: absolute;\n inset: var(--_padding);\n min-block-size: 0;\n min-inline-size: 0;\n}\n\n/* Empty state — overlaid on the canvas so the host's box keeps its\n full responsive size and the message centres. */\n.md-line-chart__empty {\n position: absolute;\n inset: 0;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n padding: 24px;\n /* Mirrors the chart's own container — same surface and corner radius. The\n engine still draws a phantom 0-1 axis for an empty series, so an OPAQUE\n surface here masks that ghost grid instead of letting it show through\n behind the message. Column layout stacks a slotted icon above the text. */\n background: var(--_empty-background);\n border-radius: var(--_shape);\n color: var(--_empty-color);\n font-family: var(--_empty-font);\n font-size: var(--_empty-font-size);\n line-height: var(--md-sys-typescale-body-medium-line-height, 20px);\n pointer-events: none;\n text-align: center;\n}\n\n/* Loading state — the same opaque overlay as the empty state (it has to mask\n the phantom 0-1 axis the engine draws while there is no data), with the\n default indicator + label stacked in the middle. Slot `loading` replaces the\n content; the box keeps its size either way. */\n.md-line-chart__loading {\n position: absolute;\n inset: 0;\n z-index: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 12px;\n box-sizing: border-box;\n padding: 24px;\n background: var(--_empty-background);\n border-radius: var(--_shape);\n color: var(--_empty-color);\n font-family: var(--_empty-font);\n font-size: var(--_empty-font-size);\n text-align: center;\n}\n\n.md-line-chart__spinner {\n /* Sized against the empty-state icon so a loading chart and an empty one\n read as the same family. */\n inline-size: var(--_empty-icon-size);\n block-size: var(--_empty-icon-size);\n}\n\n/* A slotted icon (e.g. a Material Symbols span) gets a sensible size and the\n muted empty-state colour without the consumer restyling it. */\n.md-line-chart__empty ::slotted(.material-symbols-outlined),\n.md-line-chart__empty ::slotted(.material-symbols-rounded),\n.md-line-chart__empty ::slotted(.material-symbols-sharp),\n.md-line-chart__empty ::slotted(.material-icons) {\n /* Document-level .material-symbols rules outrank ::slotted() in the cascade,\n so the size needs !important to win (same reason md-icon-button does it). */\n font-size: var(--_empty-icon-size) !important;\n line-height: 1;\n opacity: 0.55;\n}\n\n/* ── Zoom ──────────────────────────────────────────────────\n The slider sits inside the host's padding at the bottom, and the plot gives\n up exactly that much height (the canvas is inset by --_padding, so its bottom\n is pushed up by the slider's height). */\n:host(.md-line-chart--zoom-slider) .md-line-chart__canvas {\n bottom: calc(var(--_padding) + var(--_zoom-size));\n}\n\n:host(.md-line-chart--zoom-drag) .md-line-chart__canvas {\n /* Signals the plot is draggable; the band itself is pointer-transparent. */\n cursor: ew-resize;\n}\n\n.md-line-chart__zoom {\n position: absolute;\n inset-inline: var(--_padding);\n bottom: var(--_padding);\n block-size: var(--_zoom-size);\n display: flex;\n align-items: center;\n}\n\n/* The house slider draws the track and thumbs; the chart only maps its own\n public zoom tokens onto the slider's and sizes it to the reserved band. */\n.md-line-chart__zoom-slider {\n --md-slider-active-color: var(--_zoom-window-color);\n --md-slider-inactive-color: var(--_zoom-track-color);\n --md-slider-thumb-color: var(--_zoom-handle-color);\n /* Full-height thumbs in a band that is shorter than the MD3 default (44px),\n so the slider never overflows into the plot. */\n --md-slider-thumb-height: var(--_zoom-size);\n --md-slider-track-height: 12px;\n}\n\n/* Pan grip over the selected window: drag it to move the window without\n resizing. Inset at both ends (see renderZoomSlider) so a press near a thumb\n still reaches the slider's rail and resizes. */\n.md-line-chart__zoom-pan {\n position: absolute;\n inset-block: 0;\n z-index: 1;\n cursor: grab;\n touch-action: none;\n}\n\n.md-line-chart__zoom-pan:active {\n cursor: grabbing;\n}\n\n/* Live drag selection over the plot. */\n.md-line-chart__zoom-band {\n position: absolute;\n background: var(--_zoom-band-color);\n border-inline: 1px solid var(--_zoom-handle-color);\n pointer-events: none;\n}\n\n/* Screen-reader-only data table. Visually hidden but readable\n by AT; positioned absolute so it doesn't disturb layout.\n Uses the standard \"sr-only\" pattern (1px box with overflow\n hidden) — `display:none` would hide it from AT too. */\n/* Same visually-hidden technique as the data table below: readable by AT,\n invisible on screen, and out of the layout. */\n.md-line-chart__live {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* The plot takes focus for keyboard navigation, so it needs a visible ring —\n inset, because the canvas fills its box and an outset ring would be clipped\n by the host's padding. */\n/* The legend chips are engine-created buttons styled inline, and inline styles\n can't express :focus-visible — so their focus ring comes from here. Same\n neutral outline as the plot's, rather than the browser's blue default. */\n[part='legend'] button:focus-visible {\n /* Same ring md-button uses, so focus looks the same wherever it lands. */\n outline: 3px solid var(--md-sys-color-secondary, #625B71);\n outline-offset: 2px;\n border-radius: 6px;\n}\n\n.md-line-chart__canvas:focus-visible {\n /* Same ring as md-button. Inset, because the canvas fills its box and an\n outward ring would be clipped by the host's padding. */\n outline: 3px solid var(--md-sys-color-secondary, #625B71);\n outline-offset: -3px;\n border-radius: 4px;\n}\n\n.md-line-chart__a11y-table {\n position: absolute;\n inline-size: 1px;\n block-size: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n}\n\n/* Forced-colors (Windows high-contrast): we let ECharts use\n the system's CanvasText / Highlight colours by NOT pinning\n our own colour vars, so the chart inherits readable contrast\n automatically. Reduced-motion is handled in the theme reader\n (motion-duration → 0) so no animation overrides needed here. */\n@media (forced-colors: active) {\n :host {\n forced-color-adjust: auto;\n }\n}\n\n/* ==========================================================\n DENSITY (local override)\n Maps the local `density` prop onto the same --md-sys-density-scale signal a\n global `data-density` ancestor sets. Declared on :host, so a local rung wins\n over the inherited global one. Every density-sensitive value in this file\n derives from that single signal by calc — never add a fixed per-rung ladder.\n ========================================================== */\n:host([density='-1']) { --md-sys-density-scale: -1; }\n:host([density='-2']) { --md-sys-density-scale: -2; }\n:host([density='-3']) { --md-sys-density-scale: -3; }\n:host([density='-4']) { --md-sys-density-scale: -4; }\n","import {\n Component,\n Host,\n h,\n Prop,\n State,\n Event,\n EventEmitter,\n Element,\n Method,\n Watch,\n} from '@stencil/core';\nimport {\n buildChartSummary,\n buildDataTableHtml,\n datumY,\n defaultValueFormatter,\n normalizeSeriesX,\n pickPaletteColor,\n readMdChartTheme,\n remapIndexRecord,\n resolveAxisBands,\n resolveSeriesColor,\n LineChartEngine,\n type AxisSeriesValue,\n type EngineTheme,\n type LineChartSpec,\n type MdChartAnimation,\n type MdChartAxis,\n type MdChartAxisClickDetail,\n type MdChartAxisSeriesValue,\n type MdChartAxisValue,\n type MdChartClickDetail,\n type MdChartHoverDetail,\n type MdChartLegendPosition,\n type MdChartMarkLine,\n type MdChartStackMode,\n type MdChartTitleAlign,\n type MdChartTooltipRenderer,\n type MdChartTooltipTrigger,\n type MdChartXYSeries,\n type NormalizedSeriesX,\n} from '../../utils/charts';\n\n/**\n * md-line-chart — Material Design 3 line chart rendered by the\n * in-house chart engine (Canvas2D + a DOM text overlay). No\n * ECharts.\n *\n * Pattern parity with MUI X Charts:\n * • multi-series with per-series colour / label / curve\n * • category, time, value, log scales\n * • curve types: linear / smooth / monotone / step variants\n * • stacking: normal / percentage\n * • markers, area fills, gap bridging (`connectNulls`)\n * • legend with toggle + custom position\n * • hover crosshair + tooltip\n * • emits `mdMarkerClick`, `mdLineClick`, `mdAreaClick`, `mdAxisClick`,\n * `mdLegendClick`, `mdHover`\n *\n * MD3 expressive layer on top:\n * • palette resolves to `--md-sys-color-*` tokens\n * • dark theme + brand re-themes via CSS variables only\n * • a11y: role=\"figure\" + screen-reader-only data table\n * • fully responsive via ResizeObserver\n */\n@Component({\n tag: 'md-line-chart',\n styleUrl: 'md-line-chart.css',\n shadow: true,\n})\nexport class MdLineChart {\n @Element() el!: HTMLElement;\n\n /** Optional chart title rendered above the plot. */\n @Prop() label: string = '';\n\n /** Optional sub-title rendered under the title in the muted text colour. */\n @Prop() subtitle: string | undefined;\n\n /** Vertical reference lines across the plot (e.g. a \"current time\" divider). */\n @Prop() markLines: MdChartMarkLine[] | undefined;\n\n /** Title alignment over the plot: `start` (left), `center`, or `end` (right). */\n @Prop({ attribute: 'title-align' }) titleAlign: MdChartTitleAlign = 'start';\n\n /**\n * Series array. Each entry is one line. Empty → empty state.\n *\n * `data` is either a bare list of y values, positioned by index against\n * `xAxis.data`, or a list of points carrying their own x —\n * `{ x: '2021-11-13', y: 0.12 }` / `['2021-11-13', 0.12]`. Points are what\n * irregular data needs: uneven sampling, or several series measured on\n * completely different dates. Set `xAxis.scale = 'time'` (or `'value'`) so\n * the gaps render proportionally; series carrying their own x need no\n * `xAxis.data` at all.\n */\n @Prop() series: MdChartXYSeries[] = [];\n\n /** X-axis configuration. */\n @Prop() xAxis: MdChartAxis | undefined;\n\n /** Y-axis configuration. */\n @Prop() yAxis: MdChartAxis | undefined;\n\n /**\n * Multiple independent value (y) axes. When set (non-empty), each series is\n * measured against `yAxes[series.yAxisIndex ?? 0]`, and the axes stack outward\n * from the plot (first → left, rest → right, or per each axis' `position`).\n * Supersedes the single `yAxis`. Each axis keeps its own `min`/`max`/`scale`/\n * `valueFormatter`/`label`.\n */\n @Prop() yAxes: MdChartAxis[] | undefined;\n\n /** Default curve interpolation. Overridable per-series. */\n @Prop() curve: 'linear' | 'smooth' | 'monotone' | 'step' | 'step-before' | 'step-middle' = 'smooth';\n\n /** Stacking strategy. */\n @Prop() stack: MdChartStackMode = 'none';\n\n /** Whether `null` values are bridged with a straight line. */\n @Prop({ attribute: 'connect-nulls' }) connectNulls: boolean = false;\n\n /** Show data-point markers on every series by default. */\n @Prop({ attribute: 'show-marks' }) showMarks: boolean = false;\n\n /** Line stroke width in px, for every series. Default 2.5; a per-series\n * `series[].lineWidth` overrides it. */\n @Prop({ attribute: 'line-width' }) lineWidth?: number;\n /** Marker RADIUS in px, for every series. Overrides the per-symbol default; a\n * per-series `series[].markSize` wins. */\n @Prop({ attribute: 'mark-size' }) markSize?: number;\n\n /** Render the line area as a filled gradient below the line. */\n @Prop() area: boolean = false;\n\n /**\n * Draw the line for each series. Default `true`. Set `false` for a fill-only\n * chart (with `area`) or a marks-only chart — handy when a high `fillOpacity`\n * makes the same-coloured line vanish into the fill. A per-series\n * `series[].stroke` still wins over this.\n */\n @Prop({ attribute: 'show-line' }) showLine: boolean = true;\n\n /** Legend position. `'none'` hides the legend. */\n @Prop({ reflect: true }) legend: MdChartLegendPosition | 'none' = 'top-end';\n\n /** Tooltip interaction model. */\n @Prop() tooltip: MdChartTooltipTrigger = 'axis';\n\n /** Gridlines: horizontal (y ticks), vertical (x ticks), both, or none. */\n @Prop() grid: 'none' | 'horizontal' | 'vertical' | 'both' = 'horizontal';\n\n /** Draw small perpendicular tick marks on the axes. */\n @Prop({ attribute: 'axis-ticks' }) axisTicks: boolean = false;\n\n /** Transpose the axes — the x-axis data runs vertically and the values run\n * horizontally (e.g. a temperature-by-altitude spline). Best with `curve=\"smooth\"`. */\n @Prop() inverted: boolean = false;\n\n /** Print each point's value as a data label beside its marker. */\n @Prop({ attribute: 'show-labels' }) showLabels: boolean = false;\n\n /** Label each series at its last point with its name (follows the line end). */\n @Prop({ attribute: 'series-labels' }) seriesLabels: boolean = false;\n\n /**\n * Interactive zoom over the x range.\n * • `inside` — drag horizontally across the plot to zoom into that span;\n * double-click anywhere in the plot to reset.\n * • `slider` — an `md-slider` in range mode under the plot: drag either\n * thumb to resize the window, click the track to jump the nearest thumb,\n * drag the window itself to pan. Thumbs are focusable and take\n * Arrow/Home/End/PageUp/PageDown.\n * • `both` — both of the above.\n *\n * Zoom is a *view* over the data: `series`/`xAxis` are untouched, and\n * `mdHover`/`mdMarkerClick` keep reporting absolute indices into your data.\n */\n @Prop() zoom: 'none' | 'inside' | 'slider' | 'both' = 'none';\n\n /**\n * BCP-47 locale for the DEFAULT number / date formatting — axis ticks,\n * tooltip values and the screen-reader table. Empty follows the browser.\n * An explicit `valueFormatter` / `xAxis.valueFormatter` always wins, so a\n * consumer that formats its own values is unaffected.\n */\n @Prop() locale: string = '';\n\n /**\n * Text shown when there is no data. The `empty` slot still overrides it —\n * this is the prop form, for handing a string straight from a dictionary.\n */\n @Prop({ attribute: 'label-empty' }) labelEmpty: string = 'No data to display';\n\n /**\n * Instructions announced when the plot receives keyboard focus. The plot is\n * focusable so a keyboard user can walk the data with the arrow keys; this\n * is what tells them so.\n */\n @Prop({ attribute: 'label-plot' }) labelPlot: string =\n 'Chart data. Use the arrow keys to move between points, Home and End for the first and last, Escape to leave.';\n\n /**\n * Template for the live announcement made as keyboard focus moves. `%x%` is\n * the axis value and `%values%` the series readings at it.\n */\n @Prop({ attribute: 'label-point' }) labelPoint: string = '%x%: %values%';\n\n /** Accessible label for the zoom slider's start thumb. */\n @Prop({ attribute: 'label-zoom-start' }) labelZoomStart: string = 'Zoom range start';\n\n /** Accessible label for the zoom slider's end thumb. */\n @Prop({ attribute: 'label-zoom-end' }) labelZoomEnd: string = 'Zoom range end';\n\n /**\n * Replaces the generated `aria-label` outright. The default summary is\n * assembled in English (\"Revenue, Line chart, with 2 series, from Jan to\n * Dec.\"); rather than translate it piecewise, hand over the whole sentence\n * built in your own language.\n */\n @Prop() summary: string = '';\n\n /**\n * Translatable chrome for the screen-reader data table. `%shown%` and\n * `%total%` are substituted in `truncated`.\n */\n @Prop() tableLabels?: { x?: string; index?: string; series?: string; truncated?: string };\n\n /**\n * Format raw Y values for tooltips / a11y table.\n *\n * The tooltip also asks it about series with NO value at the hovered x —\n * `null` when the series has a null datum there, `undefined` when it has no\n * datum at all. Return `''` (or leave those cases unhandled) to keep the\n * default behaviour of omitting the series; return a string to show a row\n * for it — e.g. `(v) => (v === null ? 'no reading' : v === undefined ? '—' : v + ' m')`.\n */\n @Prop() valueFormatter?: (value: number | null | undefined) => string;\n\n /**\n * Replace the tooltip's content with your own. Receives everything the chart\n * knows about the hovered x — the axis value + its formatted label, and per\n * visible series the index, label, colour, raw and formatted value, and\n * whether it is the emphasised one — split into `series` (has a reading here)\n * and `missing` (does not).\n *\n * Return a DOM `Node` (what React / Vue / Angular renderers produce), a\n * string (inserted as TEXT, never parsed as markup), `{ unsafeHtml }` to opt\n * into raw HTML, `undefined` to fall back to the built-in tooltip, or `null`\n * for no tooltip at this x. The engine keeps positioning it, and it is still\n * the `tooltip` CSS part.\n */\n @Prop() tooltipRenderer?: MdChartTooltipRenderer;\n\n /** Force a specific height (CSS length). */\n @Prop({ attribute: 'height' }) heightProp?: string;\n\n /** Disable all animation (shorthand for `animation=\"none\"`). */\n @Prop({ attribute: 'no-animation' }) noAnimation: boolean = false;\n\n /** Entry-animation variant: `expressive` (default), `grow`, `fade`, `draw`, or `none`. */\n @Prop() animation: MdChartAnimation = 'expressive';\n\n /** Entry-animation duration override in ms (≤ 0 disables). */\n @Prop({ attribute: 'animation-duration' }) animationDuration?: number;\n\n\n /**\n * Data is still on its way — the chart covers the plot with a loader instead\n * of drawing an empty (or stale) axis, and marks itself `aria-busy`.\n *\n * Set it while the fetch is in flight and clear it when `series` arrives; the\n * entry animation replays on the way out, so the data draws itself in rather\n * than appearing fully formed. Slot `loading` to replace the default\n * indicator with your own skeleton.\n */\n @Prop({ reflect: true }) loading: boolean = false;\n\n /** Accessible + visible text under the loader. */\n @Prop({ attribute: 'loading-label' }) loadingLabel: string = 'Loading chart…';\n\n /**\n * Local density rung. Drives the same `--md-sys-density-scale` signal that a\n * global `data-density` ancestor sets, so a local value simply overrides the\n * inherited one. 0 = default, -4 = ultra-compact.\n */\n @Prop({ reflect: true }) density: 0 | -1 | -2 | -3 | -4 = 0;\n\n /** Fires on marker click. `dataIndex` addresses the clicked series' own\n * `data` array (its point index, for series that carry their own x). */\n @Event() mdMarkerClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when a series' drawn line is clicked *between* its data points (a\n * click on a point emits `mdMarkerClick` instead). `dataIndex` is the point\n * the click is nearest along x. */\n @Event() mdLineClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when a series' filled area is clicked (`area` charts only) — the\n * region between that series' line and its baseline, excluding its line and\n * points. `dataIndex` is the point the click is nearest along x. */\n @Event() mdAreaClick!: EventEmitter<MdChartClickDetail<MdChartXYSeries>>;\n\n /** Fires when the plot background is clicked (inside the plot, but not on a\n * mark, line or area): the nearest x position plus every visible series'\n * value there. */\n @Event() mdAxisClick!: EventEmitter<MdChartAxisClickDetail>;\n\n /** Fires when a legend entry is clicked. */\n @Event() mdLegendClick!: EventEmitter<{ seriesIndex: number; seriesId?: string; selected: boolean }>;\n\n /** Fires (throttled to rAF) as the pointer crosses the plot. */\n @Event() mdHover!: EventEmitter<MdChartHoverDetail>;\n\n /** Fires after the chart finishes its initial render. */\n @Event() mdReady!: EventEmitter<void>;\n\n /** Fires when the zoom window changes (drag, slider or `setZoom`/`resetZoom`). */\n @Event() mdZoom!: EventEmitter<{ startIndex: number; endIndex: number; reset: boolean }>;\n\n @State() private mounted = false;\n\n /** Index the keyboard cursor sits on, or -1 when the plot isn't focused. */\n @State() private kbIndex = -1;\n\n /** Text for the aria-live region — what a screen reader speaks on move. */\n @State() private announcement = '';\n\n /** Visible index window, or null for the full range. */\n @State() private zoomWin: { start: number; end: number } | null = null;\n\n /** Live drag rectangle (plot-relative px) while selecting a range to zoom. */\n @State() private dragBand: { x1: number; x2: number } | null = null;\n\n /**\n * Pointer id + origin of an in-progress gesture: `band` is a drag across the\n * plot, `pan` is a drag of the zoom window. (Resizing the window is the\n * slider's own gesture — see `renderZoomSlider`.)\n */\n private grab: { id: number; kind: 'band' | 'pan'; x: number; win: { start: number; end: number } } | null = null;\n\n private engine: LineChartEngine | null = null;\n private ro: ResizeObserver | null = null;\n private chartHost?: HTMLDivElement;\n private a11yTableHost?: HTMLDivElement;\n private themeMql?: MediaQueryList;\n private themeListener?: () => void;\n /**\n * Legend-toggle memory, keyed by series identity (id → label → position).\n * A legend click self-toggles the engine, but a live-updating consumer that\n * re-feeds `series` every frame (e.g. a line-race) would otherwise rebuild the\n * spec with the prop's `hidden` and lose the toggle. We remember the toggle\n * here and re-apply it in `buildSpec`, so visibility survives data updates\n * (ECharts-style), while an explicit `series[i].hidden` prop still wins.\n */\n private legendHidden = new Map<string, boolean>();\n\n /** Memo for {@link merged}, keyed on the identity of what it was built from. */\n private mergeCache: {\n series: unknown;\n axis: unknown;\n scale: string;\n out: NormalizedSeriesX;\n } | null = null;\n\n // ─────────────────── lifecycle ───────────────────\n\n componentDidLoad() {\n this.initChart();\n if (typeof window !== 'undefined' && window.matchMedia) {\n this.themeMql = window.matchMedia('(prefers-color-scheme: dark)');\n this.themeListener = () => this.applyEngine();\n this.themeMql.addEventListener?.('change', this.themeListener);\n }\n }\n\n disconnectedCallback() {\n this.ro?.disconnect();\n this.ro = null;\n this.engine?.dispose();\n this.engine = null;\n if (this.themeMql && this.themeListener) {\n this.themeMql.removeEventListener?.('change', this.themeListener);\n this.themeListener = undefined;\n this.themeMql = undefined;\n }\n }\n\n @Watch('series')\n @Watch('xAxis')\n @Watch('yAxis')\n @Watch('yAxes')\n @Watch('curve')\n @Watch('stack')\n @Watch('area')\n @Watch('showLine')\n @Watch('legend')\n @Watch('tooltip')\n @Watch('grid')\n @Watch('axisTicks')\n @Watch('inverted')\n @Watch('showLabels')\n @Watch('seriesLabels')\n @Watch('connectNulls')\n @Watch('showMarks')\n @Watch('lineWidth')\n @Watch('markSize')\n @Watch('label')\n @Watch('subtitle')\n @Watch('markLines')\n @Watch('titleAlign')\n @Watch('animation')\n @Watch('animationDuration')\n @Watch('tooltipRenderer')\n @Watch('valueFormatter')\n onAnyPropChange() {\n this.applyEngine();\n this.rebuildA11yTable();\n }\n\n /**\n * Coming OUT of the loading state, replay the entry motion so the data that\n * just arrived draws itself in instead of appearing fully formed behind the\n * fading loader. (Going in needs nothing — the loader covers the plot.)\n */\n @Watch('loading')\n onLoadingChange(now: boolean, before: boolean) {\n if (before && !now) this.engine?.replay();\n }\n\n // ─────────────────── public API ───────────────────\n\n /** Force a resize — useful after the chart was hidden then shown. */\n @Method()\n async resize(): Promise<void> {\n this.engine?.resize();\n }\n\n /** Replay the entry animation from the start (uses the current `animation`). */\n @Method()\n async replay(): Promise<void> {\n this.engine?.replay();\n }\n\n /** Render the current frame to a PNG data URL. */\n @Method()\n async toDataURL(): Promise<string> {\n return this.engine?.toDataURL('image/png') ?? '';\n }\n\n /** Return the underlying chart engine for advanced cases. */\n @Method()\n async getInstance(): Promise<LineChartEngine | null> {\n return this.engine;\n }\n\n // ─────────────────── internals ───────────────────\n\n private bindChartHost = (el?: HTMLDivElement) => {\n this.chartHost = el;\n };\n\n private bindA11yTableHost = (el?: HTMLDivElement) => {\n this.a11yTableHost = el;\n };\n\n private initChart() {\n this.makeEngine();\n this.applyEngine();\n this.rebuildA11yTable();\n this.mounted = true;\n this.mdReady.emit();\n }\n\n /** (Re)create the engine on the selected backend + wire its ResizeObserver. */\n private makeEngine() {\n if (!this.chartHost) return;\n this.ro?.disconnect();\n this.ro = null;\n this.engine?.dispose();\n try {\n this.engine = new LineChartEngine(this.chartHost);\n } catch {\n // No usable DOM (mock-doc / SSR / no canvas). Stay mounted;\n // ResizeObserver / a prop change will retry in a real browser.\n this.engine = null;\n }\n if (this.engine && typeof ResizeObserver !== 'undefined') {\n this.ro = new ResizeObserver(() => this.engine?.resize());\n this.ro.observe(this.chartHost);\n }\n }\n\n\n private buildEngineTheme(t: ReturnType<typeof readMdChartTheme>): EngineTheme {\n return {\n background: t.background,\n textColor: t.textColor,\n textColorMuted: t.textColorMuted,\n axisLineColor: t.axisLineColor,\n gridLineColor: t.gridColor,\n surface: t.surface,\n fontFamily: t.fontFamily,\n labelSize: t.labelSize,\n titleSize: t.titleSize,\n };\n }\n\n /**\n * Collision-free identity per series for the legend-toggle memory. Prefers a\n * consumer `id`, else `label`, else positional index; duplicates of the same\n * base are disambiguated by occurrence (`#1`, `#2`, …) so two same-labelled\n * series never share one memory slot (a click on one would otherwise hide\n * both). A unique id/label stays stable across a re-fed reorder.\n */\n private seriesKeys(): string[] {\n const seen = new Map<string, number>();\n return this.series.map((s, i) => {\n const base = s.id != null ? `id:${s.id}` : s.label != null ? `label:${s.label}` : `pos:${i}`;\n const n = seen.get(base) ?? 0;\n seen.set(base, n + 1);\n return n === 0 ? base : `${base}#${n}`;\n });\n }\n\n /** Record a legend toggle so `buildSpec` re-applies it across series re-feeds. */\n private rememberLegendToggle(seriesIndex: number, hidden: boolean): void {\n const key = this.seriesKeys()[seriesIndex];\n if (key == null) return;\n this.legendHidden.set(key, hidden);\n // Backstop against unbounded growth (only legend clicks add entries, so this\n // realistically never trips): evict the oldest toggle.\n if (this.legendHidden.size > 256) {\n const oldest = this.legendHidden.keys().next().value as string;\n this.legendHidden.delete(oldest);\n }\n }\n\n // ─────────────────── zoom ───────────────────\n\n private get zoomInside(): boolean {\n return this.zoom === 'inside' || this.zoom === 'both';\n }\n\n private get zoomSliderOn(): boolean {\n return this.zoom === 'slider' || this.zoom === 'both';\n }\n\n /**\n * Series merged onto one x axis (see `utils/charts/xy.ts`). Pass-through\n * unless a series carries its own x, and memoised on the identity of the\n * inputs so a render / hover / zoom trio doesn't re-merge the same feed.\n */\n private get merged(): NormalizedSeriesX {\n const scale = this.xAxis?.scale ?? 'category';\n const axis = this.xAxis?.data;\n const c = this.mergeCache;\n if (c && c.series === this.series && c.axis === axis && c.scale === scale) return c.out;\n const out = normalizeSeriesX(this.series ?? [], axis, scale);\n this.mergeCache = { series: this.series, axis, scale, out };\n return out;\n }\n\n /** Number of datapoints along x — the longest series, or the axis if longer. */\n private dataLength(): number {\n const m = this.merged;\n const s = m.data.reduce((acc, d) => Math.max(acc, d?.length ?? 0), 0);\n return Math.max(s, m.xValues.length);\n }\n\n /** Current window, defaulted to the full range and clamped to the data. */\n private win(): { start: number; end: number } {\n const last = Math.max(0, this.dataLength() - 1);\n const w = this.zoomWin;\n if (!w) return { start: 0, end: last };\n // Keep at least two points visible, else there is no line to draw.\n const start = Math.min(Math.max(0, w.start), Math.max(0, last - 1));\n return { start, end: Math.min(Math.max(start + 1, w.end), last) };\n }\n\n private applyZoom(start: number, end: number, reset = false): void {\n const last = Math.max(0, this.dataLength() - 1);\n const s = Math.min(Math.max(0, Math.round(start)), Math.max(0, last - 1));\n const e = Math.min(Math.max(s + 1, Math.round(end)), last);\n this.zoomWin = reset ? null : { start: s, end: e };\n this.applyEngine();\n this.rebuildA11yTable();\n this.mdZoom.emit({ startIndex: reset ? 0 : s, endIndex: reset ? last : e, reset });\n }\n\n /** Zoom to an absolute index range. */\n @Method()\n async setZoom(startIndex: number, endIndex: number): Promise<void> {\n this.applyZoom(startIndex, endIndex);\n }\n\n /** Drop the zoom window and show the full range. */\n @Method()\n async resetZoom(): Promise<void> {\n this.applyZoom(0, 0, true);\n }\n\n /**\n * Plot rect in CANVAS coordinates, from the live scene.\n *\n * The engine lays the scene out relative to the canvas box, which the host's\n * padding insets from the host box — so canvas and host space differ by that\n * padding. Everything that compares against the scene (`indexAtX` reads\n * `scene.xPositions`, which is canvas-space too) converts the pointer INTO\n * this space via `hostX`; only the drag band, positioned against the host,\n * converts back out.\n */\n private plotRect(): { x: number; y: number; width: number; height: number } | null {\n const p = this.engine?.getScene()?.plot;\n return p ? { x: p.x, y: p.y, width: p.width, height: p.height } : null;\n }\n\n /** Offset of the canvas box inside the host box — canvas space → host space. */\n private canvasOffset(): { x: number; y: number } {\n const canvas = this.chartHost;\n if (!canvas) return { x: 0, y: 0 };\n const host = this.el.getBoundingClientRect();\n const box = canvas.getBoundingClientRect();\n return { x: box.left - host.left, y: box.top - host.top };\n }\n\n /** Drag-band geometry, converted from canvas space back out to host space. */\n private zoomBandStyle(): { [key: string]: string } | undefined {\n const plot = this.plotRect();\n if (!this.dragBand || !plot) return undefined;\n const off = this.canvasOffset();\n const { x1, x2 } = this.dragBand;\n return {\n left: `${off.x + Math.min(x1, x2)}px`,\n width: `${Math.abs(x2 - x1)}px`,\n top: `${off.y + plot.y}px`,\n height: `${plot.height}px`,\n };\n }\n\n /** Map a canvas-relative x to the nearest ABSOLUTE data index. */\n private indexAtX(hostX: number): number {\n const scene = this.engine?.getScene();\n const w = this.win();\n if (!scene?.xPositions?.length) return w.start;\n let best = 0;\n let bestD = Infinity;\n scene.xPositions.forEach((px, i) => {\n const d = Math.abs(px - hostX);\n if (d < bestD) {\n bestD = d;\n best = i;\n }\n });\n return w.start + best;\n }\n\n /** Pointer x in CANVAS coordinates — the space `plotRect`/`xPositions` use. */\n private hostX(e: MouseEvent): number {\n return e.clientX - (this.chartHost ?? this.el).getBoundingClientRect().left;\n }\n\n /** Is the event over the plot itself (as opposed to the header, zoom slider, footer)? */\n private insidePlot(e: MouseEvent): boolean {\n const plot = this.plotRect();\n if (!plot) return false;\n const box = (this.chartHost ?? this.el).getBoundingClientRect();\n const x = e.clientX - box.left;\n const y = e.clientY - box.top;\n return x >= plot.x && x <= plot.x + plot.width && y >= plot.y && y <= plot.y + plot.height;\n }\n\n private onPlotPointerDown = (e: PointerEvent) => {\n if (!this.zoomInside || e.button !== 0 || this.grab) return;\n if (!this.insidePlot(e)) return;\n const x = this.hostX(e);\n this.grab = { id: e.pointerId, kind: 'band', x, win: this.win() };\n this.dragBand = { x1: x, x2: x };\n // Capture so the gesture survives the pointer leaving the plot — on the\n // element really under the pointer, NOT on `e.target`. This listener sits on\n // the host, so the shadow-internal target is retargeted to the host itself,\n // and capturing there sends the whole gesture — including the `click` that\n // closes it — to the host, where the engine's plot canvas never sees it. That\n // silently killed every chart click event whenever zoom was on.\n const target = (e.composedPath?.()[0] as HTMLElement | undefined) ?? (e.target as HTMLElement);\n target.setPointerCapture?.(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent) => {\n const g = this.grab;\n if (!g || g.id !== e.pointerId) return;\n if (g.kind === 'band') {\n const plot = this.plotRect();\n if (!plot) return;\n this.dragBand = { x1: g.x, x2: Math.min(Math.max(this.hostX(e), plot.x), plot.x + plot.width) };\n return;\n }\n // Pan: shift the window by the pointer's travel along the slider track,\n // keeping its span. Fractions of the full range, so it tracks the thumbs.\n const frac = this.trackFrac(e.clientX);\n const originFrac = this.trackFrac(g.x);\n if (frac == null || originFrac == null) return;\n const last = Math.max(1, this.dataLength() - 1);\n const span = g.win.end - g.win.start;\n const delta = Math.round((frac - originFrac) * last);\n const s = Math.min(Math.max(0, g.win.start + delta), last - span);\n this.applyZoom(s, s + span);\n };\n\n private onPointerUp = (e: PointerEvent) => {\n const g = this.grab;\n if (!g || g.id !== e.pointerId) return;\n this.grab = null;\n const band = this.dragBand;\n this.dragBand = null;\n if (g.kind !== 'band' || !band) return;\n // A tiny drag is a click, not a zoom — leave the view alone so marker\n // clicks and tooltips keep working.\n if (Math.abs(band.x2 - band.x1) < 8) return;\n // In RTL the plot is mirrored, so the LEFT edge of the band is the LATER\n // index — order by index, not by pixel, or the window comes out reversed.\n const [a, b] = [this.indexAtX(band.x1), this.indexAtX(band.x2)].sort((m, n) => m - n);\n if (b - a >= 1) this.applyZoom(a, b);\n };\n\n /**\n * Walk the data with the keyboard. The chart's information was previously\n * reachable only by hovering, which no keyboard or screen-reader user can\n * do; this gives them the same crosshair, tooltip and values.\n *\n * Arrow keys follow the READING direction, so in RTL, Left advances — the\n * plot is mirrored and an arrow that moved \"back\" visually would be wrong.\n */\n private onPlotKeyDown = (e: KeyboardEvent) => {\n const last = Math.max(0, this.dataLength() - 1);\n if (last < 0) return;\n const rtl = typeof getComputedStyle === 'function' && getComputedStyle(this.el).direction === 'rtl';\n const forward = rtl ? 'ArrowLeft' : 'ArrowRight';\n const back = rtl ? 'ArrowRight' : 'ArrowLeft';\n let next = this.kbIndex;\n switch (e.key) {\n case forward:\n next = this.kbIndex < 0 ? 0 : Math.min(last, this.kbIndex + 1);\n break;\n case back:\n next = this.kbIndex < 0 ? last : Math.max(0, this.kbIndex - 1);\n break;\n case 'Home':\n next = 0;\n break;\n case 'End':\n next = last;\n break;\n case 'Escape':\n if (this.kbIndex < 0) return;\n next = -1;\n break;\n case 'Enter':\n case ' ':\n if (this.kbIndex < 0) return;\n // Keyboard parity with clicking the plot background: the focus is on an\n // x position, not one series, which is exactly what mdAxisClick reports.\n this.mdAxisClick.emit(this.axisDetail(this.kbIndex, this.seriesValuesAt(this.kbIndex), e));\n e.preventDefault();\n return;\n default:\n return;\n }\n e.preventDefault();\n this.moveKeyboardCursor(next);\n };\n\n private onPlotBlur = () => {\n if (this.kbIndex >= 0) this.moveKeyboardCursor(-1);\n };\n\n /** Move the keyboard cursor, mirroring it into the hover UI and the live region. */\n private moveKeyboardCursor(next: number) {\n this.kbIndex = next;\n this.engine?.focusIndex(next);\n if (next < 0) {\n this.announcement = '';\n return;\n }\n const m = this.merged;\n const xRaw = m.xValues[next];\n const xText = this.xAxis?.valueFormatter\n ? this.xAxis.valueFormatter(xRaw)\n : defaultValueFormatter(xRaw ?? next + 1, this.locale);\n const yFmt = (v: number) =>\n this.valueFormatter ? this.valueFormatter(v) : v.toLocaleString(this.locale || undefined);\n const values = this.seriesValuesAt(next)\n .filter((sv: AxisSeriesValue) => sv.value != null)\n .map((sv: AxisSeriesValue) => `${sv.label} ${yFmt(sv.value as number)}`)\n .join(', ');\n this.announcement = this.labelPoint.replace('%x%', xText).replace('%values%', values);\n this.mdHover.emit({ dataIndex: next, axisValue: xRaw, seriesIndices: this.visibleSeriesIndices() });\n }\n\n private onPlotDblClick = (e: MouseEvent) => {\n // Plot only: a double-click on the zoom slider is two track clicks, not a\n // request to throw the window away.\n if (this.zoomInside && this.zoomWin && this.insidePlot(e)) this.resetZoom();\n };\n\n /**\n * The zoom slider's track box. `md-slider` maps 0→100% across its own host\n * box (surface and rail both flex to fill it), so the host rect *is* the\n * track — measuring it keeps the pan gesture in step with the thumbs.\n */\n private sliderTrackRect(): { left: number; width: number; rtl: boolean } | null {\n const slider = this.el.shadowRoot?.querySelector('.md-line-chart__zoom-slider');\n if (!slider) return null;\n const r = slider.getBoundingClientRect();\n if (!r.width) return null;\n return { left: r.left, width: r.width, rtl: getComputedStyle(this.el).direction === 'rtl' };\n }\n\n /** Client x → fraction along the zoom track (RTL-aware, as md-slider is). */\n private trackFrac(clientX: number): number | null {\n const track = this.sliderTrackRect();\n if (!track) return null;\n const raw = (clientX - track.left) / track.width;\n return Math.min(Math.max(track.rtl ? 1 - raw : raw, 0), 1);\n }\n\n private onZoomPanDown = (e: PointerEvent) => {\n if (e.button !== 0) return;\n // Keep it away from the plot-drag handler on the host, and from the\n // slider's own rail (which would resize instead of pan).\n e.stopPropagation();\n e.preventDefault();\n this.grab = { id: e.pointerId, kind: 'pan', x: e.clientX, win: this.win() };\n (e.target as HTMLElement).setPointerCapture?.(e.pointerId);\n };\n\n /** md-slider drives the window while a thumb moves (continuous). */\n private onZoomSliderInput = (e: CustomEvent<{ valueStart?: number; valueEnd?: number }>) => {\n // md-slider's events are composed, so they would surface on the chart's own\n // host and look like chart events to a consumer. Stop them here.\n e.stopPropagation();\n const { valueStart, valueEnd } = e.detail ?? {};\n if (valueStart == null || valueEnd == null) return;\n this.applyZoom(valueStart, valueEnd);\n };\n\n /** Swallow the slider's remaining composed events (see above). mdInput has\n * already applied the window, so the commit needs no second applyZoom. */\n private onZoomSliderEvent = (e: Event) => e.stopPropagation();\n\n private buildSpec(t: ReturnType<typeof readMdChartTheme>): LineChartSpec {\n const percentage = this.stack === 'percentage';\n const yFmt = (v: number) =>\n this.valueFormatter ? this.valueFormatter(v) : v.toLocaleString(this.locale || undefined);\n // Re-apply remembered legend toggles by identity. We do NOT prune here: a\n // series that blips out of the feed for a frame must keep its toggle when it\n // returns. Growth is bounded in rememberLegendToggle instead.\n const keys = this.seriesKeys();\n // Zoom is a view: slice what the engine draws, leave `this.series` alone.\n // Anything index-addressed (dashAfter, pointSymbols, markIndices, markLines\n // on a category axis) is rebased into window coordinates, and anything that\n // falls outside the window is dropped.\n const zw = this.zoomWin ? this.win() : null;\n const cut = <T,>(arr: T[] | undefined): T[] | undefined =>\n arr && zw ? arr.slice(zw.start, zw.end + 1) : arr;\n const rebaseMap = <T,>(rec: Record<number, T> | undefined): Record<number, T> | undefined => {\n if (!rec || !zw) return rec;\n const out: Record<number, T> = {};\n for (const [k, v] of Object.entries(rec)) {\n const i = Number(k) - zw.start;\n if (i >= 0 && i <= zw.end - zw.start) out[i] = v;\n }\n return out;\n };\n // Series that carry their own x are merged onto one axis first; index-\n // addressed options (pointSymbols, dashAfter) are rebased onto it before\n // the zoom window rebases them again.\n const m = this.merged;\n const series = this.series.map((s, i) => {\n const key = keys[i];\n const remembered = this.legendHidden.get(key);\n const toMerged = m.toMerged[i];\n const dashAt = s.dashAfter != null && toMerged ? toMerged[s.dashAfter] : s.dashAfter;\n // An explicit `hidden` prop takes control: it wins AND clears the legend\n // memory, so the consumer's value sticks across later omitted-hidden frames\n // (a 'show all' reset isn't silently re-hidden on the next frame).\n if (s.hidden !== undefined) this.legendHidden.delete(key);\n return {\n label: s.label ?? `Series ${i + 1}`,\n color: resolveSeriesColor(this.el, s.color, pickPaletteColor(t.palette, i)),\n data: cut(m.data[i]) ?? m.data[i] ?? [],\n curve: s.curve ?? this.curve,\n connectNulls: s.connectNulls ?? this.connectNulls,\n showMarks: s.showMarks ?? this.showMarks,\n hidden: s.hidden ?? remembered ?? false,\n dash: s.dash,\n symbol: s.symbol,\n pointSymbols: rebaseMap(remapIndexRecord(s.pointSymbols, toMerged)),\n yAxisIndex: s.yAxisIndex,\n dashAfter: dashAt != null && dashAt >= 0 && zw ? dashAt - zw.start : dashAt,\n hollow: s.hollow,\n stroke: s.stroke ?? (this.showLine ? undefined : false),\n lineWidth: s.lineWidth ?? this.lineWidth,\n markSize: s.markSize ?? this.markSize,\n };\n });\n return {\n series,\n title: this.label || undefined,\n subtitle: this.subtitle || undefined,\n markLines: this.markLines\n ?.map((ml) => {\n // On a category axis the value IS an index, so it rebases with the\n // window; on a value axis it is a real x value and must not move.\n const indexed = zw != null && (this.xAxis?.scale ?? 'category') === 'category' && typeof ml.value === 'number';\n const value = indexed ? (ml.value as number) - zw!.start : ml.value;\n return {\n value,\n label: ml.label,\n color: ml.color != null ? resolveSeriesColor(this.el, ml.color, ml.color) : undefined,\n dash: ml.dash,\n // Rebased out of view — dropped below rather than drawn at the edge.\n offscreen: indexed && (Number(value) < 0 || Number(value) > zw!.end - zw!.start),\n };\n })\n .filter((ml) => !ml.offscreen)\n .map(({ offscreen: _drop, ...ml }) => ml),\n titleAlign: this.titleAlign,\n xValues: cut(m.xValues) ?? [],\n xScale: this.xAxis?.scale ?? 'category',\n xFormatter: this.xAxis?.valueFormatter ?? ((v: MdChartAxisValue) => defaultValueFormatter(v, this.locale)),\n xLabel: this.xAxis?.label,\n xHidden: this.xAxis?.hidden,\n xHideTicks: this.xAxis?.hideTicks,\n xDash: this.xAxis?.dash,\n xGridDash: this.xAxis?.gridDash,\n xBands: resolveAxisBands(this.el, this.xAxis?.bands),\n yBands: resolveAxisBands(this.el, this.yAxis?.bands),\n xBreaks: this.xAxis?.breaks,\n yBreaks: this.yAxis?.breaks,\n yScale: this.yAxis?.scale ?? 'value',\n yMin: percentage ? 0 : this.yAxis?.min,\n yMax: percentage ? 100 : this.yAxis?.max,\n yFormatter: percentage ? (v: number) => `${Math.round(v)}%` : yFmt,\n // The axis can format independently of the values (bare numbers on the\n // axis, units in the tooltip); unset → the axis follows `valueFormatter`.\n yTickFormatter:\n !percentage && this.yAxis?.valueFormatter ? (v: number) => this.yAxis!.valueFormatter!(v) : undefined,\n yLabel: this.yAxis?.label,\n yHidden: this.yAxis?.hidden,\n yHideTicks: this.yAxis?.hideTicks,\n yDash: this.yAxis?.dash,\n yGridDash: this.yAxis?.gridDash,\n yAxes: this.yAxes?.length\n ? this.yAxes.map((a) => ({\n scale: a.scale ?? 'value',\n min: a.min,\n max: a.max,\n formatter: a.valueFormatter\n ? (v: number) => a.valueFormatter!(v)\n : (v: number) => v.toLocaleString(this.locale || undefined),\n label: a.label,\n position: a.position,\n hidden: a.hidden,\n hideTicks: a.hideTicks,\n color: a.color != null ? resolveSeriesColor(this.el, a.color, a.color) : undefined,\n bands: resolveAxisBands(this.el, a.bands),\n dash: a.dash,\n gridDash: a.gridDash,\n }))\n : undefined,\n stack: this.stack,\n area: this.area,\n legend: this.legend,\n gridY: this.grid === 'horizontal' || this.grid === 'both',\n gridX: this.grid === 'vertical' || this.grid === 'both',\n axisTicks: this.axisTicks,\n inverted: this.inverted,\n showLabels: this.showLabels,\n seriesLabels: this.seriesLabels,\n animation: this.noAnimation ? 'none' : this.animation,\n animationDuration: this.animationDuration,\n };\n }\n\n private applyEngine() {\n if (!this.engine) return;\n const t = readMdChartTheme(this.el);\n this.engine.setSpec(this.buildSpec(t), this.buildEngineTheme(t), {\n onHover: (idx) => {\n if (idx < 0) return;\n // The engine indexes the sliced view; consumers get absolute indices.\n const abs = idx + (this.zoomWin ? this.win().start : 0);\n this.mdHover.emit({\n dataIndex: abs,\n axisValue: this.merged.xValues[abs],\n seriesIndices: this.visibleSeriesIndices(),\n });\n },\n onLegendClick: (item) => {\n // Remember the toggle so it survives a live consumer re-feeding `series`\n // every frame (the engine self-toggles; buildSpec re-applies this).\n this.rememberLegendToggle(item.seriesIndex, !!item.hidden);\n this.mdLegendClick.emit({\n seriesIndex: item.seriesIndex,\n seriesId: this.series[item.seriesIndex]?.id,\n selected: !item.hidden,\n });\n },\n onPointClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdMarkerClick.emit(d);\n },\n onLineClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdLineClick.emit(d);\n },\n onAreaClick: (si, di, e) => {\n const d = this.clickDetail(si, di, e);\n if (d) this.mdAreaClick.emit(d);\n },\n onAxisClick: (di, values, e) => this.mdAxisClick.emit(this.axisDetail(di, values, e)),\n });\n // Honour the tooltip prop — the engine only exposes a hover on/off toggle.\n this.engine.setHoverEnabled(this.tooltip !== 'none');\n this.engine.setTooltip({\n render: this.tooltipRenderer,\n missingFormatter: this.valueFormatter,\n // `item` reports only the series under the cursor; `axis` lists them all.\n trigger: this.tooltip === 'item' ? 'item' : 'axis',\n });\n }\n\n /**\n * The payload shared by the three per-series click events (marker / line /\n * area). The engine reports indices into what it drew, so both the zoom\n * window and the merge onto one x axis are undone here: `dataIndex` addresses\n * the consumer's OWN array (for a series carrying its own x, that's its point\n * index, not the merged one).\n */\n private clickDetail(si: number, di: number, e: PointerEvent): MdChartClickDetail<MdChartXYSeries> | null {\n const s = this.series[si];\n if (!s) return null;\n const abs = di + (this.zoomWin ? this.win().start : 0);\n const own = this.ownIndex(si, abs);\n return {\n seriesIndex: si,\n seriesId: s.id,\n dataIndex: own >= 0 ? own : abs,\n value: own >= 0 ? datumY(s.data[own]) : null,\n axisValue: this.merged.xValues[abs],\n nativeEvent: e,\n series: s,\n };\n }\n\n /** Index into series `si`'s own `data` for an absolute (merged) x index, or\n * -1 when that series has no point there. */\n private ownIndex(si: number, abs: number): number {\n const toOwn = this.merged.toOwn[si];\n return toOwn ? toOwn[abs] ?? -1 : abs;\n }\n\n /** `mdAxisClick`'s payload: the x the click is nearest, plus the reading of\n * every visible series there (the rows the tooltip would show). */\n /**\n * Every visible series' reading at a data index, in the shape the axis-click\n * detail and the keyboard announcement both want. Read from the live scene,\n * so a legend-toggled series is excluded exactly as it is on screen.\n */\n private seriesValuesAt(di: number): AxisSeriesValue[] {\n const hp = this.engine?.getScene()?.hoverPoints ?? [];\n return hp.map((h) => ({\n seriesIndex: h.seriesIndex,\n label: h.label,\n value: h.byIndex[di]?.value ?? null,\n }));\n }\n\n private axisDetail(di: number, values: AxisSeriesValue[], e: PointerEvent | KeyboardEvent): MdChartAxisClickDetail {\n const abs = di + (this.zoomWin ? this.win().start : 0);\n const seriesValues: MdChartAxisSeriesValue[] = values.map((v) => {\n const own = this.ownIndex(v.seriesIndex, abs);\n return {\n seriesIndex: v.seriesIndex,\n seriesId: this.series[v.seriesIndex]?.id,\n label: v.label,\n dataIndex: v.value == null ? -1 : own,\n value: v.value,\n };\n });\n return { dataIndex: abs, axisValue: this.merged.xValues[abs], seriesValues, nativeEvent: e };\n }\n\n /** Visible (non-toggled-off) series indices — reads the engine's live state so\n * an uncontrolled legend toggle is reflected, falling back to the prop. */\n private visibleSeriesIndices(): number[] {\n const hp = this.engine?.getScene()?.hoverPoints;\n if (hp) return hp.map((h) => h.seriesIndex);\n const keys = this.seriesKeys();\n return this.series\n .map((_, i) => i)\n .filter((i) => !(this.series[i].hidden ?? this.legendHidden.get(keys[i]) ?? false));\n }\n\n private rebuildA11yTable() {\n if (!this.a11yTableHost) return;\n // The table mirrors what's drawn, so it reads the merged axis: one row per\n // x, and a series with no sample at that x gets an empty cell.\n const m = this.merged;\n this.a11yTableHost.innerHTML = buildDataTableHtml({\n title: this.label,\n xAxisLabel: this.xAxis?.label,\n xAxisData: m.xValues,\n xValueFormatter: this.xAxis?.valueFormatter ?? ((v: MdChartAxisValue) => defaultValueFormatter(v, this.locale)),\n locale: this.locale,\n labels: this.tableLabels,\n series: this.series.map((s, i) => ({ label: s.label, data: m.data[i] ?? [] })),\n valueFormatter: this.valueFormatter,\n });\n }\n\n // ─────────────────── render ───────────────────\n\n /**\n * Range slider under the plot — the house `md-slider` in range mode, so the\n * thumbs, track, keyboard support and theming all come from the design\n * system. The chart stays the source of truth (`controlled`) because it\n * clamps the window to at least two points; on top of it sits a pan grip,\n * which is the one gesture a plain slider has no notion of.\n */\n private renderZoomSlider() {\n const last = Math.max(1, this.dataLength() - 1);\n const w = this.win();\n const pct = (i: number) => (i / last) * 100;\n const fmt = (i: number) => String(this.xAxis?.data?.[i] ?? i);\n return (\n <div class=\"md-line-chart__zoom\" part=\"zoom\">\n <md-slider\n class=\"md-line-chart__zoom-slider\"\n part=\"zoom-slider\"\n exportparts=\"track: zoom-track, track-active: zoom-window, thumb-knob: zoom-handle\"\n range\n controlled\n min={0}\n max={last}\n step={1}\n valueStart={w.start}\n valueEnd={w.end}\n ariaLabelStart={this.labelZoomStart}\n ariaLabelEnd={this.labelZoomEnd}\n valueStartText={fmt(w.start)}\n valueEndText={fmt(w.end)}\n onMdInput={this.onZoomSliderInput}\n onMdChange={this.onZoomSliderEvent}\n onMdDragStart={this.onZoomSliderEvent}\n onMdDragEnd={this.onZoomSliderEvent}\n onMdFocus={this.onZoomSliderEvent}\n onMdBlur={this.onZoomSliderEvent}\n ></md-slider>\n\n {/* Pan grip over the selected window. Inset at both ends so the thumbs\n stay grabbable, and it collapses to nothing on a narrow window. */}\n <div\n class=\"md-line-chart__zoom-pan\"\n part=\"zoom-pan\"\n style={{\n insetInlineStart: `calc(${pct(w.start)}% + var(--_zoom-pan-inset))`,\n inlineSize: `max(0px, calc(${pct(w.end) - pct(w.start)}% - 2 * var(--_zoom-pan-inset)))`,\n }}\n onPointerDown={this.onZoomPanDown}\n ></div>\n </div>\n );\n }\n\n render() {\n // Merged, so the announced range covers series that carry their own x.\n const xValues = this.merged.xValues;\n const summary =\n this.summary ||\n buildChartSummary({\n title: this.label,\n chartType: this.area ? 'area' : 'line',\n seriesCount: this.series.length,\n xMin: xValues[0] as MdChartAxisValue | undefined,\n xMax: xValues[xValues.length - 1] as MdChartAxisValue | undefined,\n locale: this.locale,\n });\n\n // While loading, the loader owns the box — an empty-state message under it\n // would just be the wrong answer to \"where is my data?\".\n const empty = this.series.length === 0 && !this.loading;\n\n return (\n <Host\n class={{\n 'md-line-chart': true,\n 'md-line-chart--empty': empty,\n 'md-line-chart--loading': this.loading,\n 'md-line-chart--mounted': this.mounted,\n 'md-line-chart--zoom-slider': this.zoomSliderOn,\n 'md-line-chart--zoom-drag': this.zoomInside,\n }}\n role=\"figure\"\n aria-label={summary}\n aria-busy={this.loading ? 'true' : null}\n style={this.heightProp ? { blockSize: this.heightProp } : undefined}\n onPointerDown={this.onPlotPointerDown}\n onPointerMove={this.onPointerMove}\n onPointerUp={this.onPointerUp}\n onPointerCancel={this.onPointerUp}\n onDblClick={this.onPlotDblClick}\n >\n <header class=\"md-line-chart__header\" part=\"header\">\n <slot name=\"header\"></slot>\n </header>\n\n {/* The plot is focusable so the data is reachable without a pointer:\n arrow keys walk the points, and each move is mirrored into the\n hover UI (for sighted keyboard users) and the live region (for\n screen readers). role=application stops a screen reader's browse\n mode from swallowing the arrow keys. */}\n <div\n class=\"md-line-chart__canvas\"\n part=\"canvas\"\n ref={el => this.bindChartHost(el as HTMLDivElement)}\n tabindex={empty ? undefined : '0'}\n role={empty ? undefined : 'application'}\n aria-label={empty ? undefined : this.labelPlot}\n onKeyDown={this.onPlotKeyDown}\n onBlur={this.onPlotBlur}\n ></div>\n\n {empty && (\n <div class=\"md-line-chart__empty\" part=\"empty\">\n <slot name=\"empty\">{this.labelEmpty}</slot>\n </div>\n )}\n\n {/* Loader — same opaque overlay as the empty state, so the phantom axis\n the engine draws for absent data can't show through. */}\n {this.loading && (\n <div class=\"md-line-chart__loading\" part=\"loading\" role=\"status\">\n {/* `loader` is the library-wide name for \"swap the loading affordance\";\n `loading` is kept as the older alias. Nesting them means either\n works — the outer slot falls back to the inner one, which falls\n back to the default below — and `loader` wins if both are given. */}\n <slot name=\"loader\">\n <slot name=\"loading\">\n <md-progress-indicator\n class=\"md-line-chart__spinner\"\n variant=\"circular\"\n indeterminate\n label={this.loadingLabel}\n ></md-progress-indicator>\n <span class=\"md-line-chart__loading-text\">{this.loadingLabel}</span>\n </slot>\n </slot>\n </div>\n )}\n\n {/* Drag-to-zoom band — purely visual, so it never eats pointer events. */}\n {this.dragBand && Math.abs(this.dragBand.x2 - this.dragBand.x1) > 1 && (\n <div\n class=\"md-line-chart__zoom-band\"\n part=\"zoom-band\"\n style={this.zoomBandStyle()}\n ></div>\n )}\n\n {this.zoomSliderOn && this.renderZoomSlider()}\n\n <footer class=\"md-line-chart__footer\" part=\"footer\">\n <slot name=\"footer\"></slot>\n </footer>\n\n {/* Screen-reader-only data table — the readable equivalent of\n the canvas plot (role=figure hides descendants from AT). */}\n <div\n class=\"md-line-chart__a11y-table\"\n ref={el => this.bindA11yTableHost(el as HTMLDivElement)}\n ></div>\n\n {/* Narrates the keyboard cursor. Polite so it waits for the reader to\n finish rather than interrupting every arrow press. */}\n <div class=\"md-line-chart__live\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {this.announcement}\n </div>\n </Host>\n );\n }\n}\n"],"mappings":"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","ignoreList":[]}
|