@vielzeug/prism 1.1.7 → 2.0.0
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/_dev.cjs +1 -1
- package/dist/_dev.cjs.map +1 -1
- package/dist/_dev.js +3 -8
- package/dist/_dev.js.map +1 -1
- package/dist/charts/area/area-chart.cjs +1 -1
- package/dist/charts/area/area-chart.cjs.map +1 -1
- package/dist/charts/area/area-chart.js +43 -43
- package/dist/charts/area/area-chart.js.map +1 -1
- package/dist/charts/area/area-renderer.cjs +1 -1
- package/dist/charts/area/area-renderer.cjs.map +1 -1
- package/dist/charts/area/area-renderer.js +40 -40
- package/dist/charts/area/area-renderer.js.map +1 -1
- package/dist/charts/bar/bar-chart.cjs +1 -1
- package/dist/charts/bar/bar-chart.cjs.map +1 -1
- package/dist/charts/bar/bar-chart.js +92 -92
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/bar/bar-hit-test.cjs +1 -1
- package/dist/charts/bar/bar-hit-test.cjs.map +1 -1
- package/dist/charts/bar/bar-hit-test.js +1 -1
- package/dist/charts/bar/bar-hit-test.js.map +1 -1
- package/dist/charts/line/line-chart.cjs +1 -1
- package/dist/charts/line/line-chart.cjs.map +1 -1
- package/dist/charts/line/line-chart.js +43 -43
- package/dist/charts/line/line-chart.js.map +1 -1
- package/dist/charts/line/line-renderer.cjs +1 -1
- package/dist/charts/line/line-renderer.cjs.map +1 -1
- package/dist/charts/line/line-renderer.js +52 -52
- package/dist/charts/line/line-renderer.js.map +1 -1
- package/dist/charts/pie/pie-chart.cjs.map +1 -1
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/sparkline/sparkline.cjs +1 -1
- package/dist/charts/sparkline/sparkline.cjs.map +1 -1
- package/dist/charts/sparkline/sparkline.d.ts.map +1 -1
- package/dist/charts/sparkline/sparkline.js +14 -12
- package/dist/charts/sparkline/sparkline.js.map +1 -1
- package/dist/core/cartesian-scales.cjs +1 -1
- package/dist/core/cartesian-scales.cjs.map +1 -1
- package/dist/core/cartesian-scales.js +23 -39
- package/dist/core/cartesian-scales.js.map +1 -1
- package/dist/core/chart-base.cjs +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.d.ts.map +1 -1
- package/dist/core/chart-base.js +38 -38
- package/dist/core/chart-base.js.map +1 -1
- package/dist/core/chart-scaffold.cjs +1 -1
- package/dist/core/chart-scaffold.cjs.map +1 -1
- package/dist/core/chart-scaffold.d.ts.map +1 -1
- package/dist/core/chart-scaffold.js +46 -48
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/errors.cjs.map +1 -1
- package/dist/errors.js.map +1 -1
- package/dist/interaction/tooltip.cjs +1 -1
- package/dist/interaction/tooltip.cjs.map +1 -1
- package/dist/interaction/tooltip.js +33 -35
- package/dist/interaction/tooltip.js.map +1 -1
- package/dist/prism.cjs +1 -1
- package/dist/prism.cjs.map +1 -1
- package/dist/prism.iife.js +1 -1
- package/dist/prism.iife.js.map +1 -1
- package/dist/prism.js +1 -1
- package/dist/prism.js.map +1 -1
- package/dist/scales/band.cjs +1 -1
- package/dist/scales/band.cjs.map +1 -1
- package/dist/scales/band.js +22 -22
- package/dist/scales/band.js.map +1 -1
- package/dist/svg/element.cjs +1 -1
- package/dist/svg/element.cjs.map +1 -1
- package/dist/svg/element.js +12 -12
- package/dist/svg/element.js.map +1 -1
- package/package.json +4 -4
package/dist/_dev.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
function e(e){}function t(e,...t){}exports.error=t,exports.warn=e;
|
|
2
2
|
//# sourceMappingURL=_dev.cjs.map
|
package/dist/_dev.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/**\n * Emits a `console.error` in development builds only.\n * @internal\n */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/prism] ${msg}`, ...args);\n}\n\n/** @internal — Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() / error() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"_dev.cjs","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/**\n * Emits a `console.error` in development builds only.\n * @internal\n */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/prism] ${msg}`, ...args);\n}\n\n/** @internal — Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() / error() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":"AASA,SAAgB,EAAK,EAAmB,CAExC,CAMA,SAAgB,EAAM,EAAa,GAAG,EAAuB,CAE7D"}
|
package/dist/_dev.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
//#region src/_dev.ts
|
|
2
|
-
|
|
3
|
-
function t(t) {
|
|
4
|
-
e && console.warn(`[@vielzeug/prism] ${t}`);
|
|
5
|
-
}
|
|
6
|
-
function n(t, ...n) {
|
|
7
|
-
e && console.error(`[@vielzeug/prism] ${t}`, ...n);
|
|
8
|
-
}
|
|
2
|
+
function e(e) {}
|
|
3
|
+
function t(e, ...t) {}
|
|
9
4
|
//#endregion
|
|
10
|
-
export {
|
|
5
|
+
export { t as error, e as warn };
|
|
11
6
|
|
|
12
7
|
//# sourceMappingURL=_dev.js.map
|
package/dist/_dev.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/**\n * Emits a `console.error` in development builds only.\n * @internal\n */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/prism] ${msg}`, ...args);\n}\n\n/** @internal — Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() / error() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":";
|
|
1
|
+
{"version":3,"file":"_dev.js","names":[],"sources":["../src/_dev.ts"],"sourcesContent":["/** @internal */\nconst isDev = !(globalThis as { __PRISM_PROD__?: boolean }).__PRISM_PROD__;\n\n/**\n * Emits a `console.warn` in development builds only.\n * @internal\n * @security Messages may include user-supplied data (e.g. category names, x-values).\n * Never pass PII, tokens, or secrets as chart data labels.\n */\nexport function warn(msg: string): void {\n if (isDev) console.warn(`[@vielzeug/prism] ${msg}`);\n}\n\n/**\n * Emits a `console.error` in development builds only.\n * @internal\n */\nexport function error(msg: string, ...args: unknown[]): void {\n if (isDev) console.error(`[@vielzeug/prism] ${msg}`, ...args);\n}\n\n/** @internal — Run fn only in dev builds. Use when dev-only logic goes beyond a single warn() / error() call. */\nexport function devOnly(fn: () => void): void {\n if (isDev) fn();\n}\n"],"mappings":";AASA,SAAgB,EAAK,GAAmB,CAExC;AAMA,SAAgB,EAAM,GAAa,GAAG,GAAuB,CAE7D"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../axes/axis.cjs"),n=require("../../axes/grid.cjs"),r=require("../../core/cartesian-scales.cjs"),i=require("../../core/layout.cjs"),a=require("../../core/chart-scaffold.cjs"),o=require("../../interaction/crosshair.cjs"),s=require("../../interaction/series-interaction.cjs"),c=require("../../theme/index.cjs"),l=require("./area-renderer.cjs");let u=require("@vielzeug/ripple");function d(d,f){let p=null;return a.createChartScaffold(d,f,d=>{let{groups:m,legend:h,tooltip:g}=d,_=d.dimensions.value,v=i.chartArea(_.width,_.height,_.margin),y=(0,u.isReactive)(f.series)?f.series.value:f.series,b=y.map(e=>(0,u.isReactive)(e.data)?e.data.value:e.data),x=b.flat().map(e=>e.key),S=b.flat().map(e=>e.value);if(x.length===0){a.clearCartesianDom(m,h,g,p);return}f.crosshair&&!p&&(p=o.createCrosshair(d.chartArea,f.crosshair));let C=r.buildXScale(x,v.width),w=r.buildYScale(S,v.height),T=w.map(0);for(f.yAxis?.grid&&n.renderGrid(m.grid,w,f.yAxis.grid,v.width,`horizontal`,t.resolveTickCount(f.yAxis,v.height,`left`)),f.xAxis?.grid&&n.renderGrid(m.grid,C,f.xAxis.grid,v.height,`vertical`,t.resolveTickCount(f.xAxis,v.width,`bottom`)),f.xAxis&&(m.xAxis.setAttribute(`transform`,`translate(0,${v.height})`),t.renderAxis(m.xAxis,C,f.xAxis,v.width,`bottom`)),f.yAxis&&t.renderAxis(m.yAxis,w,f.yAxis,v.height,`left`);m.series.children.length>y.length;)m.series.removeChild(m.series.lastChild);let E=[];for(let t=0;t<y.length;t++){let n=y[t],r=m.series.children[t];r||(r=e.createSvgElement(`g`,{class:`prism-area-series`}),m.series.appendChild(r));let i=l.computeAreaPoints(b[t],C,w);E.push(i),l.renderArea(r,i,T,{color:c.seriesColor(t,n.color),curve:n.curve??`linear`,disposalSignal:d.disposalSignal,fillOpacity:n.fillOpacity??.3,showLine:n.showLine!==!1,transition:f.transition})}return h?.update(y.map((e,t)=>({color:c.seriesColor(t,e.color),name:e.name}))),g?.hide(),s.createSeriesInteraction({crosshair:p,dims:()=>d.dimensions.value,getData:()=>b,getPoints:()=>E,getSeriesList:()=>(0,u.isReactive)(f.series)?f.series.value:f.series,onClick:f.onClick,onHover:f.onHover,svg:d.svg,tooltip:g})})}exports.createAreaChart=d;
|
|
2
2
|
//# sourceMappingURL=area-chart.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area-chart.cjs","names":[],"sources":["../../../src/charts/area/area-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { Point } from '../../svg/path';\nimport type { AreaChartConfig, ChartHandle } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { computeAreaPoints, renderArea } from './area-renderer';\n\nexport function createAreaChart(container: HTMLElement, config: AreaChartConfig): ChartHandle {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const allX = allData.flat().map((d) => d.key as Date | number);\n const allY = allData.flat().map((d) => d.value);\n\n if (allX.length === 0) {\n warn('createAreaChart: no data');\n clearCartesianDom(groups, legend, tooltip, crosshair);\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX as (Date | number)[], area.width);\n const yScale = buildYScale(allY, area.height);\n const baselineY = yScale.map(0);\n\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, yScale, config.yAxis, area.height, 'left');\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-area-series' });\n groups.series.appendChild(group);\n }\n\n const points = computeAreaPoints(allData[i], xScale, yScale);\n\n allPoints.push(points);\n\n renderArea(group, points, baselineY, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n fillOpacity: series.fillOpacity ?? 0.3,\n showLine: series.showLine !== false,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n return createSeriesInteraction({\n crosshair,\n dims: () => ctx.dimensions.value,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => (isReactive(config.series) ? config.series.value : config.series),\n onClick: config.onClick,\n onHover: config.onHover,\n svg: ctx.svg,\n tooltip,\n });\n });\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"area-chart.cjs","names":[],"sources":["../../../src/charts/area/area-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { Point } from '../../svg/path';\nimport type { AreaChartConfig, ChartHandle } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { computeAreaPoints, renderArea } from './area-renderer';\n\nexport function createAreaChart(container: HTMLElement, config: AreaChartConfig): ChartHandle {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const allX = allData.flat().map((d) => d.key as Date | number);\n const allY = allData.flat().map((d) => d.value);\n\n if (allX.length === 0) {\n warn('createAreaChart: no data');\n clearCartesianDom(groups, legend, tooltip, crosshair);\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX as (Date | number)[], area.width);\n const yScale = buildYScale(allY, area.height);\n const baselineY = yScale.map(0);\n\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, yScale, config.yAxis, area.height, 'left');\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-area-series' });\n groups.series.appendChild(group);\n }\n\n const points = computeAreaPoints(allData[i], xScale, yScale);\n\n allPoints.push(points);\n\n renderArea(group, points, baselineY, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n fillOpacity: series.fillOpacity ?? 0.3,\n showLine: series.showLine !== false,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n return createSeriesInteraction({\n crosshair,\n dims: () => ctx.dimensions.value,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => (isReactive(config.series) ? config.series.value : config.series),\n onClick: config.onClick,\n onHover: config.onHover,\n svg: ctx.svg,\n tooltip,\n });\n });\n}\n"],"mappings":"ycAiBA,SAAgB,EAAgB,EAAwB,EAAsC,CAC5F,IAAI,EAAuD,KAE3D,OAAO,EAAA,oBAAoB,EAAW,EAAS,GAAQ,CACrD,GAAM,CAAE,SAAQ,SAAQ,WAAY,EAC9B,EAAO,EAAI,WAAW,MACtB,EAAO,EAAA,UAAU,EAAK,MAAO,EAAK,OAAQ,EAAK,MAAM,EACrD,GAAA,EAAa,EAAA,WAAA,CAAW,EAAO,MAAM,EAAI,EAAO,OAAO,MAAQ,EAAO,OACtE,EAAU,EAAW,IAAK,IAAA,EAAO,EAAA,WAAA,CAAW,EAAE,IAAI,EAAI,EAAE,KAAK,MAAQ,EAAE,IAAK,EAC5E,EAAO,EAAQ,KAAK,CAAC,CAAC,IAAK,GAAM,EAAE,GAAoB,EACvD,EAAO,EAAQ,KAAK,CAAC,CAAC,IAAK,GAAM,EAAE,KAAK,EAE9C,GAAI,EAAK,SAAW,EAAG,CAErB,EAAA,kBAAkB,EAAQ,EAAQ,EAAS,CAAS,EAEpD,MACF,CAEI,EAAO,WAAa,CAAC,IACvB,EAAY,EAAA,gBAAgB,EAAI,UAAW,EAAO,SAAS,GAG7D,IAAM,EAAS,EAAA,YAAY,EAA2B,EAAK,KAAK,EAC1D,EAAS,EAAA,YAAY,EAAM,EAAK,MAAM,EACtC,EAAY,EAAO,IAAI,CAAC,EA+B9B,IA7BI,EAAO,OAAO,MAChB,EAAA,WACE,EAAO,KACP,EACA,EAAO,MAAM,KACb,EAAK,MACL,aACA,EAAA,iBAAiB,EAAO,MAAO,EAAK,OAAQ,MAAM,CACpD,EAGE,EAAO,OAAO,MAChB,EAAA,WACE,EAAO,KACP,EACA,EAAO,MAAM,KACb,EAAK,OACL,WACA,EAAA,iBAAiB,EAAO,MAAO,EAAK,MAAO,QAAQ,CACrD,EAGE,EAAO,QACT,EAAO,MAAM,aAAa,YAAa,eAAe,EAAK,OAAO,EAAE,EACpE,EAAA,WAAW,EAAO,MAAO,EAAQ,EAAO,MAAO,EAAK,MAAO,QAAQ,GAGjE,EAAO,OAAO,EAAA,WAAW,EAAO,MAAO,EAAQ,EAAO,MAAO,EAAK,OAAQ,MAAM,EAE7E,EAAO,OAAO,SAAS,OAAS,EAAW,QAChD,EAAO,OAAO,YAAY,EAAO,OAAO,SAAU,EAGpD,IAAM,EAAuB,CAAC,EAE9B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CAC1C,IAAM,EAAS,EAAW,GACtB,EAAQ,EAAO,OAAO,SAAS,GAE9B,IACH,EAAQ,EAAA,iBAAiB,IAAK,CAAE,MAAO,mBAAoB,CAAC,EAC5D,EAAO,OAAO,YAAY,CAAK,GAGjC,IAAM,EAAS,EAAA,kBAAkB,EAAQ,GAAI,EAAQ,CAAM,EAE3D,EAAU,KAAK,CAAM,EAErB,EAAA,WAAW,EAAO,EAAQ,EAAW,CACnC,MAAO,EAAA,YAAY,EAAG,EAAO,KAAK,EAClC,MAAO,EAAO,OAAS,SACvB,eAAgB,EAAI,eACpB,YAAa,EAAO,aAAe,GACnC,SAAU,EAAO,WAAa,GAC9B,WAAY,EAAO,UACrB,CAAC,CACH,CAKA,OAHA,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAA,YAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,GAAS,KAAK,EAEP,EAAA,wBAAwB,CAC7B,YACA,SAAY,EAAI,WAAW,MAC3B,YAAe,EACf,cAAiB,EACjB,mBAAA,EAAsB,EAAA,WAAA,CAAW,EAAO,MAAM,EAAI,EAAO,OAAO,MAAQ,EAAO,OAC/E,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,IAAK,EAAI,IACT,SACF,CAAC,CACH,CAAC,CACH"}
|
|
@@ -1,58 +1,58 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createSvgElement as
|
|
3
|
-
import { renderAxis as
|
|
4
|
-
import { renderGrid as
|
|
5
|
-
import { buildXScale as
|
|
6
|
-
import { chartArea as
|
|
7
|
-
import { clearCartesianDom as
|
|
8
|
-
import { createCrosshair as
|
|
9
|
-
import { createSeriesInteraction as
|
|
10
|
-
import { seriesColor as
|
|
11
|
-
import { computeAreaPoints as
|
|
12
|
-
import { isReactive as
|
|
1
|
+
import "../../_dev.js";
|
|
2
|
+
import { createSvgElement as e } from "../../svg/element.js";
|
|
3
|
+
import { renderAxis as t, resolveTickCount as n } from "../../axes/axis.js";
|
|
4
|
+
import { renderGrid as r } from "../../axes/grid.js";
|
|
5
|
+
import { buildXScale as i, buildYScale as a } from "../../core/cartesian-scales.js";
|
|
6
|
+
import { chartArea as o } from "../../core/layout.js";
|
|
7
|
+
import { clearCartesianDom as s, createChartScaffold as c } from "../../core/chart-scaffold.js";
|
|
8
|
+
import { createCrosshair as l } from "../../interaction/crosshair.js";
|
|
9
|
+
import { createSeriesInteraction as u } from "../../interaction/series-interaction.js";
|
|
10
|
+
import { seriesColor as d } from "../../theme/index.js";
|
|
11
|
+
import { computeAreaPoints as f, renderArea as p } from "./area-renderer.js";
|
|
12
|
+
import { isReactive as m } from "@vielzeug/ripple";
|
|
13
13
|
//#region src/charts/area/area-chart.ts
|
|
14
|
-
function
|
|
15
|
-
let
|
|
16
|
-
return
|
|
17
|
-
let { groups:
|
|
18
|
-
if (
|
|
19
|
-
|
|
14
|
+
function h(h, g) {
|
|
15
|
+
let _ = null;
|
|
16
|
+
return c(h, g, (c) => {
|
|
17
|
+
let { groups: h, legend: v, tooltip: y } = c, b = c.dimensions.value, x = o(b.width, b.height, b.margin), S = m(g.series) ? g.series.value : g.series, C = S.map((e) => m(e.data) ? e.data.value : e.data), w = C.flat().map((e) => e.key), T = C.flat().map((e) => e.value);
|
|
18
|
+
if (w.length === 0) {
|
|
19
|
+
s(h, v, y, _);
|
|
20
20
|
return;
|
|
21
21
|
}
|
|
22
|
-
|
|
23
|
-
let
|
|
24
|
-
for (
|
|
25
|
-
let
|
|
26
|
-
for (let
|
|
27
|
-
let n =
|
|
28
|
-
r || (r =
|
|
29
|
-
let i =
|
|
30
|
-
|
|
31
|
-
color:
|
|
22
|
+
g.crosshair && !_ && (_ = l(c.chartArea, g.crosshair));
|
|
23
|
+
let E = i(w, x.width), D = a(T, x.height), O = D.map(0);
|
|
24
|
+
for (g.yAxis?.grid && r(h.grid, D, g.yAxis.grid, x.width, "horizontal", n(g.yAxis, x.height, "left")), g.xAxis?.grid && r(h.grid, E, g.xAxis.grid, x.height, "vertical", n(g.xAxis, x.width, "bottom")), g.xAxis && (h.xAxis.setAttribute("transform", `translate(0,${x.height})`), t(h.xAxis, E, g.xAxis, x.width, "bottom")), g.yAxis && t(h.yAxis, D, g.yAxis, x.height, "left"); h.series.children.length > S.length;) h.series.removeChild(h.series.lastChild);
|
|
25
|
+
let k = [];
|
|
26
|
+
for (let t = 0; t < S.length; t++) {
|
|
27
|
+
let n = S[t], r = h.series.children[t];
|
|
28
|
+
r || (r = e("g", { class: "prism-area-series" }), h.series.appendChild(r));
|
|
29
|
+
let i = f(C[t], E, D);
|
|
30
|
+
k.push(i), p(r, i, O, {
|
|
31
|
+
color: d(t, n.color),
|
|
32
32
|
curve: n.curve ?? "linear",
|
|
33
|
-
disposalSignal:
|
|
33
|
+
disposalSignal: c.disposalSignal,
|
|
34
34
|
fillOpacity: n.fillOpacity ?? .3,
|
|
35
35
|
showLine: n.showLine !== !1,
|
|
36
|
-
transition:
|
|
36
|
+
transition: g.transition
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
|
-
return
|
|
40
|
-
color:
|
|
39
|
+
return v?.update(S.map((e, t) => ({
|
|
40
|
+
color: d(t, e.color),
|
|
41
41
|
name: e.name
|
|
42
|
-
}))),
|
|
43
|
-
crosshair:
|
|
44
|
-
dims: () =>
|
|
45
|
-
getData: () =>
|
|
46
|
-
getPoints: () =>
|
|
47
|
-
getSeriesList: () =>
|
|
48
|
-
onClick:
|
|
49
|
-
onHover:
|
|
50
|
-
svg:
|
|
51
|
-
tooltip:
|
|
42
|
+
}))), y?.hide(), u({
|
|
43
|
+
crosshair: _,
|
|
44
|
+
dims: () => c.dimensions.value,
|
|
45
|
+
getData: () => C,
|
|
46
|
+
getPoints: () => k,
|
|
47
|
+
getSeriesList: () => m(g.series) ? g.series.value : g.series,
|
|
48
|
+
onClick: g.onClick,
|
|
49
|
+
onHover: g.onHover,
|
|
50
|
+
svg: c.svg,
|
|
51
|
+
tooltip: y
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
54
|
}
|
|
55
55
|
//#endregion
|
|
56
|
-
export {
|
|
56
|
+
export { h as createAreaChart };
|
|
57
57
|
|
|
58
58
|
//# sourceMappingURL=area-chart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area-chart.js","names":[],"sources":["../../../src/charts/area/area-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { Point } from '../../svg/path';\nimport type { AreaChartConfig, ChartHandle } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { computeAreaPoints, renderArea } from './area-renderer';\n\nexport function createAreaChart(container: HTMLElement, config: AreaChartConfig): ChartHandle {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const allX = allData.flat().map((d) => d.key as Date | number);\n const allY = allData.flat().map((d) => d.value);\n\n if (allX.length === 0) {\n warn('createAreaChart: no data');\n clearCartesianDom(groups, legend, tooltip, crosshair);\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX as (Date | number)[], area.width);\n const yScale = buildYScale(allY, area.height);\n const baselineY = yScale.map(0);\n\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, yScale, config.yAxis, area.height, 'left');\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-area-series' });\n groups.series.appendChild(group);\n }\n\n const points = computeAreaPoints(allData[i], xScale, yScale);\n\n allPoints.push(points);\n\n renderArea(group, points, baselineY, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n fillOpacity: series.fillOpacity ?? 0.3,\n showLine: series.showLine !== false,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n return createSeriesInteraction({\n crosshair,\n dims: () => ctx.dimensions.value,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => (isReactive(config.series) ? config.series.value : config.series),\n onClick: config.onClick,\n onHover: config.onHover,\n svg: ctx.svg,\n tooltip,\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,EAAgB,GAAwB,GAAsC;CAC5F,IAAI,IAAuD;CAE3D,OAAO,EAAoB,GAAW,IAAS,MAAQ;EACrD,IAAM,EAAE,WAAQ,WAAQ,eAAY,GAC9B,IAAO,EAAI,WAAW,OACtB,IAAO,EAAU,EAAK,OAAO,EAAK,QAAQ,EAAK,MAAM,GACrD,IAAa,EAAW,EAAO,MAAM,IAAI,EAAO,OAAO,QAAQ,EAAO,QACtE,IAAU,EAAW,KAAK,MAAO,EAAW,EAAE,IAAI,IAAI,EAAE,KAAK,QAAQ,EAAE,IAAK,GAC5E,IAAO,EAAQ,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,GAAoB,GACvD,IAAO,EAAQ,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK;EAE9C,IAAI,EAAK,WAAW,GAAG;GAErB,
|
|
1
|
+
{"version":3,"file":"area-chart.js","names":[],"sources":["../../../src/charts/area/area-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { Point } from '../../svg/path';\nimport type { AreaChartConfig, ChartHandle } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { computeAreaPoints, renderArea } from './area-renderer';\n\nexport function createAreaChart(container: HTMLElement, config: AreaChartConfig): ChartHandle {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const allX = allData.flat().map((d) => d.key as Date | number);\n const allY = allData.flat().map((d) => d.value);\n\n if (allX.length === 0) {\n warn('createAreaChart: no data');\n clearCartesianDom(groups, legend, tooltip, crosshair);\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX as (Date | number)[], area.width);\n const yScale = buildYScale(allY, area.height);\n const baselineY = yScale.map(0);\n\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n yScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n xScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, xScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, yScale, config.yAxis, area.height, 'left');\n\n while (groups.series.children.length > seriesList.length) {\n groups.series.removeChild(groups.series.lastChild!);\n }\n\n const allPoints: Point[][] = [];\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-area-series' });\n groups.series.appendChild(group);\n }\n\n const points = computeAreaPoints(allData[i], xScale, yScale);\n\n allPoints.push(points);\n\n renderArea(group, points, baselineY, {\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n fillOpacity: series.fillOpacity ?? 0.3,\n showLine: series.showLine !== false,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n return createSeriesInteraction({\n crosshair,\n dims: () => ctx.dimensions.value,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => (isReactive(config.series) ? config.series.value : config.series),\n onClick: config.onClick,\n onHover: config.onHover,\n svg: ctx.svg,\n tooltip,\n });\n });\n}\n"],"mappings":";;;;;;;;;;;;;AAiBA,SAAgB,EAAgB,GAAwB,GAAsC;CAC5F,IAAI,IAAuD;CAE3D,OAAO,EAAoB,GAAW,IAAS,MAAQ;EACrD,IAAM,EAAE,WAAQ,WAAQ,eAAY,GAC9B,IAAO,EAAI,WAAW,OACtB,IAAO,EAAU,EAAK,OAAO,EAAK,QAAQ,EAAK,MAAM,GACrD,IAAa,EAAW,EAAO,MAAM,IAAI,EAAO,OAAO,QAAQ,EAAO,QACtE,IAAU,EAAW,KAAK,MAAO,EAAW,EAAE,IAAI,IAAI,EAAE,KAAK,QAAQ,EAAE,IAAK,GAC5E,IAAO,EAAQ,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,GAAoB,GACvD,IAAO,EAAQ,KAAK,CAAC,CAAC,KAAK,MAAM,EAAE,KAAK;EAE9C,IAAI,EAAK,WAAW,GAAG;GAErB,EAAkB,GAAQ,GAAQ,GAAS,CAAS;GAEpD;EACF;EAEA,AAAI,EAAO,aAAa,CAAC,MACvB,IAAY,EAAgB,EAAI,WAAW,EAAO,SAAS;EAG7D,IAAM,IAAS,EAAY,GAA2B,EAAK,KAAK,GAC1D,IAAS,EAAY,GAAM,EAAK,MAAM,GACtC,IAAY,EAAO,IAAI,CAAC;EA+B9B,KA7BI,EAAO,OAAO,QAChB,EACE,EAAO,MACP,GACA,EAAO,MAAM,MACb,EAAK,OACL,cACA,EAAiB,EAAO,OAAO,EAAK,QAAQ,MAAM,CACpD,GAGE,EAAO,OAAO,QAChB,EACE,EAAO,MACP,GACA,EAAO,MAAM,MACb,EAAK,QACL,YACA,EAAiB,EAAO,OAAO,EAAK,OAAO,QAAQ,CACrD,GAGE,EAAO,UACT,EAAO,MAAM,aAAa,aAAa,eAAe,EAAK,OAAO,EAAE,GACpE,EAAW,EAAO,OAAO,GAAQ,EAAO,OAAO,EAAK,OAAO,QAAQ,IAGjE,EAAO,SAAO,EAAW,EAAO,OAAO,GAAQ,EAAO,OAAO,EAAK,QAAQ,MAAM,GAE7E,EAAO,OAAO,SAAS,SAAS,EAAW,SAChD,EAAO,OAAO,YAAY,EAAO,OAAO,SAAU;EAGpD,IAAM,IAAuB,CAAC;EAE9B,KAAK,IAAI,IAAI,GAAG,IAAI,EAAW,QAAQ,KAAK;GAC1C,IAAM,IAAS,EAAW,IACtB,IAAQ,EAAO,OAAO,SAAS;GAEnC,AAAK,MACH,IAAQ,EAAiB,KAAK,EAAE,OAAO,oBAAoB,CAAC,GAC5D,EAAO,OAAO,YAAY,CAAK;GAGjC,IAAM,IAAS,EAAkB,EAAQ,IAAI,GAAQ,CAAM;GAI3D,AAFA,EAAU,KAAK,CAAM,GAErB,EAAW,GAAO,GAAQ,GAAW;IACnC,OAAO,EAAY,GAAG,EAAO,KAAK;IAClC,OAAO,EAAO,SAAS;IACvB,gBAAgB,EAAI;IACpB,aAAa,EAAO,eAAe;IACnC,UAAU,EAAO,aAAa;IAC9B,YAAY,EAAO;GACrB,CAAC;EACH;EAKA,OAHA,GAAQ,OAAO,EAAW,KAAK,GAAG,OAAO;GAAE,OAAO,EAAY,GAAG,EAAE,KAAK;GAAG,MAAM,EAAE;EAAK,EAAE,CAAC,GAC3F,GAAS,KAAK,GAEP,EAAwB;GAC7B;GACA,YAAY,EAAI,WAAW;GAC3B,eAAe;GACf,iBAAiB;GACjB,qBAAsB,EAAW,EAAO,MAAM,IAAI,EAAO,OAAO,QAAQ,EAAO;GAC/E,SAAS,EAAO;GAChB,SAAS,EAAO;GAChB,KAAK,EAAI;GACT;EACF,CAAC;CACH,CAAC;AACH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../animation/easing.cjs"),n=require("../../animation/tween.cjs"),r=require("../../svg/path.cjs");var i=new WeakMap,a=new WeakMap;function o(e,t){return t===`monotone`?r.monotonePath(e):t===`step`?r.stepPath(e):r.linePath(e)}function s(s,c,l,u){let d=u.transition?.duration??(u.transition?300:0),f=t.resolveEasing(u.transition?.easing),p=s.querySelector(`.prism-area-fill`);p||(p=e.createSvgElement(`path`,{class:`prism-area-fill`}),s.appendChild(p)),e.setAttributes(p,{fill:u.color,"fill-opacity":u.fillOpacity,stroke:`none`});let m=null;if(u.showLine?(m=s.querySelector(`.prism-area-line`),m||(m=e.createSvgElement(`path`,{class:`prism-area-line`,fill:`none`}),s.appendChild(m)),e.setAttributes(m,{stroke:u.color,"stroke-width":2})):s.querySelector(`.prism-area-line`)?.remove(),d===0){let t=c.map(e=>({x:e.x,y:l}));e.setAttributes(p,{d:r.areaPath(c,t,u.curve)}),m&&e.setAttributes(m,{d:o(c,u.curve)});return}if(i.get(s)?.(),!p.hasAttribute(`d`)){let t=c.map(e=>({x:e.x,y:l}));e.setAttributes(p,{d:r.areaPath(c,t,u.curve)}),m&&e.setAttributes(m,{d:o(c,u.curve)}),a.set(s,c);return}let h=a.get(s)??c,g=c.map((e,t)=>h[t]??h[h.length-1]??c[t]),_=null;function v(t){if(u.disposalSignal?.aborted){i.delete(s);return}_===null&&(_=t);let h=Math.min(1,(t-_)/d),y=f(h),b=c.map((e,t)=>({x:n.tweenNumber(g[t].x,e.x,y),y:n.tweenNumber(g[t].y,e.y,y)})),x=b.map(e=>({x:e.x,y:l}));if(e.setAttributes(p,{d:r.areaPath(b,x,u.curve)}),m&&e.setAttributes(m,{d:o(b,u.curve)}),h<1){let e=requestAnimationFrame(v);i.set(s,()=>cancelAnimationFrame(e))}else i.delete(s),a.set(s,c)}a.set(s,g);let y=requestAnimationFrame(v);i.set(s,()=>cancelAnimationFrame(y))}function c(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}exports.computeAreaPoints=c,exports.renderArea=s;
|
|
2
2
|
//# sourceMappingURL=area-renderer.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area-renderer.cjs","names":[],"sources":["../../../src/charts/area/area-renderer.ts"],"sourcesContent":["import type { Point } from '../../svg/path';\nimport type { Datum, Scale, TransitionConfig } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { tweenNumber } from '../../animation/tween';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\n\nexport interface AreaRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed — stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n fillOpacity: number;\n showLine: boolean;\n transition?: TransitionConfig;\n}\n\nconst activeAreaAnimations = new WeakMap<SVGGElement, () => void>();\nconst previousPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildLinePath(pts: Point[], curve: AreaRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderArea(parent: SVGGElement, points: Point[], baselineY: number, options: AreaRenderOptions): void {\n const dur = options.transition?.duration ?? (options.transition ? 300 : 0);\n const easing = resolveEasing(options.transition?.easing);\n\n let fill = parent.querySelector<SVGPathElement>('.prism-area-fill');\n\n if (!fill) {\n fill = createSvgElement('path', { class: 'prism-area-fill' });\n parent.appendChild(fill);\n }\n\n setAttributes(fill, { fill: options.color, 'fill-opacity': options.fillOpacity, stroke: 'none' });\n\n let line: SVGPathElement | null = null;\n\n if (options.showLine) {\n line = parent.querySelector<SVGPathElement>('.prism-area-line');\n\n if (!line) {\n line = createSvgElement('path', { class: 'prism-area-line', fill: 'none' });\n parent.appendChild(line);\n }\n\n setAttributes(line, { stroke: options.color, 'stroke-width': 2 });\n } else {\n parent.querySelector('.prism-area-line')?.remove();\n }\n\n if (dur === 0) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n return;\n }\n\n activeAreaAnimations.get(parent)?.();\n\n const hasExisting = fill.hasAttribute('d');\n\n if (!hasExisting) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n previousPoints.set(parent, points);\n\n return;\n }\n\n const rawFrom = previousPoints.get(parent) ?? points;\n const fromPoints: Point[] = points.map((_, i) => rawFrom[i] ?? rawFrom[rawFrom.length - 1] ?? points[i]);\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAreaAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => ({\n x: tweenNumber(fromPoints[i].x, to.x, e),\n y: tweenNumber(fromPoints[i].y, to.y, e),\n }));\n const interpolatedBottom = interpolated.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill!, { d: areaPath(interpolated, interpolatedBottom, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(interpolated, options.curve) });\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAreaAnimations.delete(parent);\n previousPoints.set(parent, points);\n }\n }\n\n previousPoints.set(parent, fromPoints);\n\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n}\n\nexport function computeAreaPoints(data: Datum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeAreaPoints: datum.key is null or undefined — data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeAreaPoints: string keys are not supported for line/area charts — use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"area-renderer.cjs","names":[],"sources":["../../../src/charts/area/area-renderer.ts"],"sourcesContent":["import type { Point } from '../../svg/path';\nimport type { Datum, Scale, TransitionConfig } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { tweenNumber } from '../../animation/tween';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\n\nexport interface AreaRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed — stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n fillOpacity: number;\n showLine: boolean;\n transition?: TransitionConfig;\n}\n\nconst activeAreaAnimations = new WeakMap<SVGGElement, () => void>();\nconst previousPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildLinePath(pts: Point[], curve: AreaRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderArea(parent: SVGGElement, points: Point[], baselineY: number, options: AreaRenderOptions): void {\n const dur = options.transition?.duration ?? (options.transition ? 300 : 0);\n const easing = resolveEasing(options.transition?.easing);\n\n let fill = parent.querySelector<SVGPathElement>('.prism-area-fill');\n\n if (!fill) {\n fill = createSvgElement('path', { class: 'prism-area-fill' });\n parent.appendChild(fill);\n }\n\n setAttributes(fill, { fill: options.color, 'fill-opacity': options.fillOpacity, stroke: 'none' });\n\n let line: SVGPathElement | null = null;\n\n if (options.showLine) {\n line = parent.querySelector<SVGPathElement>('.prism-area-line');\n\n if (!line) {\n line = createSvgElement('path', { class: 'prism-area-line', fill: 'none' });\n parent.appendChild(line);\n }\n\n setAttributes(line, { stroke: options.color, 'stroke-width': 2 });\n } else {\n parent.querySelector('.prism-area-line')?.remove();\n }\n\n if (dur === 0) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n return;\n }\n\n activeAreaAnimations.get(parent)?.();\n\n const hasExisting = fill.hasAttribute('d');\n\n if (!hasExisting) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n previousPoints.set(parent, points);\n\n return;\n }\n\n const rawFrom = previousPoints.get(parent) ?? points;\n const fromPoints: Point[] = points.map((_, i) => rawFrom[i] ?? rawFrom[rawFrom.length - 1] ?? points[i]);\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAreaAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => ({\n x: tweenNumber(fromPoints[i].x, to.x, e),\n y: tweenNumber(fromPoints[i].y, to.y, e),\n }));\n const interpolatedBottom = interpolated.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill!, { d: areaPath(interpolated, interpolatedBottom, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(interpolated, options.curve) });\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAreaAnimations.delete(parent);\n previousPoints.set(parent, points);\n }\n }\n\n previousPoints.set(parent, fromPoints);\n\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n}\n\nexport function computeAreaPoints(data: Datum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeAreaPoints: datum.key is null or undefined — data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeAreaPoints: string keys are not supported for line/area charts — use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
|
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { createSvgElement as
|
|
3
|
-
import { resolveEasing as
|
|
4
|
-
import { tweenNumber as
|
|
5
|
-
import { areaPath as
|
|
1
|
+
import "../../_dev.js";
|
|
2
|
+
import { createSvgElement as e, setAttributes as t } from "../../svg/element.js";
|
|
3
|
+
import { resolveEasing as n } from "../../animation/easing.js";
|
|
4
|
+
import { tweenNumber as r } from "../../animation/tween.js";
|
|
5
|
+
import { areaPath as i, linePath as a, monotonePath as o, stepPath as s } from "../../svg/path.js";
|
|
6
6
|
//#region src/charts/area/area-renderer.ts
|
|
7
|
-
var
|
|
8
|
-
function
|
|
9
|
-
return t === "monotone" ?
|
|
7
|
+
var c = /* @__PURE__ */ new WeakMap(), l = /* @__PURE__ */ new WeakMap();
|
|
8
|
+
function u(e, t) {
|
|
9
|
+
return t === "monotone" ? o(e) : t === "step" ? s(e) : a(e);
|
|
10
10
|
}
|
|
11
|
-
function
|
|
12
|
-
let f =
|
|
13
|
-
m || (m =
|
|
14
|
-
fill:
|
|
15
|
-
"fill-opacity":
|
|
11
|
+
function d(a, o, s, d) {
|
|
12
|
+
let f = d.transition?.duration ?? (d.transition ? 300 : 0), p = n(d.transition?.easing), m = a.querySelector(".prism-area-fill");
|
|
13
|
+
m || (m = e("path", { class: "prism-area-fill" }), a.appendChild(m)), t(m, {
|
|
14
|
+
fill: d.color,
|
|
15
|
+
"fill-opacity": d.fillOpacity,
|
|
16
16
|
stroke: "none"
|
|
17
17
|
});
|
|
18
18
|
let h = null;
|
|
19
|
-
if (
|
|
19
|
+
if (d.showLine ? (h = a.querySelector(".prism-area-line"), h || (h = e("path", {
|
|
20
20
|
class: "prism-area-line",
|
|
21
21
|
fill: "none"
|
|
22
|
-
}),
|
|
23
|
-
stroke:
|
|
22
|
+
}), a.appendChild(h)), t(h, {
|
|
23
|
+
stroke: d.color,
|
|
24
24
|
"stroke-width": 2
|
|
25
|
-
})) :
|
|
25
|
+
})) : a.querySelector(".prism-area-line")?.remove(), f === 0) {
|
|
26
26
|
let e = o.map((e) => ({
|
|
27
27
|
x: e.x,
|
|
28
28
|
y: s
|
|
29
29
|
}));
|
|
30
|
-
|
|
30
|
+
t(m, { d: i(o, e, d.curve) }), h && t(h, { d: u(o, d.curve) });
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
|
-
if (
|
|
34
|
-
let
|
|
33
|
+
if (c.get(a)?.(), !m.hasAttribute("d")) {
|
|
34
|
+
let e = o.map((e) => ({
|
|
35
35
|
x: e.x,
|
|
36
36
|
y: s
|
|
37
37
|
}));
|
|
38
|
-
|
|
38
|
+
t(m, { d: i(o, e, d.curve) }), h && t(h, { d: u(o, d.curve) }), l.set(a, o);
|
|
39
39
|
return;
|
|
40
40
|
}
|
|
41
|
-
let g =
|
|
42
|
-
function y(
|
|
43
|
-
if (
|
|
44
|
-
|
|
41
|
+
let g = l.get(a) ?? o, _ = o.map((e, t) => g[t] ?? g[g.length - 1] ?? o[t]), v = null;
|
|
42
|
+
function y(e) {
|
|
43
|
+
if (d.disposalSignal?.aborted) {
|
|
44
|
+
c.delete(a);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
v === null && (v =
|
|
48
|
-
let
|
|
49
|
-
x:
|
|
50
|
-
y:
|
|
47
|
+
v === null && (v = e);
|
|
48
|
+
let n = Math.min(1, (e - v) / f), g = p(n), b = o.map((e, t) => ({
|
|
49
|
+
x: r(_[t].x, e.x, g),
|
|
50
|
+
y: r(_[t].y, e.y, g)
|
|
51
51
|
})), x = b.map((e) => ({
|
|
52
52
|
x: e.x,
|
|
53
53
|
y: s
|
|
54
54
|
}));
|
|
55
|
-
if (
|
|
56
|
-
let
|
|
57
|
-
|
|
58
|
-
} else
|
|
55
|
+
if (t(m, { d: i(b, x, d.curve) }), h && t(h, { d: u(b, d.curve) }), n < 1) {
|
|
56
|
+
let e = requestAnimationFrame(y);
|
|
57
|
+
c.set(a, () => cancelAnimationFrame(e));
|
|
58
|
+
} else c.delete(a), l.set(a, o);
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
l.set(a, _);
|
|
61
61
|
let b = requestAnimationFrame(y);
|
|
62
|
-
|
|
62
|
+
c.set(a, () => cancelAnimationFrame(b));
|
|
63
63
|
}
|
|
64
|
-
function
|
|
65
|
-
return
|
|
66
|
-
x:
|
|
67
|
-
y:
|
|
64
|
+
function f(e, t, n) {
|
|
65
|
+
return e.some((e) => e.key == null) || e.some((e) => typeof e.key == "string"), e.map((e) => ({
|
|
66
|
+
x: t.map(e.key),
|
|
67
|
+
y: n.map(e.value)
|
|
68
68
|
}));
|
|
69
69
|
}
|
|
70
70
|
//#endregion
|
|
71
|
-
export {
|
|
71
|
+
export { f as computeAreaPoints, d as renderArea };
|
|
72
72
|
|
|
73
73
|
//# sourceMappingURL=area-renderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"area-renderer.js","names":[],"sources":["../../../src/charts/area/area-renderer.ts"],"sourcesContent":["import type { Point } from '../../svg/path';\nimport type { Datum, Scale, TransitionConfig } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { tweenNumber } from '../../animation/tween';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\n\nexport interface AreaRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed — stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n fillOpacity: number;\n showLine: boolean;\n transition?: TransitionConfig;\n}\n\nconst activeAreaAnimations = new WeakMap<SVGGElement, () => void>();\nconst previousPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildLinePath(pts: Point[], curve: AreaRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderArea(parent: SVGGElement, points: Point[], baselineY: number, options: AreaRenderOptions): void {\n const dur = options.transition?.duration ?? (options.transition ? 300 : 0);\n const easing = resolveEasing(options.transition?.easing);\n\n let fill = parent.querySelector<SVGPathElement>('.prism-area-fill');\n\n if (!fill) {\n fill = createSvgElement('path', { class: 'prism-area-fill' });\n parent.appendChild(fill);\n }\n\n setAttributes(fill, { fill: options.color, 'fill-opacity': options.fillOpacity, stroke: 'none' });\n\n let line: SVGPathElement | null = null;\n\n if (options.showLine) {\n line = parent.querySelector<SVGPathElement>('.prism-area-line');\n\n if (!line) {\n line = createSvgElement('path', { class: 'prism-area-line', fill: 'none' });\n parent.appendChild(line);\n }\n\n setAttributes(line, { stroke: options.color, 'stroke-width': 2 });\n } else {\n parent.querySelector('.prism-area-line')?.remove();\n }\n\n if (dur === 0) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n return;\n }\n\n activeAreaAnimations.get(parent)?.();\n\n const hasExisting = fill.hasAttribute('d');\n\n if (!hasExisting) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n previousPoints.set(parent, points);\n\n return;\n }\n\n const rawFrom = previousPoints.get(parent) ?? points;\n const fromPoints: Point[] = points.map((_, i) => rawFrom[i] ?? rawFrom[rawFrom.length - 1] ?? points[i]);\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAreaAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => ({\n x: tweenNumber(fromPoints[i].x, to.x, e),\n y: tweenNumber(fromPoints[i].y, to.y, e),\n }));\n const interpolatedBottom = interpolated.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill!, { d: areaPath(interpolated, interpolatedBottom, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(interpolated, options.curve) });\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAreaAnimations.delete(parent);\n previousPoints.set(parent, points);\n }\n }\n\n previousPoints.set(parent, fromPoints);\n\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n}\n\nexport function computeAreaPoints(data: Datum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeAreaPoints: datum.key is null or undefined — data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeAreaPoints: string keys are not supported for line/area charts — use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"area-renderer.js","names":[],"sources":["../../../src/charts/area/area-renderer.ts"],"sourcesContent":["import type { Point } from '../../svg/path';\nimport type { Datum, Scale, TransitionConfig } from '../../types';\n\nimport { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { tweenNumber } from '../../animation/tween';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { areaPath, linePath, monotonePath, stepPath } from '../../svg/path';\n\nexport interface AreaRenderOptions {\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed — stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n fillOpacity: number;\n showLine: boolean;\n transition?: TransitionConfig;\n}\n\nconst activeAreaAnimations = new WeakMap<SVGGElement, () => void>();\nconst previousPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildLinePath(pts: Point[], curve: AreaRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderArea(parent: SVGGElement, points: Point[], baselineY: number, options: AreaRenderOptions): void {\n const dur = options.transition?.duration ?? (options.transition ? 300 : 0);\n const easing = resolveEasing(options.transition?.easing);\n\n let fill = parent.querySelector<SVGPathElement>('.prism-area-fill');\n\n if (!fill) {\n fill = createSvgElement('path', { class: 'prism-area-fill' });\n parent.appendChild(fill);\n }\n\n setAttributes(fill, { fill: options.color, 'fill-opacity': options.fillOpacity, stroke: 'none' });\n\n let line: SVGPathElement | null = null;\n\n if (options.showLine) {\n line = parent.querySelector<SVGPathElement>('.prism-area-line');\n\n if (!line) {\n line = createSvgElement('path', { class: 'prism-area-line', fill: 'none' });\n parent.appendChild(line);\n }\n\n setAttributes(line, { stroke: options.color, 'stroke-width': 2 });\n } else {\n parent.querySelector('.prism-area-line')?.remove();\n }\n\n if (dur === 0) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n return;\n }\n\n activeAreaAnimations.get(parent)?.();\n\n const hasExisting = fill.hasAttribute('d');\n\n if (!hasExisting) {\n const bottomPoints = points.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill, { d: areaPath(points, bottomPoints, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(points, options.curve) });\n\n previousPoints.set(parent, points);\n\n return;\n }\n\n const rawFrom = previousPoints.get(parent) ?? points;\n const fromPoints: Point[] = points.map((_, i) => rawFrom[i] ?? rawFrom[rawFrom.length - 1] ?? points[i]);\n\n let startTime: number | null = null;\n\n function frame(ts: number) {\n if (options.disposalSignal?.aborted) {\n activeAreaAnimations.delete(parent);\n\n return;\n }\n\n if (startTime === null) startTime = ts;\n\n const t = Math.min(1, (ts - startTime) / dur);\n const e = easing(t);\n const interpolated: Point[] = points.map((to, i) => ({\n x: tweenNumber(fromPoints[i].x, to.x, e),\n y: tweenNumber(fromPoints[i].y, to.y, e),\n }));\n const interpolatedBottom = interpolated.map((p) => ({ x: p.x, y: baselineY }));\n\n setAttributes(fill!, { d: areaPath(interpolated, interpolatedBottom, options.curve) });\n\n if (line) setAttributes(line, { d: buildLinePath(interpolated, options.curve) });\n\n if (t < 1) {\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n } else {\n activeAreaAnimations.delete(parent);\n previousPoints.set(parent, points);\n }\n }\n\n previousPoints.set(parent, fromPoints);\n\n const id = requestAnimationFrame(frame);\n\n activeAreaAnimations.set(parent, () => cancelAnimationFrame(id));\n}\n\nexport function computeAreaPoints(data: Datum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computeAreaPoints: datum.key is null or undefined — data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computeAreaPoints: string keys are not supported for line/area charts — use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../axes/axis.cjs"),n=require("../../axes/grid.cjs"),r=require("../../scales/linear.cjs"),i=require("../../core/layout.cjs"),a=require("../../core/chart-scaffold.cjs"),o=require("../../interaction/events.cjs"),s=require("../../theme/index.cjs"),c=require("../../scales/band.cjs"),l=require("./bar-hit-test.cjs"),u=require("./bar-renderer.cjs");let d=require("@vielzeug/ripple");function f(e){return{horizontal:e===`grouped-horizontal`||e===`stacked-horizontal`,stacked:e===`stacked`||e===`stacked-horizontal`}}function p(p,m){return a.createChartScaffold(p,m,p=>{let{groups:h,legend:g,tooltip:_}=p,v=p.dimensions.value,y=i.chartArea(v.width,v.height,v.margin),b=(0,d.isReactive)(m.series)?m.series.value:m.series,x=b.map(e=>(0,d.isReactive)(e.data)?e.data.value:e.data),S=[...new Set(x.flat().map(e=>String(e.key)))];if(S.length===0){a.clearCartesianDom(h,g,_);return}let{horizontal:C,stacked:w}=f(m.variant??`grouped`),T,E;if(w){x.some(e=>e.some(e=>e.value<0));let e=S.map(e=>x.reduce((t,n)=>{let r=n.find(t=>String(t.key)===e);return t+(r?Math.max(0,r.value):0)},0));T=Math.max(...e),E=0}else{let e=x.flat().map(e=>e.value);T=Math.max(...e),E=Math.min(0,...e)}let D=C?c.bandScale({domain:S,range:[0,y.height]}):c.bandScale({domain:S,range:[0,y.width]}),O=C?r.linearScale({domain:[E,T],range:[0,y.width]}):r.linearScale({domain:[E,T],range:[y.height,0]}),k=[],A=Object.create(null);for(let e of S)A[e]=0;let j={bandCenter:e=>D.map(e)+D.bandwidth()/2,bandwidth:D.bandwidth(),baselinePx:O.map(0),horizontal:C,stacked:w,stackedTops:k,valueScale:O};for(C?(m.xAxis?.grid&&n.renderGrid(h.grid,O,m.xAxis.grid,y.height,`vertical`,t.resolveTickCount(m.xAxis,y.width,`bottom`)),m.yAxis&&t.renderAxis(h.yAxis,D,m.yAxis,y.height,`left`),m.xAxis&&(h.xAxis.setAttribute(`transform`,`translate(0,${y.height})`),t.renderAxis(h.xAxis,O,m.xAxis,y.width,`bottom`))):(m.yAxis?.grid&&n.renderGrid(h.grid,O,m.yAxis.grid,y.width,`horizontal`,t.resolveTickCount(m.yAxis,y.height,`left`)),m.xAxis&&(h.xAxis.setAttribute(`transform`,`translate(0,${y.height})`),t.renderAxis(h.xAxis,D,m.xAxis,y.width,`bottom`)),m.yAxis&&t.renderAxis(h.yAxis,O,m.yAxis,y.height,`left`));h.series.children.length>b.length;){let e=h.series.lastElementChild;e&&h.series.removeChild(e)}for(let t=0;t<b.length;t++){let n=b[t],r=h.series.children[t];r||(r=e.createSvgElement(`g`,{class:`prism-bar-series`}),h.series.appendChild(r));let i=x[t].map(e=>{let t=String(e.key);if(w){let n=A[t]??0,r=n+Math.max(0,e.value);return A[t]=r,{base:n,key:t,y:r}}return{base:0,key:t,y:e.value}});k[t]=i.map(e=>e.y);let a=w?i.map(e=>O.map(e.base)):void 0;u.renderBars(r,i,D,O,j.baselinePx,{baselineYs:a,borderRadius:n.borderRadius??0,color:s.seriesColor(t,n.color),disposalSignal:p.disposalSignal,horizontal:C,seriesCount:b.length,seriesIndex:t,stacked:w,transition:m.transition})}return g?.update(b.map((e,t)=>({color:s.seriesColor(t,e.color),name:e.name}))),_?.hide(),{onClick:e=>{if(!m.onClick)return;let t=p.dimensions.value,n=o.getMousePosition(p.svg,e,t.margin.left,t.margin.top),r=i.chartArea(t.width,t.height,t.margin);if(n.x<0||n.x>r.width||n.y<0||n.y>r.height)return;let a=C?n.y:n.x,s=l.findCatIdx(a,S,j);if(s===-1)return;let c=l.findSeriesIdx(n,s,S,j,b.length),u=x[c]?.[s];u&&m.onClick({datum:u,originalEvent:e,series:b[c]})},onMouseLeave:()=>{_?.hide(),m.onHover?.(null)},onMouseMove:e=>{let t=p.dimensions.value,n=o.getMousePosition(p.svg,e,t.margin.left,t.margin.top),r=i.chartArea(t.width,t.height,t.margin);if(n.x<0||n.x>r.width||n.y<0||n.y>r.height){_?.hide();return}let a=C?n.y:n.x,s=l.findCatIdx(a,S,j);if(s===-1){_?.hide();return}if(l.isOutsideBars(n,s,x,j,b.length)){_?.hide();return}let c=l.findSeriesIdx(n,s,S,j,b.length),u=x[c]?.[s];if(u){let n=j.bandCenter(S[s]),r=w?k[c]?.[s]??u.value:u.value,i=O.map(r),a=C?i+t.margin.left:n+t.margin.left,o=C?n+t.margin.top:i+t.margin.top;_?.show(a,o,u,b[c]),m.onHover?.({datum:u,originalEvent:e,series:b[c]})}}}})}exports.createBarChart=p;
|
|
2
2
|
//# sourceMappingURL=bar-chart.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-chart.cjs","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { BarChartConfig, BarVariant, ChartHandle } from '../../types';\nimport type { BarScaleContext } from './bar-scale-context';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { getMousePosition } from '../../interaction/events';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { findCatIdx, findSeriesIdx, isOutsideBars } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\n\nfunction variantFlags(variant: BarVariant): { horizontal: boolean; stacked: boolean } {\n return {\n horizontal: variant === 'grouped-horizontal' || variant === 'stacked-horizontal',\n stacked: variant === 'stacked' || variant === 'stacked-horizontal',\n };\n}\n\n// ─── Chart ────────────────────────────────────────────────────────────────────\n\nexport function createBarChart(container: HTMLElement, config: BarChartConfig): ChartHandle {\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const categories = [...new Set(allData.flat().map((d) => String(d.key)))];\n\n if (categories.length === 0) {\n warn('createBarChart: no data');\n clearCartesianDom(groups, legend, tooltip);\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((sd) => sd.some((d) => d.value < 0))) {\n warn(\n 'createBarChart: negative values in a stacked/stacked-horizontal series are clamped to 0 — stacking mixed-sign data is not supported.',\n );\n }\n\n const sums = categories.map((cat) =>\n allData.reduce((sum, sd) => {\n const pt = sd.find((d) => String(d.key) === cat);\n\n return sum + (pt ? Math.max(0, pt.value) : 0);\n }, 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flat().map((d) => d.value);\n\n vMax = Math.max(...allY);\n vMin = Math.min(0, ...allY);\n }\n\n // Build uniform scale context\n const catScale = horizontal\n ? bandScale({ domain: categories, range: [0, area.height] })\n : bandScale({ domain: categories, range: [0, area.width] });\n\n const valScale = horizontal\n ? linearScale({ domain: [vMin, vMax], range: [0, area.width] })\n : linearScale({ domain: [vMin, vMax], range: [area.height, 0] });\n\n const stackedTops: number[][] = [];\n const stackTops = Object.create(null) as Record<string, number>;\n\n for (const cat of categories) stackTops[cat] = 0;\n\n const sc: BarScaleContext = {\n bandCenter: (cat) => catScale.map(cat) + catScale.bandwidth() / 2,\n bandwidth: catScale.bandwidth(),\n baselinePx: valScale.map(0),\n horizontal,\n stacked,\n stackedTops,\n valueScale: valScale,\n };\n\n // Axes & grid\n if (horizontal) {\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n valScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, catScale, config.yAxis, area.height, 'left');\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, valScale, config.xAxis, area.width, 'bottom');\n }\n } else {\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n valScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, catScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, valScale, config.yAxis, area.height, 'left');\n }\n\n // Series groups\n while (groups.series.children.length > seriesList.length) {\n const last = groups.series.lastElementChild;\n\n if (last) groups.series.removeChild(last);\n }\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-bar-series' });\n groups.series.appendChild(group);\n }\n\n const barData = allData[i].map((d) => {\n const key = String(d.key);\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, d.value);\n\n stackTops[key] = top;\n\n return { base, key, y: top };\n }\n\n return { base: 0, key, y: d.value };\n });\n\n stackedTops[i] = barData.map((d) => d.y);\n\n const baselineYs = stacked ? barData.map((d) => valScale.map(d.base)) : undefined;\n\n renderBars(group, barData, catScale, valScale, sc.baselinePx, {\n baselineYs,\n borderRadius: series.borderRadius ?? 0,\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n horizontal,\n seriesCount: seriesList.length,\n seriesIndex: i,\n stacked,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const onMouseMove = (event: MouseEvent) => {\n const d = ctx.dimensions.value;\n const pos = getMousePosition(ctx.svg, event, d.margin.left, d.margin.top);\n const a = chartArea(d.width, d.height, d.margin);\n\n if (pos.x < 0 || pos.x > a.width || pos.y < 0 || pos.y > a.height) {\n tooltip?.hide();\n\n return;\n }\n\n const posBand = horizontal ? pos.y : pos.x;\n const catIdx = findCatIdx(posBand, categories, sc);\n\n if (catIdx === -1) {\n tooltip?.hide();\n\n return;\n }\n\n if (isOutsideBars(pos, catIdx, allData, sc, seriesList.length)) {\n tooltip?.hide();\n\n return;\n }\n\n const seriesIdx = findSeriesIdx(pos, catIdx, categories, sc, seriesList.length);\n const point = allData[seriesIdx]?.[catIdx];\n\n if (point) {\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const stackedTop = stacked ? (stackedTops[seriesIdx]?.[catIdx] ?? point.value) : point.value;\n const valuePx = valScale.map(stackedTop);\n\n const tooltipX = horizontal ? valuePx + d.margin.left : bandCenterPx + d.margin.left;\n const tooltipY = horizontal ? bandCenterPx + d.margin.top : valuePx + d.margin.top;\n\n tooltip?.show(tooltipX, tooltipY, point, seriesList[seriesIdx]);\n config.onHover?.({ datum: point, originalEvent: event, series: seriesList[seriesIdx] });\n }\n };\n\n const onMouseLeave = () => {\n tooltip?.hide();\n config.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!config.onClick) return;\n\n const d = ctx.dimensions.value;\n const pos = getMousePosition(ctx.svg, event, d.margin.left, d.margin.top);\n const a = chartArea(d.width, d.height, d.margin);\n\n if (pos.x < 0 || pos.x > a.width || pos.y < 0 || pos.y > a.height) return;\n\n const posBand = horizontal ? pos.y : pos.x;\n const catIdx = findCatIdx(posBand, categories, sc);\n\n if (catIdx === -1) return;\n\n const seriesIdx = findSeriesIdx(pos, catIdx, categories, sc, seriesList.length);\n const point = allData[seriesIdx]?.[catIdx];\n\n if (point) {\n config.onClick({ datum: point, originalEvent: event, series: seriesList[seriesIdx] });\n }\n };\n\n return { onClick, onMouseLeave, onMouseMove };\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bar-chart.cjs","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { isReactive } from '@vielzeug/ripple';\n\nimport type { BarChartConfig, BarVariant, ChartHandle } from '../../types';\nimport type { BarScaleContext } from './bar-scale-context';\n\nimport { warn } from '../../_dev';\nimport { renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { getMousePosition } from '../../interaction/events';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport { findCatIdx, findSeriesIdx, isOutsideBars } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\n\nfunction variantFlags(variant: BarVariant): { horizontal: boolean; stacked: boolean } {\n return {\n horizontal: variant === 'grouped-horizontal' || variant === 'stacked-horizontal',\n stacked: variant === 'stacked' || variant === 'stacked-horizontal',\n };\n}\n\n// ─── Chart ────────────────────────────────────────────────────────────────────\n\nexport function createBarChart(container: HTMLElement, config: BarChartConfig): ChartHandle {\n return createChartScaffold(container, config, (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions.value;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const seriesList = isReactive(config.series) ? config.series.value : config.series;\n const allData = seriesList.map((s) => (isReactive(s.data) ? s.data.value : s.data));\n const categories = [...new Set(allData.flat().map((d) => String(d.key)))];\n\n if (categories.length === 0) {\n warn('createBarChart: no data');\n clearCartesianDom(groups, legend, tooltip);\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((sd) => sd.some((d) => d.value < 0))) {\n warn(\n 'createBarChart: negative values in a stacked/stacked-horizontal series are clamped to 0 — stacking mixed-sign data is not supported.',\n );\n }\n\n const sums = categories.map((cat) =>\n allData.reduce((sum, sd) => {\n const pt = sd.find((d) => String(d.key) === cat);\n\n return sum + (pt ? Math.max(0, pt.value) : 0);\n }, 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flat().map((d) => d.value);\n\n vMax = Math.max(...allY);\n vMin = Math.min(0, ...allY);\n }\n\n // Build uniform scale context\n const catScale = horizontal\n ? bandScale({ domain: categories, range: [0, area.height] })\n : bandScale({ domain: categories, range: [0, area.width] });\n\n const valScale = horizontal\n ? linearScale({ domain: [vMin, vMax], range: [0, area.width] })\n : linearScale({ domain: [vMin, vMax], range: [area.height, 0] });\n\n const stackedTops: number[][] = [];\n const stackTops = Object.create(null) as Record<string, number>;\n\n for (const cat of categories) stackTops[cat] = 0;\n\n const sc: BarScaleContext = {\n bandCenter: (cat) => catScale.map(cat) + catScale.bandwidth() / 2,\n bandwidth: catScale.bandwidth(),\n baselinePx: valScale.map(0),\n horizontal,\n stacked,\n stackedTops,\n valueScale: valScale,\n };\n\n // Axes & grid\n if (horizontal) {\n if (config.xAxis?.grid) {\n renderGrid(\n groups.grid,\n valScale,\n config.xAxis.grid,\n area.height,\n 'vertical',\n resolveTickCount(config.xAxis, area.width, 'bottom'),\n );\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, catScale, config.yAxis, area.height, 'left');\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, valScale, config.xAxis, area.width, 'bottom');\n }\n } else {\n if (config.yAxis?.grid) {\n renderGrid(\n groups.grid,\n valScale,\n config.yAxis.grid,\n area.width,\n 'horizontal',\n resolveTickCount(config.yAxis, area.height, 'left'),\n );\n }\n\n if (config.xAxis) {\n groups.xAxis.setAttribute('transform', `translate(0,${area.height})`);\n renderAxis(groups.xAxis, catScale, config.xAxis, area.width, 'bottom');\n }\n\n if (config.yAxis) renderAxis(groups.yAxis, valScale, config.yAxis, area.height, 'left');\n }\n\n // Series groups\n while (groups.series.children.length > seriesList.length) {\n const last = groups.series.lastElementChild;\n\n if (last) groups.series.removeChild(last);\n }\n\n for (let i = 0; i < seriesList.length; i++) {\n const series = seriesList[i];\n let group = groups.series.children[i] as SVGGElement | undefined;\n\n if (!group) {\n group = createSvgElement('g', { class: 'prism-bar-series' });\n groups.series.appendChild(group);\n }\n\n const barData = allData[i].map((d) => {\n const key = String(d.key);\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, d.value);\n\n stackTops[key] = top;\n\n return { base, key, y: top };\n }\n\n return { base: 0, key, y: d.value };\n });\n\n stackedTops[i] = barData.map((d) => d.y);\n\n const baselineYs = stacked ? barData.map((d) => valScale.map(d.base)) : undefined;\n\n renderBars(group, barData, catScale, valScale, sc.baselinePx, {\n baselineYs,\n borderRadius: series.borderRadius ?? 0,\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n horizontal,\n seriesCount: seriesList.length,\n seriesIndex: i,\n stacked,\n transition: config.transition,\n });\n }\n\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n tooltip?.hide();\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const onMouseMove = (event: MouseEvent) => {\n const d = ctx.dimensions.value;\n const pos = getMousePosition(ctx.svg, event, d.margin.left, d.margin.top);\n const a = chartArea(d.width, d.height, d.margin);\n\n if (pos.x < 0 || pos.x > a.width || pos.y < 0 || pos.y > a.height) {\n tooltip?.hide();\n\n return;\n }\n\n const posBand = horizontal ? pos.y : pos.x;\n const catIdx = findCatIdx(posBand, categories, sc);\n\n if (catIdx === -1) {\n tooltip?.hide();\n\n return;\n }\n\n if (isOutsideBars(pos, catIdx, allData, sc, seriesList.length)) {\n tooltip?.hide();\n\n return;\n }\n\n const seriesIdx = findSeriesIdx(pos, catIdx, categories, sc, seriesList.length);\n const point = allData[seriesIdx]?.[catIdx];\n\n if (point) {\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const stackedTop = stacked ? (stackedTops[seriesIdx]?.[catIdx] ?? point.value) : point.value;\n const valuePx = valScale.map(stackedTop);\n\n const tooltipX = horizontal ? valuePx + d.margin.left : bandCenterPx + d.margin.left;\n const tooltipY = horizontal ? bandCenterPx + d.margin.top : valuePx + d.margin.top;\n\n tooltip?.show(tooltipX, tooltipY, point, seriesList[seriesIdx]);\n config.onHover?.({ datum: point, originalEvent: event, series: seriesList[seriesIdx] });\n }\n };\n\n const onMouseLeave = () => {\n tooltip?.hide();\n config.onHover?.(null);\n };\n\n const onClick = (event: MouseEvent) => {\n if (!config.onClick) return;\n\n const d = ctx.dimensions.value;\n const pos = getMousePosition(ctx.svg, event, d.margin.left, d.margin.top);\n const a = chartArea(d.width, d.height, d.margin);\n\n if (pos.x < 0 || pos.x > a.width || pos.y < 0 || pos.y > a.height) return;\n\n const posBand = horizontal ? pos.y : pos.x;\n const catIdx = findCatIdx(posBand, categories, sc);\n\n if (catIdx === -1) return;\n\n const seriesIdx = findSeriesIdx(pos, catIdx, categories, sc, seriesList.length);\n const point = allData[seriesIdx]?.[catIdx];\n\n if (point) {\n config.onClick({ datum: point, originalEvent: event, series: seriesList[seriesIdx] });\n }\n };\n\n return { onClick, onMouseLeave, onMouseMove };\n });\n}\n"],"mappings":"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"}
|