@vielzeug/prism 26.10.4 → 26.10.6
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/README.md +15 -26
- package/dist/animation/reveal.cjs +2 -0
- package/dist/animation/reveal.cjs.map +1 -0
- package/dist/animation/reveal.d.ts +29 -0
- package/dist/animation/reveal.d.ts.map +1 -0
- package/dist/animation/reveal.js +2 -0
- package/dist/animation/reveal.js.map +1 -0
- package/dist/axes/axis.cjs +1 -1
- package/dist/axes/axis.cjs.map +1 -1
- package/dist/axes/axis.d.ts +10 -3
- package/dist/axes/axis.d.ts.map +1 -1
- package/dist/axes/axis.js +1 -1
- package/dist/axes/axis.js.map +1 -1
- package/dist/axes/grid.cjs +1 -1
- package/dist/axes/grid.cjs.map +1 -1
- package/dist/axes/grid.d.ts +1 -1
- package/dist/axes/grid.d.ts.map +1 -1
- package/dist/axes/grid.js +1 -1
- package/dist/axes/grid.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.d.ts.map +1 -1
- package/dist/charts/area/area-chart.js +1 -1
- package/dist/charts/area/area-chart.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.d.ts.map +1 -1
- package/dist/charts/bar/bar-chart.js +1 -1
- package/dist/charts/bar/bar-chart.js.map +1 -1
- package/dist/charts/bar/bar-renderer.cjs +1 -1
- package/dist/charts/bar/bar-renderer.cjs.map +1 -1
- package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
- package/dist/charts/bar/bar-renderer.js +1 -1
- package/dist/charts/bar/bar-renderer.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.d.ts.map +1 -1
- package/dist/charts/line/line-chart.js +1 -1
- 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.d.ts +5 -2
- package/dist/charts/line/line-renderer.d.ts.map +1 -1
- package/dist/charts/line/line-renderer.js +1 -1
- package/dist/charts/line/line-renderer.js.map +1 -1
- package/dist/charts/pie/pie-chart.cjs +1 -1
- package/dist/charts/pie/pie-chart.cjs.map +1 -1
- package/dist/charts/pie/pie-chart.d.ts.map +1 -1
- package/dist/charts/pie/pie-chart.js +1 -1
- package/dist/charts/pie/pie-chart.js.map +1 -1
- package/dist/charts/scatter/index.d.ts +2 -0
- package/dist/charts/scatter/index.d.ts.map +1 -0
- package/dist/charts/scatter/scatter-chart.cjs +2 -0
- package/dist/charts/scatter/scatter-chart.cjs.map +1 -0
- package/dist/charts/scatter/scatter-chart.d.ts +3 -0
- package/dist/charts/scatter/scatter-chart.d.ts.map +1 -0
- package/dist/charts/scatter/scatter-chart.js +2 -0
- package/dist/charts/scatter/scatter-chart.js.map +1 -0
- package/dist/charts/scatter/scatter-renderer.cjs +2 -0
- package/dist/charts/scatter/scatter-renderer.cjs.map +1 -0
- package/dist/charts/scatter/scatter-renderer.d.ts +24 -0
- package/dist/charts/scatter/scatter-renderer.d.ts.map +1 -0
- package/dist/charts/scatter/scatter-renderer.js +2 -0
- package/dist/charts/scatter/scatter-renderer.js.map +1 -0
- package/dist/core/chart-base.cjs +1 -1
- package/dist/core/chart-base.cjs.map +1 -1
- package/dist/core/chart-base.d.ts +1 -0
- package/dist/core/chart-base.d.ts.map +1 -1
- package/dist/core/chart-base.js +1 -1
- 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 +4 -2
- package/dist/core/chart-scaffold.d.ts.map +1 -1
- package/dist/core/chart-scaffold.js +1 -1
- package/dist/core/chart-scaffold.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/interaction/announcer.cjs +1 -1
- package/dist/interaction/announcer.cjs.map +1 -1
- package/dist/interaction/announcer.d.ts +1 -1
- package/dist/interaction/announcer.d.ts.map +1 -1
- package/dist/interaction/announcer.js +1 -1
- package/dist/interaction/announcer.js.map +1 -1
- package/dist/interaction/legend.cjs +1 -1
- package/dist/interaction/legend.cjs.map +1 -1
- package/dist/interaction/legend.d.ts +1 -1
- package/dist/interaction/legend.d.ts.map +1 -1
- package/dist/interaction/legend.js +1 -1
- package/dist/interaction/legend.js.map +1 -1
- package/dist/interaction/scatter-interaction.cjs +2 -0
- package/dist/interaction/scatter-interaction.cjs.map +1 -0
- package/dist/interaction/scatter-interaction.d.ts +36 -0
- package/dist/interaction/scatter-interaction.d.ts.map +1 -0
- package/dist/interaction/scatter-interaction.js +2 -0
- package/dist/interaction/scatter-interaction.js.map +1 -0
- package/dist/interaction/series-interaction.cjs +1 -1
- package/dist/interaction/series-interaction.cjs.map +1 -1
- package/dist/interaction/series-interaction.d.ts +3 -1
- package/dist/interaction/series-interaction.d.ts.map +1 -1
- package/dist/interaction/series-interaction.js +1 -1
- package/dist/interaction/series-interaction.js.map +1 -1
- package/dist/interaction/tooltip.cjs +1 -1
- package/dist/interaction/tooltip.cjs.map +1 -1
- package/dist/interaction/tooltip.d.ts.map +1 -1
- package/dist/interaction/tooltip.js +1 -1
- 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/theme/prism.css +6 -0
- package/dist/types.d.ts +39 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +4 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-chart.cjs","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { positionAxis, renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { normalizeCartesianSeries } from '../../core/cartesian-model';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { getMousePosition } from '../../interaction/events';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n ChartEvent,\n ChartHandle,\n SeriesValue,\n XAxisConfig,\n YAxisConfig,\n} from '../../types';\nimport { findCatIdx, findSeriesIdx } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\nimport type { BarScaleContext } from './bar-scale-context';\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<BarSeriesConfig[]> {\n let seriesList = config.series;\n let band: SVGRectElement | null = null;\n\n return createChartScaffold(\n container,\n config,\n (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const sourceData = seriesList.map((series) => series.data);\n const model = normalizeCartesianSeries(seriesList, sourceData);\n const categories = model.domain;\n const allData = model.series.map(({ byKey }) => categories.map((key) => byKey.get(key)));\n const categoryAxis = (axis: XAxisConfig | YAxisConfig) => {\n return {\n ...axis,\n tickFormat: (value: Date | number | string) => {\n const key = String(value);\n const label = model.labels.get(key) ?? value;\n\n return axis.tickFormat ? axis.tickFormat(label) : String(label);\n },\n };\n };\n\n if (categories.length === 0) {\n clearCartesianDom(groups, legend, tooltip);\n band?.remove();\n band = null;\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Axes render by default; `false` opts out. The value axis carries gridlines by\n // default, the category axis does not; an explicit config is used verbatim.\n const xAxisConfig: XAxisConfig | false =\n config.xAxis === false ? false : (config.xAxis ?? (horizontal ? { grid: true } : {}));\n const yAxisConfig: YAxisConfig | false =\n config.yAxis === false ? false : (config.yAxis ?? (horizontal ? {} : { grid: true }));\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((seriesData) => seriesData.some((datum) => (datum?.value ?? 0) < 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((_, categoryIndex) =>\n allData.reduce((sum, seriesData) => sum + Math.max(0, seriesData[categoryIndex]?.value ?? 0), 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flatMap((seriesData) => seriesData.flatMap((datum) => (datum ? [datum.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 (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTickCount(xAxisConfig, area.width, 'bottom'),\n );\n }\n\n if (yAxisConfig !== false) {\n const yAxis = categoryAxis(yAxisConfig);\n\n positionAxis(groups.yAxis, yAxis.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, catScale, yAxis, area.height, 'left');\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, valScale, xAxisConfig, area.width, 'bottom');\n }\n } else {\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTickCount(yAxisConfig, area.height, 'left'),\n );\n }\n\n if (xAxisConfig !== false) {\n const xAxis = categoryAxis(xAxisConfig);\n\n positionAxis(groups.xAxis, xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, catScale, xAxis, area.width, 'bottom');\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, valScale, yAxisConfig, area.height, 'left');\n }\n }\n\n // Series groups\n // Stacked segments stay square so they join cleanly.\n const themeRadius = stacked\n ? 0\n : Number.parseFloat(getComputedStyle(ctx.svg).getPropertyValue('--prism-bar-radius')) || 0;\n\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 group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const barData = categories.map((key, categoryIndex) => {\n const datum = allData[i]?.[categoryIndex];\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, datum?.value ?? 0);\n\n stackTops[key] = top;\n\n return { base, dash: datum?.dash, key, opacity: datum?.opacity, present: datum !== undefined, y: top };\n }\n\n return {\n base: 0,\n dash: datum?.dash,\n key,\n opacity: datum?.opacity,\n present: datum !== undefined,\n y: datum?.value ?? 0,\n };\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 ?? themeRadius,\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 groups.series.classList.toggle('prism-bars-stacked', stacked);\n\n if (!band || !ctx.chartArea.contains(band)) {\n band = createSvgElement('rect', { 'aria-hidden': 'true', class: 'prism-bar-band', 'pointer-events': 'none' });\n ctx.chartArea.insertBefore(band, groups.series);\n }\n\n band.style.display = 'none';\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const colors = seriesList.map((s, i) => seriesColor(i, s.color));\n const labelOf = (catIdx: number): string => String(model.labels.get(categories[catIdx]) ?? categories[catIdx]);\n let activeCat = -1;\n\n const valuesAt = (catIdx: number): SeriesValue[] =>\n seriesList.map((series, si) => ({ datum: allData[si]?.[catIdx], series }));\n\n const eventAt = (catIdx: number, seriesIdx: number, originalEvent: Event): ChartEvent | null => {\n const values = valuesAt(catIdx);\n const preferred = values[seriesIdx]?.datum ? seriesIdx : values.findIndex((v) => v.datum);\n const datum = values[preferred]?.datum;\n\n return datum ? { datum, originalEvent, series: seriesList[preferred], values } : null;\n };\n\n const setActive = (catIdx: number): void => {\n activeCat = catIdx;\n groups.series.classList.toggle('prism-bars-focused', catIdx >= 0);\n\n for (const group of groups.series.children) {\n for (const [i, rect] of [...group.children].entries())\n rect.classList.toggle('prism-bar--active', i === catIdx);\n }\n\n if (!band) return;\n\n band.style.display = catIdx < 0 ? 'none' : '';\n\n if (catIdx < 0) return;\n\n const start = sc.bandCenter(categories[catIdx]) - catScale.bandwidth() / 2 - catScale.gap() / 2;\n const size = catScale.bandwidth() + catScale.gap();\n const a = chartArea(ctx.dimensions.width, ctx.dimensions.height, ctx.dimensions.margin);\n\n setAttributes(\n band,\n horizontal\n ? { height: size, width: a.width, x: 0, y: start }\n : { height: a.height, width: size, x: start, y: 0 },\n );\n };\n\n const activate = (catIdx: number, seriesIdx: number, originalEvent: Event): void => {\n const event = eventAt(catIdx, seriesIdx, originalEvent);\n\n if (!event) return;\n\n setActive(catIdx);\n\n const values = event.values ?? [];\n const spoken = describeValues(labelOf(catIdx), values);\n\n if (tooltip) {\n const tops = values.map((v, si) =>\n stacked ? (stackedTops[si]?.[catIdx] ?? 0) : Math.max(0, v.datum?.value ?? 0),\n );\n const valuePx = valScale.map(Math.max(...tops));\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const { margin } = ctx.dimensions;\n const rows = values.flatMap((v, si) =>\n v.datum ? [{ color: colors[si], name: v.series.name, value: String(v.datum.value) }] : [],\n );\n\n tooltip.show(\n (horizontal ? valuePx : bandCenterPx) + margin.left,\n (horizontal ? bandCenterPx : valuePx) + margin.top,\n event.datum,\n event.series,\n comparisonContent(ctx.svg.ownerDocument, labelOf(catIdx), rows, spoken),\n );\n } else {\n ctx.announcer.announce(spoken);\n }\n\n config.onHover?.(event);\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hit = (event: MouseEvent): { catIdx: number; seriesIdx: number } | null => {\n const d = ctx.dimensions;\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 null;\n\n const catIdx = findCatIdx(horizontal ? pos.y : pos.x, categories, sc);\n\n return catIdx === -1\n ? null\n : { catIdx, seriesIdx: findSeriesIdx(pos, catIdx, categories, sc, seriesList.length) };\n };\n\n const onMouseMove = (event: MouseEvent) => {\n const target = hit(event);\n\n if (target) activate(target.catIdx, target.seriesIdx, event);\n else if (activeCat >= 0) deactivate();\n };\n\n const onClick = (event: MouseEvent) => {\n const target = config.onClick && hit(event);\n const chartEvent = target && eventAt(target.catIdx, target.seriesIdx, event);\n\n if (chartEvent) config.onClick?.(chartEvent);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const last = categories.length - 1;\n const prev = activeCat < 0 ? last : Math.max(0, activeCat - 1);\n const next = activeCat < 0 ? 0 : Math.min(last, activeCat + 1);\n const target: Record<string, number> = {\n ArrowDown: next,\n ArrowLeft: prev,\n ArrowRight: next,\n ArrowUp: prev,\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n activate(target[event.key], 0, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeCat >= 0 && config.onClick) {\n event.preventDefault();\n\n const chartEvent = eventAt(activeCat, 0, event);\n\n if (chartEvent) config.onClick(chartEvent);\n } else if (event.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"klBA4BA,SAAS,aAAa,EAAgE,CACpF,MAAO,CACL,WAAY,IAAY,sBAAwB,IAAY,qBAC5D,QAAS,IAAY,WAAa,IAAY,oBAChD,CACF,CAIA,SAAgB,eAAe,EAAwB,EAAwD,CAC7G,IAAI,EAAa,EAAO,OACpB,EAA8B,KAElC,OAAO,EAAA,oBACL,EACA,EACC,GAAQ,CACP,GAAM,CAAE,SAAQ,SAAQ,WAAY,EAC9B,EAAO,EAAI,WACX,EAAO,EAAA,UAAU,EAAK,MAAO,EAAK,OAAQ,EAAK,MAAM,EACrD,EAAa,EAAW,IAAK,GAAW,EAAO,IAAI,EACnD,EAAQ,EAAA,yBAAyB,EAAY,CAAU,EACvD,EAAa,EAAM,OACnB,EAAU,EAAM,OAAO,KAAK,CAAE,WAAY,EAAW,IAAK,GAAQ,EAAM,IAAI,CAAG,CAAC,CAAC,EACjF,aAAgB,IACb,CACL,GAAG,EACH,WAAa,GAAkC,CAC7C,IAAM,EAAM,OAAO,CAAK,EAClB,EAAQ,EAAM,OAAO,IAAI,CAAG,GAAK,EAEvC,OAAO,EAAK,WAAa,EAAK,WAAW,CAAK,EAAI,OAAO,CAAK,CAChE,CACF,GAGF,GAAI,EAAW,SAAW,EAAG,CAC3B,EAAA,kBAAkB,EAAQ,EAAQ,CAAO,EACzC,GAAM,OAAO,EACb,EAAO,KAEP,MACF,CAEA,GAAM,CAAE,aAAY,WAAY,aAAa,EAAO,SAAW,SAAS,EAIlE,EACJ,EAAO,QAAU,GAAQ,GAAS,EAAO,QAAU,EAAa,CAAE,KAAM,EAAK,EAAI,CAAC,GAC9E,EACJ,EAAO,QAAU,GAAQ,GAAS,EAAO,QAAU,EAAa,CAAC,EAAI,CAAE,KAAM,EAAK,GAGhF,EACA,EAEJ,GAAI,EAAS,CACP,EAAQ,KAAM,GAAe,EAAW,KAAM,IAAW,GAAO,OAAS,GAAK,CAAC,CAAC,EAMpF,IAAM,EAAO,EAAW,KAAK,EAAG,IAC9B,EAAQ,QAAQ,EAAK,IAAe,EAAM,KAAK,IAAI,EAAG,EAAW,EAAc,EAAE,OAAS,CAAC,EAAG,CAAC,CACjG,EAEA,EAAO,KAAK,IAAI,GAAG,CAAI,EACvB,EAAO,CACT,KAAO,CACL,IAAM,EAAO,EAAQ,QAAS,GAAe,EAAW,QAAS,GAAW,EAAQ,CAAC,EAAM,KAAK,EAAI,CAAC,CAAE,CAAC,EAExG,EAAO,KAAK,IAAI,GAAG,CAAI,EACvB,EAAO,KAAK,IAAI,EAAG,GAAG,CAAI,CAC5B,CAGA,IAAM,EAAW,EACb,EAAA,UAAU,CAAE,OAAQ,EAAY,MAAO,CAAC,EAAG,EAAK,MAAM,CAAE,CAAC,EACzD,EAAA,UAAU,CAAE,OAAQ,EAAY,MAAO,CAAC,EAAG,EAAK,KAAK,CAAE,CAAC,EAEtD,EAAW,EACb,EAAA,YAAY,CAAE,OAAQ,CAAC,EAAM,CAAI,EAAG,MAAO,CAAC,EAAG,EAAK,KAAK,CAAE,CAAC,EAC5D,EAAA,YAAY,CAAE,OAAQ,CAAC,EAAM,CAAI,EAAG,MAAO,CAAC,EAAK,OAAQ,CAAC,CAAE,CAAC,EAE3D,EAA0B,CAAC,EAC3B,EAAY,OAAO,OAAO,IAAI,EAEpC,IAAK,IAAM,KAAO,EAAY,EAAU,GAAO,EAE/C,IAAM,EAAsB,CAC1B,WAAa,GAAQ,EAAS,IAAI,CAAG,EAAI,EAAS,UAAU,EAAI,EAChE,UAAW,EAAS,UAAU,EAC9B,WAAY,EAAS,IAAI,CAAC,EAC1B,aACA,UACA,cACA,WAAY,CACd,EAGA,GAAI,EAAY,CAYd,GAXI,GAAe,EAAY,MAC7B,EAAA,WACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,OACL,WACA,EAAA,iBAAiB,EAAa,EAAK,MAAO,QAAQ,CACpD,EAGE,IAAgB,GAAO,CACzB,IAAM,EAAQ,aAAa,CAAW,EAEtC,EAAA,aAAa,EAAO,MAAO,EAAM,UAAY,OAAQ,EAAK,MAAO,EAAK,MAAM,EAC5E,EAAA,WAAW,EAAO,MAAO,EAAU,EAAO,EAAK,OAAQ,MAAM,CAC/D,CAEI,IACF,EAAA,aAAa,EAAO,MAAO,EAAY,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EACpF,EAAA,WAAW,EAAO,MAAO,EAAU,EAAa,EAAK,MAAO,QAAQ,EAExE,KAAO,CAYL,GAXI,GAAe,EAAY,MAC7B,EAAA,WACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,MACL,aACA,EAAA,iBAAiB,EAAa,EAAK,OAAQ,MAAM,CACnD,EAGE,IAAgB,GAAO,CACzB,IAAM,EAAQ,aAAa,CAAW,EAEtC,EAAA,aAAa,EAAO,MAAO,EAAM,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EAC9E,EAAA,WAAW,EAAO,MAAO,EAAU,EAAO,EAAK,MAAO,QAAQ,CAChE,CAEI,IACF,EAAA,aAAa,EAAO,MAAO,EAAY,UAAY,OAAQ,EAAK,MAAO,EAAK,MAAM,EAClF,EAAA,WAAW,EAAO,MAAO,EAAU,EAAa,EAAK,OAAQ,MAAM,EAEvE,CAIA,IAAM,EAAc,EAChB,EACA,OAAO,WAAW,iBAAiB,EAAI,GAAG,CAAC,CAAC,iBAAiB,oBAAoB,CAAC,GAAK,EAE3F,KAAO,EAAO,OAAO,SAAS,OAAS,EAAW,QAAQ,CACxD,IAAM,EAAO,EAAO,OAAO,iBAEvB,GAAM,EAAO,OAAO,YAAY,CAAI,CAC1C,CAEA,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,kBAAmB,CAAC,EAC3D,EAAO,OAAO,YAAY,CAAK,GAGjC,EAAM,aAAa,iBAAkB,EAAA,YAAY,EAAQ,CAAC,CAAC,EAE3D,IAAM,EAAU,EAAW,KAAK,EAAK,IAAkB,CACrD,IAAM,EAAQ,EAAQ,EAAE,GAAG,GAE3B,GAAI,EAAS,CACX,IAAM,EAAO,EAAU,IAAQ,EACzB,EAAM,EAAO,KAAK,IAAI,EAAG,GAAO,OAAS,CAAC,EAIhD,MAFA,GAAU,GAAO,EAEV,CAAE,OAAM,KAAM,GAAO,KAAM,MAAK,QAAS,GAAO,QAAS,QAAS,IAAU,IAAA,GAAW,EAAG,CAAI,CACvG,CAEA,MAAO,CACL,KAAM,EACN,KAAM,GAAO,KACb,MACA,QAAS,GAAO,QAChB,QAAS,IAAU,IAAA,GACnB,EAAG,GAAO,OAAS,CACrB,CACF,CAAC,EAED,EAAY,GAAK,EAAQ,IAAK,GAAM,EAAE,CAAC,EAEvC,IAAM,EAAa,EAAU,EAAQ,IAAK,GAAM,EAAS,IAAI,EAAE,IAAI,CAAC,EAAI,IAAA,GAExE,EAAA,WAAW,EAAO,EAAS,EAAU,EAAU,EAAG,WAAY,CAC5D,aACA,aAAc,EAAO,cAAgB,EACrC,MAAO,EAAA,YAAY,EAAG,EAAO,KAAK,EAClC,eAAgB,EAAI,eACpB,aACA,YAAa,EAAW,OACxB,YAAa,EACb,UACA,WAAY,EAAO,UACrB,CAAC,CACH,CAEA,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAA,YAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,GAAS,KAAK,EACd,EAAO,OAAO,UAAU,OAAO,qBAAsB,CAAO,GAExD,CAAC,GAAQ,CAAC,EAAI,UAAU,SAAS,CAAI,KACvC,EAAO,EAAA,iBAAiB,OAAQ,CAAE,cAAe,OAAQ,MAAO,iBAAkB,iBAAkB,MAAO,CAAC,EAC5G,EAAI,UAAU,aAAa,EAAM,EAAO,MAAM,GAGhD,EAAK,MAAM,QAAU,OAIrB,IAAM,EAAS,EAAW,KAAK,EAAG,IAAM,EAAA,YAAY,EAAG,EAAE,KAAK,CAAC,EACzD,QAAW,GAA2B,OAAO,EAAM,OAAO,IAAI,EAAW,EAAO,GAAK,EAAW,EAAO,EACzG,EAAY,GAEV,SAAY,GAChB,EAAW,KAAK,EAAQ,KAAQ,CAAE,MAAO,EAAQ,EAAG,GAAG,GAAS,QAAO,EAAE,EAErE,SAAW,EAAgB,EAAmB,IAA4C,CAC9F,IAAM,EAAS,SAAS,CAAM,EACxB,EAAY,EAAO,EAAU,EAAE,MAAQ,EAAY,EAAO,UAAW,GAAM,EAAE,KAAK,EAClF,EAAQ,EAAO,EAAU,EAAE,MAEjC,OAAO,EAAQ,CAAE,QAAO,gBAAe,OAAQ,EAAW,GAAY,QAAO,EAAI,IACnF,EAEM,UAAa,GAAyB,CAC1C,EAAY,EACZ,EAAO,OAAO,UAAU,OAAO,qBAAsB,GAAU,CAAC,EAEhE,IAAK,IAAM,KAAS,EAAO,OAAO,SAChC,IAAK,GAAM,CAAC,EAAG,IAAS,CAAC,GAAG,EAAM,QAAQ,CAAC,CAAC,QAAQ,EAClD,EAAK,UAAU,OAAO,oBAAqB,IAAM,CAAM,EAO3D,GAJI,CAAC,IAEL,EAAK,MAAM,QAAU,EAAS,EAAI,OAAS,GAEvC,EAAS,GAAG,OAEhB,IAAM,EAAQ,EAAG,WAAW,EAAW,EAAO,EAAI,EAAS,UAAU,EAAI,EAAI,EAAS,IAAI,EAAI,EACxF,EAAO,EAAS,UAAU,EAAI,EAAS,IAAI,EAC3C,EAAI,EAAA,UAAU,EAAI,WAAW,MAAO,EAAI,WAAW,OAAQ,EAAI,WAAW,MAAM,EAEtF,EAAA,cACE,EACA,EACI,CAAE,OAAQ,EAAM,MAAO,EAAE,MAAO,EAAG,EAAG,EAAG,CAAM,EAC/C,CAAE,OAAQ,EAAE,OAAQ,MAAO,EAAM,EAAG,EAAO,EAAG,CAAE,CACtD,CACF,EAEM,UAAY,EAAgB,EAAmB,IAA+B,CAClF,IAAM,EAAQ,QAAQ,EAAQ,EAAW,CAAa,EAEtD,GAAI,CAAC,EAAO,OAEZ,UAAU,CAAM,EAEhB,IAAM,EAAS,EAAM,QAAU,CAAC,EAC1B,EAAS,EAAA,eAAe,QAAQ,CAAM,EAAG,CAAM,EAErD,GAAI,EAAS,CACX,IAAM,EAAO,EAAO,KAAK,EAAG,IAC1B,EAAW,EAAY,EAAG,GAAG,IAAW,EAAK,KAAK,IAAI,EAAG,EAAE,OAAO,OAAS,CAAC,CAC9E,EACM,EAAU,EAAS,IAAI,KAAK,IAAI,GAAG,CAAI,CAAC,EACxC,EAAe,EAAG,WAAW,EAAW,EAAO,EAC/C,CAAE,UAAW,EAAI,WACjB,EAAO,EAAO,SAAS,EAAG,IAC9B,EAAE,MAAQ,CAAC,CAAE,MAAO,EAAO,GAAK,KAAM,EAAE,OAAO,KAAM,MAAO,OAAO,EAAE,MAAM,KAAK,CAAE,CAAC,EAAI,CAAC,CAC1F,EAEA,EAAQ,MACL,EAAa,EAAU,GAAgB,EAAO,MAC9C,EAAa,EAAe,GAAW,EAAO,IAC/C,EAAM,MACN,EAAM,OACN,EAAA,kBAAkB,EAAI,IAAI,cAAe,QAAQ,CAAM,EAAG,EAAM,CAAM,CACxE,CACF,MACE,EAAI,UAAU,SAAS,CAAM,EAG/B,EAAO,UAAU,CAAK,CACxB,EAEM,eAAyB,CAC7B,UAAU,EAAE,EACZ,GAAS,KAAK,EACd,EAAI,UAAU,MAAM,EACpB,EAAO,UAAU,IAAI,CACvB,EAEM,IAAO,GAAoE,CAC/E,IAAM,EAAI,EAAI,WACR,EAAM,EAAA,iBAAiB,EAAI,IAAK,EAAO,EAAE,OAAO,KAAM,EAAE,OAAO,GAAG,EAClE,EAAI,EAAA,UAAU,EAAE,MAAO,EAAE,OAAQ,EAAE,MAAM,EAE/C,GAAI,EAAI,EAAI,GAAK,EAAI,EAAI,EAAE,OAAS,EAAI,EAAI,GAAK,EAAI,EAAI,EAAE,OAAQ,OAAO,KAE1E,IAAM,EAAS,EAAA,WAAW,EAAa,EAAI,EAAI,EAAI,EAAG,EAAY,CAAE,EAEpE,OAAO,IAAW,GACd,KACA,CAAE,SAAQ,UAAW,EAAA,cAAc,EAAK,EAAQ,EAAY,EAAI,EAAW,MAAM,CAAE,CACzF,EAEM,YAAe,GAAsB,CACzC,IAAM,EAAS,IAAI,CAAK,EAEpB,EAAQ,SAAS,EAAO,OAAQ,EAAO,UAAW,CAAK,EAClD,GAAa,GAAG,WAAW,CACtC,EAEM,QAAW,GAAsB,CACrC,IAAM,EAAS,EAAO,SAAW,IAAI,CAAK,EACpC,EAAa,GAAU,QAAQ,EAAO,OAAQ,EAAO,UAAW,CAAK,EAEvE,GAAY,EAAO,UAAU,CAAU,CAC7C,EAEM,UAAa,GAAyB,CAC1C,IAAM,EAAO,EAAW,OAAS,EAC3B,EAAO,EAAY,EAAI,EAAO,KAAK,IAAI,EAAG,EAAY,CAAC,EACvD,EAAO,EAAY,EAAI,EAAI,KAAK,IAAI,EAAM,EAAY,CAAC,EACvD,EAAiC,CACrC,UAAW,EACX,UAAW,EACX,WAAY,EACZ,QAAS,EACT,IAAK,EACL,KAAM,CACR,EAEA,GAAI,EAAM,OAAO,EACf,EAAM,eAAe,EACrB,SAAS,EAAO,EAAM,KAAM,EAAG,CAAK,OAC/B,IAAK,EAAM,MAAQ,SAAW,EAAM,MAAQ,MAAQ,GAAa,GAAK,EAAO,QAAS,CAC3F,EAAM,eAAe,EAErB,IAAM,EAAa,QAAQ,EAAW,EAAG,CAAK,EAE1C,GAAY,EAAO,QAAQ,CAAU,CAC3C,MAAW,EAAM,MAAQ,UACvB,WAAW,CAEf,EAEA,MAAO,CAAE,QAAS,UAAW,aAAc,WAAY,WAAY,CACrE,EACC,GAAS,CACR,EAAa,CACf,CACF,CACF"}
|
|
1
|
+
{"version":3,"file":"bar-chart.cjs","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { normalizeCartesianSeries } from '../../core/cartesian-model';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { getMousePosition } from '../../interaction/events';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n ChartEvent,\n ChartHandle,\n Datum,\n SeriesValue,\n XAxisConfig,\n YAxisConfig,\n} from '../../types';\nimport { findCatIdx, findSeriesIdx } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\nimport type { BarScaleContext } from './bar-scale-context';\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<BarSeriesConfig[]> {\n let seriesList = config.series;\n let band: SVGRectElement | null = null;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const sourceData = seriesList.map((series) => series.data);\n const model = normalizeCartesianSeries(seriesList, sourceData);\n const categories = model.domain;\n const allData = model.series.map(({ byKey }) => categories.map((key) => byKey.get(key)));\n const categoryAxis = (axis: XAxisConfig | YAxisConfig) => {\n return {\n ...axis,\n tickFormat: (value: Date | number | string) => {\n const key = String(value);\n const label = model.labels.get(key) ?? value;\n\n return axis.tickFormat ? axis.tickFormat(label) : String(label);\n },\n };\n };\n\n if (categories.length === 0) {\n clearCartesianDom(groups, legend, tooltip);\n band?.remove();\n band = null;\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Axes render by default; `false` opts out. The value axis (x when horizontal, y\n // otherwise) carries gridlines by default and merges over that default, so a partial\n // config (e.g. only `tickFormat`) keeps the gridlines; the category axis defaults to none.\n const xAxisConfig: XAxisConfig | false =\n config.xAxis === false ? false : horizontal ? { grid: true, ...config.xAxis } : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false =\n config.yAxis === false ? false : horizontal ? (config.yAxis ?? {}) : { grid: true, ...config.yAxis };\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((seriesData) => seriesData.some((datum) => (datum?.value ?? 0) < 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((_, categoryIndex) =>\n allData.reduce((sum, seriesData) => sum + Math.max(0, seriesData[categoryIndex]?.value ?? 0), 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flatMap((seriesData) => seriesData.flatMap((datum) => (datum ? [datum.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 (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(valScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (yAxisConfig !== false) {\n const yAxis = categoryAxis(yAxisConfig);\n\n positionAxis(groups.yAxis, yAxis.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, catScale, yAxis, area.height, 'left');\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, valScale, xAxisConfig, area.width, 'bottom');\n }\n } else {\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(valScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n }\n\n if (xAxisConfig !== false) {\n const xAxis = categoryAxis(xAxisConfig);\n\n positionAxis(groups.xAxis, xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, catScale, xAxis, area.width, 'bottom');\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, valScale, yAxisConfig, area.height, 'left');\n }\n }\n\n // Series groups\n // Stacked segments stay square so they join cleanly.\n const themeRadius = stacked\n ? 0\n : Number.parseFloat(getComputedStyle(ctx.svg).getPropertyValue('--prism-bar-radius')) || 0;\n\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 group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const barData = categories.map((key, categoryIndex) => {\n const datum = allData[i]?.[categoryIndex];\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, datum?.value ?? 0);\n\n stackTops[key] = top;\n\n return { base, dash: datum?.dash, key, opacity: datum?.opacity, present: datum !== undefined, y: top };\n }\n\n return {\n base: 0,\n dash: datum?.dash,\n key,\n opacity: datum?.opacity,\n present: datum !== undefined,\n y: datum?.value ?? 0,\n };\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 ?? themeRadius,\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n horizontal,\n seriesCount: seriesList.length,\n seriesIndex: i,\n stacked,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n groups.series.classList.toggle('prism-bars-stacked', stacked);\n\n if (!band || !ctx.chartArea.contains(band)) {\n band = createSvgElement('rect', { 'aria-hidden': 'true', class: 'prism-bar-band', 'pointer-events': 'none' });\n ctx.chartArea.insertBefore(band, groups.series);\n }\n\n band.style.display = 'none';\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const colors = seriesList.map((s, i) => seriesColor(i, s.color));\n const labelOf = (catIdx: number): string => String(model.labels.get(categories[catIdx]) ?? categories[catIdx]);\n const tooltipFormat = typeof config.tooltip === 'object' ? config.tooltip : undefined;\n const keyOf = (catIdx: number): Datum['key'] => model.labels.get(categories[catIdx]) ?? categories[catIdx];\n const titleOf = (catIdx: number): string =>\n tooltipFormat?.titleFormat ? tooltipFormat.titleFormat(keyOf(catIdx)) : labelOf(catIdx);\n const formatValue = tooltipFormat?.valueFormat ?? String;\n let activeCat = -1;\n\n const valuesAt = (catIdx: number): SeriesValue[] =>\n seriesList.map((series, si) => ({ datum: allData[si]?.[catIdx], series }));\n\n const eventAt = (catIdx: number, seriesIdx: number, originalEvent: Event): ChartEvent | null => {\n const values = valuesAt(catIdx);\n const preferred = values[seriesIdx]?.datum ? seriesIdx : values.findIndex((v) => v.datum);\n const datum = values[preferred]?.datum;\n\n return datum ? { datum, originalEvent, series: seriesList[preferred], values } : null;\n };\n\n const setActive = (catIdx: number): void => {\n activeCat = catIdx;\n groups.series.classList.toggle('prism-bars-focused', catIdx >= 0);\n\n for (const group of groups.series.children) {\n for (const [i, rect] of [...group.children].entries())\n rect.classList.toggle('prism-bar--active', i === catIdx);\n }\n\n if (!band) return;\n\n band.style.display = catIdx < 0 ? 'none' : '';\n\n if (catIdx < 0) return;\n\n const start = sc.bandCenter(categories[catIdx]) - catScale.bandwidth() / 2 - catScale.gap() / 2;\n const size = catScale.bandwidth() + catScale.gap();\n const a = chartArea(ctx.dimensions.width, ctx.dimensions.height, ctx.dimensions.margin);\n\n setAttributes(\n band,\n horizontal\n ? { height: size, width: a.width, x: 0, y: start }\n : { height: a.height, width: size, x: start, y: 0 },\n );\n };\n\n const activate = (catIdx: number, seriesIdx: number, originalEvent: Event): void => {\n const event = eventAt(catIdx, seriesIdx, originalEvent);\n\n if (!event) return;\n\n setActive(catIdx);\n\n const values = event.values ?? [];\n const spoken = describeValues(titleOf(catIdx), values, formatValue);\n\n if (tooltip) {\n const tops = values.map((v, si) =>\n stacked ? (stackedTops[si]?.[catIdx] ?? 0) : Math.max(0, v.datum?.value ?? 0),\n );\n const valuePx = valScale.map(Math.max(...tops));\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const { margin } = ctx.dimensions;\n const rows = values.flatMap((v, si) =>\n v.datum\n ? [{ color: colors[si], name: v.series.name, value: formatValue(v.datum.value, v.datum, v.series) }]\n : [],\n );\n\n tooltip.show(\n (horizontal ? valuePx : bandCenterPx) + margin.left,\n (horizontal ? bandCenterPx : valuePx) + margin.top,\n event.datum,\n event.series,\n comparisonContent(ctx.svg.ownerDocument, titleOf(catIdx), rows, spoken),\n );\n } else {\n ctx.announcer.announce(spoken);\n }\n\n config.onHover?.(event);\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hit = (event: MouseEvent): { catIdx: number; seriesIdx: number } | null => {\n const d = ctx.dimensions;\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 null;\n\n const catIdx = findCatIdx(horizontal ? pos.y : pos.x, categories, sc);\n\n return catIdx === -1\n ? null\n : { catIdx, seriesIdx: findSeriesIdx(pos, catIdx, categories, sc, seriesList.length) };\n };\n\n const onMouseMove = (event: MouseEvent) => {\n const target = hit(event);\n\n if (target) activate(target.catIdx, target.seriesIdx, event);\n else if (activeCat >= 0) deactivate();\n };\n\n const onClick = (event: MouseEvent) => {\n const target = config.onClick && hit(event);\n const chartEvent = target && eventAt(target.catIdx, target.seriesIdx, event);\n\n if (chartEvent) config.onClick?.(chartEvent);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const last = categories.length - 1;\n const prev = activeCat < 0 ? last : Math.max(0, activeCat - 1);\n const next = activeCat < 0 ? 0 : Math.min(last, activeCat + 1);\n const target: Record<string, number> = {\n ArrowDown: next,\n ArrowLeft: prev,\n ArrowRight: next,\n ArrowUp: prev,\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n activate(target[event.key], 0, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeCat >= 0 && config.onClick) {\n event.preventDefault();\n\n const chartEvent = eventAt(activeCat, 0, event);\n\n if (chartEvent) config.onClick(chartEvent);\n } else if (event.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"klBA6BA,SAAS,aAAa,EAAgE,CACpF,MAAO,CACL,WAAY,IAAY,sBAAwB,IAAY,qBAC5D,QAAS,IAAY,WAAa,IAAY,oBAChD,CACF,CAIA,SAAgB,eAAe,EAAwB,EAAwD,CAC7G,IAAI,EAAa,EAAO,OACpB,EAA8B,KAElC,OAAO,EAAA,oBACL,EACA,GACC,EAAK,IAAW,CACf,GAAM,CAAE,SAAQ,SAAQ,WAAY,EACpC,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAA,YAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,IAAM,EAAO,EAAI,WACX,EAAO,EAAA,UAAU,EAAK,MAAO,EAAK,OAAQ,EAAK,MAAM,EACrD,EAAa,EAAW,IAAK,GAAW,EAAO,IAAI,EACnD,EAAQ,EAAA,yBAAyB,EAAY,CAAU,EACvD,EAAa,EAAM,OACnB,EAAU,EAAM,OAAO,KAAK,CAAE,WAAY,EAAW,IAAK,GAAQ,EAAM,IAAI,CAAG,CAAC,CAAC,EACjF,aAAgB,IACb,CACL,GAAG,EACH,WAAa,GAAkC,CAC7C,IAAM,EAAM,OAAO,CAAK,EAClB,EAAQ,EAAM,OAAO,IAAI,CAAG,GAAK,EAEvC,OAAO,EAAK,WAAa,EAAK,WAAW,CAAK,EAAI,OAAO,CAAK,CAChE,CACF,GAGF,GAAI,EAAW,SAAW,EAAG,CAC3B,EAAA,kBAAkB,EAAQ,EAAQ,CAAO,EACzC,GAAM,OAAO,EACb,EAAO,KAEP,MACF,CAEA,GAAM,CAAE,aAAY,WAAY,aAAa,EAAO,SAAW,SAAS,EAKlE,EACJ,EAAO,QAAU,GAAQ,GAAQ,EAAa,CAAE,KAAM,GAAM,GAAG,EAAO,KAAM,EAAK,EAAO,OAAS,CAAC,EAC9F,EACJ,EAAO,QAAU,GAAQ,GAAQ,EAAc,EAAO,OAAS,CAAC,EAAK,CAAE,KAAM,GAAM,GAAG,EAAO,KAAM,EAGjG,EACA,EAEJ,GAAI,EAAS,CACP,EAAQ,KAAM,GAAe,EAAW,KAAM,IAAW,GAAO,OAAS,GAAK,CAAC,CAAC,EAMpF,IAAM,EAAO,EAAW,KAAK,EAAG,IAC9B,EAAQ,QAAQ,EAAK,IAAe,EAAM,KAAK,IAAI,EAAG,EAAW,EAAc,EAAE,OAAS,CAAC,EAAG,CAAC,CACjG,EAEA,EAAO,KAAK,IAAI,GAAG,CAAI,EACvB,EAAO,CACT,KAAO,CACL,IAAM,EAAO,EAAQ,QAAS,GAAe,EAAW,QAAS,GAAW,EAAQ,CAAC,EAAM,KAAK,EAAI,CAAC,CAAE,CAAC,EAExG,EAAO,KAAK,IAAI,GAAG,CAAI,EACvB,EAAO,KAAK,IAAI,EAAG,GAAG,CAAI,CAC5B,CAGA,IAAM,EAAW,EACb,EAAA,UAAU,CAAE,OAAQ,EAAY,MAAO,CAAC,EAAG,EAAK,MAAM,CAAE,CAAC,EACzD,EAAA,UAAU,CAAE,OAAQ,EAAY,MAAO,CAAC,EAAG,EAAK,KAAK,CAAE,CAAC,EAEtD,EAAW,EACb,EAAA,YAAY,CAAE,OAAQ,CAAC,EAAM,CAAI,EAAG,MAAO,CAAC,EAAG,EAAK,KAAK,CAAE,CAAC,EAC5D,EAAA,YAAY,CAAE,OAAQ,CAAC,EAAM,CAAI,EAAG,MAAO,CAAC,EAAK,OAAQ,CAAC,CAAE,CAAC,EAE3D,EAA0B,CAAC,EAC3B,EAAY,OAAO,OAAO,IAAI,EAEpC,IAAK,IAAM,KAAO,EAAY,EAAU,GAAO,EAE/C,IAAM,EAAsB,CAC1B,WAAa,GAAQ,EAAS,IAAI,CAAG,EAAI,EAAS,UAAU,EAAI,EAChE,UAAW,EAAS,UAAU,EAC9B,WAAY,EAAS,IAAI,CAAC,EAC1B,aACA,UACA,cACA,WAAY,CACd,EAGA,GAAI,EAAY,CAYd,GAXI,GAAe,EAAY,MAC7B,EAAA,WACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,OACL,WACA,EAAA,aAAa,EAAU,EAAa,EAAA,iBAAiB,EAAa,EAAK,MAAO,QAAQ,CAAC,CACzF,EAGE,IAAgB,GAAO,CACzB,IAAM,EAAQ,aAAa,CAAW,EAEtC,EAAA,aAAa,EAAO,MAAO,EAAM,UAAY,OAAQ,EAAK,MAAO,EAAK,MAAM,EAC5E,EAAA,WAAW,EAAO,MAAO,EAAU,EAAO,EAAK,OAAQ,MAAM,CAC/D,CAEI,IACF,EAAA,aAAa,EAAO,MAAO,EAAY,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EACpF,EAAA,WAAW,EAAO,MAAO,EAAU,EAAa,EAAK,MAAO,QAAQ,EAExE,KAAO,CAYL,GAXI,GAAe,EAAY,MAC7B,EAAA,WACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,MACL,aACA,EAAA,aAAa,EAAU,EAAa,EAAA,iBAAiB,EAAa,EAAK,OAAQ,MAAM,CAAC,CACxF,EAGE,IAAgB,GAAO,CACzB,IAAM,EAAQ,aAAa,CAAW,EAEtC,EAAA,aAAa,EAAO,MAAO,EAAM,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EAC9E,EAAA,WAAW,EAAO,MAAO,EAAU,EAAO,EAAK,MAAO,QAAQ,CAChE,CAEI,IACF,EAAA,aAAa,EAAO,MAAO,EAAY,UAAY,OAAQ,EAAK,MAAO,EAAK,MAAM,EAClF,EAAA,WAAW,EAAO,MAAO,EAAU,EAAa,EAAK,OAAQ,MAAM,EAEvE,CAIA,IAAM,EAAc,EAChB,EACA,OAAO,WAAW,iBAAiB,EAAI,GAAG,CAAC,CAAC,iBAAiB,oBAAoB,CAAC,GAAK,EAE3F,KAAO,EAAO,OAAO,SAAS,OAAS,EAAW,QAAQ,CACxD,IAAM,EAAO,EAAO,OAAO,iBAEvB,GAAM,EAAO,OAAO,YAAY,CAAI,CAC1C,CAEA,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,kBAAmB,CAAC,EAC3D,EAAO,OAAO,YAAY,CAAK,GAGjC,EAAM,aAAa,iBAAkB,EAAA,YAAY,EAAQ,CAAC,CAAC,EAE3D,IAAM,EAAU,EAAW,KAAK,EAAK,IAAkB,CACrD,IAAM,EAAQ,EAAQ,EAAE,GAAG,GAE3B,GAAI,EAAS,CACX,IAAM,EAAO,EAAU,IAAQ,EACzB,EAAM,EAAO,KAAK,IAAI,EAAG,GAAO,OAAS,CAAC,EAIhD,MAFA,GAAU,GAAO,EAEV,CAAE,OAAM,KAAM,GAAO,KAAM,MAAK,QAAS,GAAO,QAAS,QAAS,IAAU,IAAA,GAAW,EAAG,CAAI,CACvG,CAEA,MAAO,CACL,KAAM,EACN,KAAM,GAAO,KACb,MACA,QAAS,GAAO,QAChB,QAAS,IAAU,IAAA,GACnB,EAAG,GAAO,OAAS,CACrB,CACF,CAAC,EAED,EAAY,GAAK,EAAQ,IAAK,GAAM,EAAE,CAAC,EAEvC,IAAM,EAAa,EAAU,EAAQ,IAAK,GAAM,EAAS,IAAI,EAAE,IAAI,CAAC,EAAI,IAAA,GAExE,EAAA,WAAW,EAAO,EAAS,EAAU,EAAU,EAAG,WAAY,CAC5D,aACA,aAAc,EAAO,cAAgB,EACrC,MAAO,EAAA,YAAY,EAAG,EAAO,KAAK,EAClC,eAAgB,EAAI,eACpB,aACA,YAAa,EAAW,OACxB,YAAa,EACb,UACA,WAAY,IAAW,UAAmB,EAAO,UACnD,CAAC,CACH,CAEA,GAAS,KAAK,EACd,EAAO,OAAO,UAAU,OAAO,qBAAsB,CAAO,GAExD,CAAC,GAAQ,CAAC,EAAI,UAAU,SAAS,CAAI,KACvC,EAAO,EAAA,iBAAiB,OAAQ,CAAE,cAAe,OAAQ,MAAO,iBAAkB,iBAAkB,MAAO,CAAC,EAC5G,EAAI,UAAU,aAAa,EAAM,EAAO,MAAM,GAGhD,EAAK,MAAM,QAAU,OAIrB,IAAM,EAAS,EAAW,KAAK,EAAG,IAAM,EAAA,YAAY,EAAG,EAAE,KAAK,CAAC,EACzD,QAAW,GAA2B,OAAO,EAAM,OAAO,IAAI,EAAW,EAAO,GAAK,EAAW,EAAO,EACvG,EAAgB,OAAO,EAAO,SAAY,SAAW,EAAO,QAAU,IAAA,GACtE,MAAS,GAAiC,EAAM,OAAO,IAAI,EAAW,EAAO,GAAK,EAAW,GAC7F,QAAW,GACf,GAAe,YAAc,EAAc,YAAY,MAAM,CAAM,CAAC,EAAI,QAAQ,CAAM,EAClF,EAAc,GAAe,aAAe,OAC9C,EAAY,GAEV,SAAY,GAChB,EAAW,KAAK,EAAQ,KAAQ,CAAE,MAAO,EAAQ,EAAG,GAAG,GAAS,QAAO,EAAE,EAErE,SAAW,EAAgB,EAAmB,IAA4C,CAC9F,IAAM,EAAS,SAAS,CAAM,EACxB,EAAY,EAAO,EAAU,EAAE,MAAQ,EAAY,EAAO,UAAW,GAAM,EAAE,KAAK,EAClF,EAAQ,EAAO,EAAU,EAAE,MAEjC,OAAO,EAAQ,CAAE,QAAO,gBAAe,OAAQ,EAAW,GAAY,QAAO,EAAI,IACnF,EAEM,UAAa,GAAyB,CAC1C,EAAY,EACZ,EAAO,OAAO,UAAU,OAAO,qBAAsB,GAAU,CAAC,EAEhE,IAAK,IAAM,KAAS,EAAO,OAAO,SAChC,IAAK,GAAM,CAAC,EAAG,IAAS,CAAC,GAAG,EAAM,QAAQ,CAAC,CAAC,QAAQ,EAClD,EAAK,UAAU,OAAO,oBAAqB,IAAM,CAAM,EAO3D,GAJI,CAAC,IAEL,EAAK,MAAM,QAAU,EAAS,EAAI,OAAS,GAEvC,EAAS,GAAG,OAEhB,IAAM,EAAQ,EAAG,WAAW,EAAW,EAAO,EAAI,EAAS,UAAU,EAAI,EAAI,EAAS,IAAI,EAAI,EACxF,EAAO,EAAS,UAAU,EAAI,EAAS,IAAI,EAC3C,EAAI,EAAA,UAAU,EAAI,WAAW,MAAO,EAAI,WAAW,OAAQ,EAAI,WAAW,MAAM,EAEtF,EAAA,cACE,EACA,EACI,CAAE,OAAQ,EAAM,MAAO,EAAE,MAAO,EAAG,EAAG,EAAG,CAAM,EAC/C,CAAE,OAAQ,EAAE,OAAQ,MAAO,EAAM,EAAG,EAAO,EAAG,CAAE,CACtD,CACF,EAEM,UAAY,EAAgB,EAAmB,IAA+B,CAClF,IAAM,EAAQ,QAAQ,EAAQ,EAAW,CAAa,EAEtD,GAAI,CAAC,EAAO,OAEZ,UAAU,CAAM,EAEhB,IAAM,EAAS,EAAM,QAAU,CAAC,EAC1B,EAAS,EAAA,eAAe,QAAQ,CAAM,EAAG,EAAQ,CAAW,EAElE,GAAI,EAAS,CACX,IAAM,EAAO,EAAO,KAAK,EAAG,IAC1B,EAAW,EAAY,EAAG,GAAG,IAAW,EAAK,KAAK,IAAI,EAAG,EAAE,OAAO,OAAS,CAAC,CAC9E,EACM,EAAU,EAAS,IAAI,KAAK,IAAI,GAAG,CAAI,CAAC,EACxC,EAAe,EAAG,WAAW,EAAW,EAAO,EAC/C,CAAE,UAAW,EAAI,WACjB,EAAO,EAAO,SAAS,EAAG,IAC9B,EAAE,MACE,CAAC,CAAE,MAAO,EAAO,GAAK,KAAM,EAAE,OAAO,KAAM,MAAO,EAAY,EAAE,MAAM,MAAO,EAAE,MAAO,EAAE,MAAM,CAAE,CAAC,EACjG,CAAC,CACP,EAEA,EAAQ,MACL,EAAa,EAAU,GAAgB,EAAO,MAC9C,EAAa,EAAe,GAAW,EAAO,IAC/C,EAAM,MACN,EAAM,OACN,EAAA,kBAAkB,EAAI,IAAI,cAAe,QAAQ,CAAM,EAAG,EAAM,CAAM,CACxE,CACF,MACE,EAAI,UAAU,SAAS,CAAM,EAG/B,EAAO,UAAU,CAAK,CACxB,EAEM,eAAyB,CAC7B,UAAU,EAAE,EACZ,GAAS,KAAK,EACd,EAAI,UAAU,MAAM,EACpB,EAAO,UAAU,IAAI,CACvB,EAEM,IAAO,GAAoE,CAC/E,IAAM,EAAI,EAAI,WACR,EAAM,EAAA,iBAAiB,EAAI,IAAK,EAAO,EAAE,OAAO,KAAM,EAAE,OAAO,GAAG,EAClE,EAAI,EAAA,UAAU,EAAE,MAAO,EAAE,OAAQ,EAAE,MAAM,EAE/C,GAAI,EAAI,EAAI,GAAK,EAAI,EAAI,EAAE,OAAS,EAAI,EAAI,GAAK,EAAI,EAAI,EAAE,OAAQ,OAAO,KAE1E,IAAM,EAAS,EAAA,WAAW,EAAa,EAAI,EAAI,EAAI,EAAG,EAAY,CAAE,EAEpE,OAAO,IAAW,GACd,KACA,CAAE,SAAQ,UAAW,EAAA,cAAc,EAAK,EAAQ,EAAY,EAAI,EAAW,MAAM,CAAE,CACzF,EAEM,YAAe,GAAsB,CACzC,IAAM,EAAS,IAAI,CAAK,EAEpB,EAAQ,SAAS,EAAO,OAAQ,EAAO,UAAW,CAAK,EAClD,GAAa,GAAG,WAAW,CACtC,EAEM,QAAW,GAAsB,CACrC,IAAM,EAAS,EAAO,SAAW,IAAI,CAAK,EACpC,EAAa,GAAU,QAAQ,EAAO,OAAQ,EAAO,UAAW,CAAK,EAEvE,GAAY,EAAO,UAAU,CAAU,CAC7C,EAEM,UAAa,GAAyB,CAC1C,IAAM,EAAO,EAAW,OAAS,EAC3B,EAAO,EAAY,EAAI,EAAO,KAAK,IAAI,EAAG,EAAY,CAAC,EACvD,EAAO,EAAY,EAAI,EAAI,KAAK,IAAI,EAAM,EAAY,CAAC,EACvD,EAAiC,CACrC,UAAW,EACX,UAAW,EACX,WAAY,EACZ,QAAS,EACT,IAAK,EACL,KAAM,CACR,EAEA,GAAI,EAAM,OAAO,EACf,EAAM,eAAe,EACrB,SAAS,EAAO,EAAM,KAAM,EAAG,CAAK,OAC/B,IAAK,EAAM,MAAQ,SAAW,EAAM,MAAQ,MAAQ,GAAa,GAAK,EAAO,QAAS,CAC3F,EAAM,eAAe,EAErB,IAAM,EAAa,QAAQ,EAAW,EAAG,CAAK,EAE1C,GAAY,EAAO,QAAQ,CAAU,CAC3C,MAAW,EAAM,MAAQ,UACvB,WAAW,CAEf,EAEA,MAAO,CAAE,QAAS,UAAW,aAAc,WAAY,WAAY,CACrE,EACC,GAAS,CACR,EAAa,CACf,CACF,CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/bar/bar-chart.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAGf,WAAW,
|
|
1
|
+
{"version":3,"file":"bar-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/bar/bar-chart.ts"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAGf,WAAW,EAKZ,MAAM,aAAa,CAAC;AAcrB,wBAAgB,cAAc,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,GAAG,WAAW,CAAC,eAAe,EAAE,CAAC,CAiX7G"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{positionAxis as n,renderAxis as r,resolveTickCount as i}from"../../axes/axis.js";import{renderGrid as
|
|
1
|
+
import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{positionAxis as n,renderAxis as r,resolveTickCount as i,resolveTicks as a}from"../../axes/axis.js";import{renderGrid as o}from"../../axes/grid.js";import{linearScale as s}from"../../scales/linear.js";import{describeValues as c}from"../../interaction/announcer.js";import{comparisonContent as l}from"../../interaction/tooltip.js";import{chartArea as u}from"../../core/layout.js";import{clearCartesianDom as d,createChartScaffold as f}from"../../core/chart-scaffold.js";import{seriesDomId as p}from"../../core/series-id.js";import{normalizeCartesianSeries as m}from"../../core/cartesian-model.js";import{getMousePosition as h}from"../../interaction/events.js";import{seriesColor as g}from"../../theme/index.js";import{bandScale as _}from"../../scales/band.js";import{findCatIdx as v,findSeriesIdx as y}from"./bar-hit-test.js";import{renderBars as b}from"./bar-renderer.js";function variantFlags(e){return{horizontal:e===`grouped-horizontal`||e===`stacked-horizontal`,stacked:e===`stacked`||e===`stacked-horizontal`}}function createBarChart(x,S){let C=S.series,w=null;return f(x,S,(f,x)=>{let{groups:T,legend:E,tooltip:D}=f;E?.update(C.map((e,t)=>({color:g(t,e.color),name:e.name})));let O=f.dimensions,k=u(O.width,O.height,O.margin),A=C.map(e=>e.data),j=m(C,A),M=j.domain,N=j.series.map(({byKey:e})=>M.map(t=>e.get(t))),categoryAxis=e=>({...e,tickFormat:t=>{let n=String(t),r=j.labels.get(n)??t;return e.tickFormat?e.tickFormat(r):String(r)}});if(M.length===0){d(T,E,D),w?.remove(),w=null;return}let{horizontal:P,stacked:F}=variantFlags(S.variant??`grouped`),I=S.xAxis===!1?!1:P?{grid:!0,...S.xAxis}:S.xAxis??{},L=S.yAxis===!1?!1:P?S.yAxis??{}:{grid:!0,...S.yAxis},R,z;if(F){N.some(e=>e.some(e=>(e?.value??0)<0));let e=M.map((e,t)=>N.reduce((e,n)=>e+Math.max(0,n[t]?.value??0),0));R=Math.max(...e),z=0}else{let e=N.flatMap(e=>e.flatMap(e=>e?[e.value]:[]));R=Math.max(...e),z=Math.min(0,...e)}let B=_(P?{domain:M,range:[0,k.height]}:{domain:M,range:[0,k.width]}),V=s(P?{domain:[z,R],range:[0,k.width]}:{domain:[z,R],range:[k.height,0]}),H=[],U=Object.create(null);for(let e of M)U[e]=0;let W={bandCenter:e=>B.map(e)+B.bandwidth()/2,bandwidth:B.bandwidth(),baselinePx:V.map(0),horizontal:P,stacked:F,stackedTops:H,valueScale:V};if(P){if(I&&I.grid&&o(T.grid,V,I.grid,k.height,`vertical`,a(V,I,i(I,k.width,`bottom`))),L!==!1){let e=categoryAxis(L);n(T.yAxis,e.position??`left`,k.width,k.height),r(T.yAxis,B,e,k.height,`left`)}I&&(n(T.xAxis,I.position??`bottom`,k.width,k.height),r(T.xAxis,V,I,k.width,`bottom`))}else{if(L&&L.grid&&o(T.grid,V,L.grid,k.width,`horizontal`,a(V,L,i(L,k.height,`left`))),I!==!1){let e=categoryAxis(I);n(T.xAxis,e.position??`bottom`,k.width,k.height),r(T.xAxis,B,e,k.width,`bottom`)}L&&(n(T.yAxis,L.position??`left`,k.width,k.height),r(T.yAxis,V,L,k.height,`left`))}let G=F?0:Number.parseFloat(getComputedStyle(f.svg).getPropertyValue(`--prism-bar-radius`))||0;for(;T.series.children.length>C.length;){let e=T.series.lastElementChild;e&&T.series.removeChild(e)}for(let t=0;t<C.length;t++){let n=C[t],r=T.series.children[t];r||(r=e(`g`,{class:`prism-bar-series`}),T.series.appendChild(r)),r.setAttribute(`data-series-id`,p(n,t));let i=M.map((e,n)=>{let r=N[t]?.[n];if(F){let t=U[e]??0,n=t+Math.max(0,r?.value??0);return U[e]=n,{base:t,dash:r?.dash,key:e,opacity:r?.opacity,present:r!==void 0,y:n}}return{base:0,dash:r?.dash,key:e,opacity:r?.opacity,present:r!==void 0,y:r?.value??0}});H[t]=i.map(e=>e.y);let a=F?i.map(e=>V.map(e.base)):void 0;b(r,i,B,V,W.baselinePx,{baselineYs:a,borderRadius:n.borderRadius??G,color:g(t,n.color),disposalSignal:f.disposalSignal,horizontal:P,seriesCount:C.length,seriesIndex:t,stacked:F,transition:x!==`resize`&&S.transition})}D?.hide(),T.series.classList.toggle(`prism-bars-stacked`,F),(!w||!f.chartArea.contains(w))&&(w=e(`rect`,{"aria-hidden":`true`,class:`prism-bar-band`,"pointer-events":`none`}),f.chartArea.insertBefore(w,T.series)),w.style.display=`none`;let K=C.map((e,t)=>g(t,e.color)),labelOf=e=>String(j.labels.get(M[e])??M[e]),q=typeof S.tooltip==`object`?S.tooltip:void 0,keyOf=e=>j.labels.get(M[e])??M[e],titleOf=e=>q?.titleFormat?q.titleFormat(keyOf(e)):labelOf(e),J=q?.valueFormat??String,Y=-1,valuesAt=e=>C.map((t,n)=>({datum:N[n]?.[e],series:t})),eventAt=(e,t,n)=>{let r=valuesAt(e),i=r[t]?.datum?t:r.findIndex(e=>e.datum),a=r[i]?.datum;return a?{datum:a,originalEvent:n,series:C[i],values:r}:null},setActive=e=>{Y=e,T.series.classList.toggle(`prism-bars-focused`,e>=0);for(let t of T.series.children)for(let[n,r]of[...t.children].entries())r.classList.toggle(`prism-bar--active`,n===e);if(!w||(w.style.display=e<0?`none`:``,e<0))return;let n=W.bandCenter(M[e])-B.bandwidth()/2-B.gap()/2,r=B.bandwidth()+B.gap(),i=u(f.dimensions.width,f.dimensions.height,f.dimensions.margin);t(w,P?{height:r,width:i.width,x:0,y:n}:{height:i.height,width:r,x:n,y:0})},activate=(e,t,n)=>{let r=eventAt(e,t,n);if(!r)return;setActive(e);let i=r.values??[],a=c(titleOf(e),i,J);if(D){let t=i.map((t,n)=>F?H[n]?.[e]??0:Math.max(0,t.datum?.value??0)),n=V.map(Math.max(...t)),o=W.bandCenter(M[e]),{margin:s}=f.dimensions,c=i.flatMap((e,t)=>e.datum?[{color:K[t],name:e.series.name,value:J(e.datum.value,e.datum,e.series)}]:[]);D.show((P?n:o)+s.left,(P?o:n)+s.top,r.datum,r.series,l(f.svg.ownerDocument,titleOf(e),c,a))}else f.announcer.announce(a);S.onHover?.(r)},deactivate=()=>{setActive(-1),D?.hide(),f.announcer.clear(),S.onHover?.(null)},hit=e=>{let t=f.dimensions,n=h(f.svg,e,t.margin.left,t.margin.top),r=u(t.width,t.height,t.margin);if(n.x<0||n.x>r.width||n.y<0||n.y>r.height)return null;let i=v(P?n.y:n.x,M,W);return i===-1?null:{catIdx:i,seriesIdx:y(n,i,M,W,C.length)}},onMouseMove=e=>{let t=hit(e);t?activate(t.catIdx,t.seriesIdx,e):Y>=0&&deactivate()},onClick=e=>{let t=S.onClick&&hit(e),n=t&&eventAt(t.catIdx,t.seriesIdx,e);n&&S.onClick?.(n)},onKeyDown=e=>{let t=M.length-1,n=Y<0?t:Math.max(0,Y-1),r=Y<0?0:Math.min(t,Y+1),i={ArrowDown:r,ArrowLeft:n,ArrowRight:r,ArrowUp:n,End:t,Home:0};if(e.key in i)e.preventDefault(),activate(i[e.key],0,e);else if((e.key===`Enter`||e.key===` `)&&Y>=0&&S.onClick){e.preventDefault();let t=eventAt(Y,0,e);t&&S.onClick(t)}else e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{C=e})}export{createBarChart};
|
|
2
2
|
//# sourceMappingURL=bar-chart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-chart.js","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { positionAxis, renderAxis, resolveTickCount } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { normalizeCartesianSeries } from '../../core/cartesian-model';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { getMousePosition } from '../../interaction/events';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n ChartEvent,\n ChartHandle,\n SeriesValue,\n XAxisConfig,\n YAxisConfig,\n} from '../../types';\nimport { findCatIdx, findSeriesIdx } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\nimport type { BarScaleContext } from './bar-scale-context';\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<BarSeriesConfig[]> {\n let seriesList = config.series;\n let band: SVGRectElement | null = null;\n\n return createChartScaffold(\n container,\n config,\n (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const sourceData = seriesList.map((series) => series.data);\n const model = normalizeCartesianSeries(seriesList, sourceData);\n const categories = model.domain;\n const allData = model.series.map(({ byKey }) => categories.map((key) => byKey.get(key)));\n const categoryAxis = (axis: XAxisConfig | YAxisConfig) => {\n return {\n ...axis,\n tickFormat: (value: Date | number | string) => {\n const key = String(value);\n const label = model.labels.get(key) ?? value;\n\n return axis.tickFormat ? axis.tickFormat(label) : String(label);\n },\n };\n };\n\n if (categories.length === 0) {\n clearCartesianDom(groups, legend, tooltip);\n band?.remove();\n band = null;\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Axes render by default; `false` opts out. The value axis carries gridlines by\n // default, the category axis does not; an explicit config is used verbatim.\n const xAxisConfig: XAxisConfig | false =\n config.xAxis === false ? false : (config.xAxis ?? (horizontal ? { grid: true } : {}));\n const yAxisConfig: YAxisConfig | false =\n config.yAxis === false ? false : (config.yAxis ?? (horizontal ? {} : { grid: true }));\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((seriesData) => seriesData.some((datum) => (datum?.value ?? 0) < 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((_, categoryIndex) =>\n allData.reduce((sum, seriesData) => sum + Math.max(0, seriesData[categoryIndex]?.value ?? 0), 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flatMap((seriesData) => seriesData.flatMap((datum) => (datum ? [datum.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 (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTickCount(xAxisConfig, area.width, 'bottom'),\n );\n }\n\n if (yAxisConfig !== false) {\n const yAxis = categoryAxis(yAxisConfig);\n\n positionAxis(groups.yAxis, yAxis.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, catScale, yAxis, area.height, 'left');\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, valScale, xAxisConfig, area.width, 'bottom');\n }\n } else {\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTickCount(yAxisConfig, area.height, 'left'),\n );\n }\n\n if (xAxisConfig !== false) {\n const xAxis = categoryAxis(xAxisConfig);\n\n positionAxis(groups.xAxis, xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, catScale, xAxis, area.width, 'bottom');\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, valScale, yAxisConfig, area.height, 'left');\n }\n }\n\n // Series groups\n // Stacked segments stay square so they join cleanly.\n const themeRadius = stacked\n ? 0\n : Number.parseFloat(getComputedStyle(ctx.svg).getPropertyValue('--prism-bar-radius')) || 0;\n\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 group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const barData = categories.map((key, categoryIndex) => {\n const datum = allData[i]?.[categoryIndex];\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, datum?.value ?? 0);\n\n stackTops[key] = top;\n\n return { base, dash: datum?.dash, key, opacity: datum?.opacity, present: datum !== undefined, y: top };\n }\n\n return {\n base: 0,\n dash: datum?.dash,\n key,\n opacity: datum?.opacity,\n present: datum !== undefined,\n y: datum?.value ?? 0,\n };\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 ?? themeRadius,\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 groups.series.classList.toggle('prism-bars-stacked', stacked);\n\n if (!band || !ctx.chartArea.contains(band)) {\n band = createSvgElement('rect', { 'aria-hidden': 'true', class: 'prism-bar-band', 'pointer-events': 'none' });\n ctx.chartArea.insertBefore(band, groups.series);\n }\n\n band.style.display = 'none';\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const colors = seriesList.map((s, i) => seriesColor(i, s.color));\n const labelOf = (catIdx: number): string => String(model.labels.get(categories[catIdx]) ?? categories[catIdx]);\n let activeCat = -1;\n\n const valuesAt = (catIdx: number): SeriesValue[] =>\n seriesList.map((series, si) => ({ datum: allData[si]?.[catIdx], series }));\n\n const eventAt = (catIdx: number, seriesIdx: number, originalEvent: Event): ChartEvent | null => {\n const values = valuesAt(catIdx);\n const preferred = values[seriesIdx]?.datum ? seriesIdx : values.findIndex((v) => v.datum);\n const datum = values[preferred]?.datum;\n\n return datum ? { datum, originalEvent, series: seriesList[preferred], values } : null;\n };\n\n const setActive = (catIdx: number): void => {\n activeCat = catIdx;\n groups.series.classList.toggle('prism-bars-focused', catIdx >= 0);\n\n for (const group of groups.series.children) {\n for (const [i, rect] of [...group.children].entries())\n rect.classList.toggle('prism-bar--active', i === catIdx);\n }\n\n if (!band) return;\n\n band.style.display = catIdx < 0 ? 'none' : '';\n\n if (catIdx < 0) return;\n\n const start = sc.bandCenter(categories[catIdx]) - catScale.bandwidth() / 2 - catScale.gap() / 2;\n const size = catScale.bandwidth() + catScale.gap();\n const a = chartArea(ctx.dimensions.width, ctx.dimensions.height, ctx.dimensions.margin);\n\n setAttributes(\n band,\n horizontal\n ? { height: size, width: a.width, x: 0, y: start }\n : { height: a.height, width: size, x: start, y: 0 },\n );\n };\n\n const activate = (catIdx: number, seriesIdx: number, originalEvent: Event): void => {\n const event = eventAt(catIdx, seriesIdx, originalEvent);\n\n if (!event) return;\n\n setActive(catIdx);\n\n const values = event.values ?? [];\n const spoken = describeValues(labelOf(catIdx), values);\n\n if (tooltip) {\n const tops = values.map((v, si) =>\n stacked ? (stackedTops[si]?.[catIdx] ?? 0) : Math.max(0, v.datum?.value ?? 0),\n );\n const valuePx = valScale.map(Math.max(...tops));\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const { margin } = ctx.dimensions;\n const rows = values.flatMap((v, si) =>\n v.datum ? [{ color: colors[si], name: v.series.name, value: String(v.datum.value) }] : [],\n );\n\n tooltip.show(\n (horizontal ? valuePx : bandCenterPx) + margin.left,\n (horizontal ? bandCenterPx : valuePx) + margin.top,\n event.datum,\n event.series,\n comparisonContent(ctx.svg.ownerDocument, labelOf(catIdx), rows, spoken),\n );\n } else {\n ctx.announcer.announce(spoken);\n }\n\n config.onHover?.(event);\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hit = (event: MouseEvent): { catIdx: number; seriesIdx: number } | null => {\n const d = ctx.dimensions;\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 null;\n\n const catIdx = findCatIdx(horizontal ? pos.y : pos.x, categories, sc);\n\n return catIdx === -1\n ? null\n : { catIdx, seriesIdx: findSeriesIdx(pos, catIdx, categories, sc, seriesList.length) };\n };\n\n const onMouseMove = (event: MouseEvent) => {\n const target = hit(event);\n\n if (target) activate(target.catIdx, target.seriesIdx, event);\n else if (activeCat >= 0) deactivate();\n };\n\n const onClick = (event: MouseEvent) => {\n const target = config.onClick && hit(event);\n const chartEvent = target && eventAt(target.catIdx, target.seriesIdx, event);\n\n if (chartEvent) config.onClick?.(chartEvent);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const last = categories.length - 1;\n const prev = activeCat < 0 ? last : Math.max(0, activeCat - 1);\n const next = activeCat < 0 ? 0 : Math.min(last, activeCat + 1);\n const target: Record<string, number> = {\n ArrowDown: next,\n ArrowLeft: prev,\n ArrowRight: next,\n ArrowUp: prev,\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n activate(target[event.key], 0, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeCat >= 0 && config.onClick) {\n event.preventDefault();\n\n const chartEvent = eventAt(activeCat, 0, event);\n\n if (chartEvent) config.onClick(chartEvent);\n } else if (event.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bar-chart.js","names":[],"sources":["../../../src/charts/bar/bar-chart.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { normalizeCartesianSeries } from '../../core/cartesian-model';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { describeValues } from '../../interaction/announcer';\nimport { getMousePosition } from '../../interaction/events';\nimport { comparisonContent } from '../../interaction/tooltip';\nimport { bandScale } from '../../scales/band';\nimport { linearScale } from '../../scales/linear';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport { seriesColor } from '../../theme';\nimport type {\n BarChartConfig,\n BarSeriesConfig,\n BarVariant,\n ChartEvent,\n ChartHandle,\n Datum,\n SeriesValue,\n XAxisConfig,\n YAxisConfig,\n} from '../../types';\nimport { findCatIdx, findSeriesIdx } from './bar-hit-test';\nimport { renderBars } from './bar-renderer';\nimport type { BarScaleContext } from './bar-scale-context';\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<BarSeriesConfig[]> {\n let seriesList = config.series;\n let band: SVGRectElement | null = null;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const area = chartArea(dims.width, dims.height, dims.margin);\n const sourceData = seriesList.map((series) => series.data);\n const model = normalizeCartesianSeries(seriesList, sourceData);\n const categories = model.domain;\n const allData = model.series.map(({ byKey }) => categories.map((key) => byKey.get(key)));\n const categoryAxis = (axis: XAxisConfig | YAxisConfig) => {\n return {\n ...axis,\n tickFormat: (value: Date | number | string) => {\n const key = String(value);\n const label = model.labels.get(key) ?? value;\n\n return axis.tickFormat ? axis.tickFormat(label) : String(label);\n },\n };\n };\n\n if (categories.length === 0) {\n clearCartesianDom(groups, legend, tooltip);\n band?.remove();\n band = null;\n\n return;\n }\n\n const { horizontal, stacked } = variantFlags(config.variant ?? 'grouped');\n\n // Axes render by default; `false` opts out. The value axis (x when horizontal, y\n // otherwise) carries gridlines by default and merges over that default, so a partial\n // config (e.g. only `tickFormat`) keeps the gridlines; the category axis defaults to none.\n const xAxisConfig: XAxisConfig | false =\n config.xAxis === false ? false : horizontal ? { grid: true, ...config.xAxis } : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false =\n config.yAxis === false ? false : horizontal ? (config.yAxis ?? {}) : { grid: true, ...config.yAxis };\n\n // Value domain\n let vMax: number;\n let vMin: number;\n\n if (stacked) {\n if (allData.some((seriesData) => seriesData.some((datum) => (datum?.value ?? 0) < 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((_, categoryIndex) =>\n allData.reduce((sum, seriesData) => sum + Math.max(0, seriesData[categoryIndex]?.value ?? 0), 0),\n );\n\n vMax = Math.max(...sums);\n vMin = 0;\n } else {\n const allY = allData.flatMap((seriesData) => seriesData.flatMap((datum) => (datum ? [datum.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 (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(valScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (yAxisConfig !== false) {\n const yAxis = categoryAxis(yAxisConfig);\n\n positionAxis(groups.yAxis, yAxis.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, catScale, yAxis, area.height, 'left');\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, valScale, xAxisConfig, area.width, 'bottom');\n }\n } else {\n if (yAxisConfig && yAxisConfig.grid) {\n renderGrid(\n groups.grid,\n valScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(valScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n }\n\n if (xAxisConfig !== false) {\n const xAxis = categoryAxis(xAxisConfig);\n\n positionAxis(groups.xAxis, xAxis.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, catScale, xAxis, area.width, 'bottom');\n }\n\n if (yAxisConfig) {\n positionAxis(groups.yAxis, yAxisConfig.position ?? 'left', area.width, area.height);\n renderAxis(groups.yAxis, valScale, yAxisConfig, area.height, 'left');\n }\n }\n\n // Series groups\n // Stacked segments stay square so they join cleanly.\n const themeRadius = stacked\n ? 0\n : Number.parseFloat(getComputedStyle(ctx.svg).getPropertyValue('--prism-bar-radius')) || 0;\n\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 group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const barData = categories.map((key, categoryIndex) => {\n const datum = allData[i]?.[categoryIndex];\n\n if (stacked) {\n const base = stackTops[key] ?? 0;\n const top = base + Math.max(0, datum?.value ?? 0);\n\n stackTops[key] = top;\n\n return { base, dash: datum?.dash, key, opacity: datum?.opacity, present: datum !== undefined, y: top };\n }\n\n return {\n base: 0,\n dash: datum?.dash,\n key,\n opacity: datum?.opacity,\n present: datum !== undefined,\n y: datum?.value ?? 0,\n };\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 ?? themeRadius,\n color: seriesColor(i, series.color),\n disposalSignal: ctx.disposalSignal,\n horizontal,\n seriesCount: seriesList.length,\n seriesIndex: i,\n stacked,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n groups.series.classList.toggle('prism-bars-stacked', stacked);\n\n if (!band || !ctx.chartArea.contains(band)) {\n band = createSvgElement('rect', { 'aria-hidden': 'true', class: 'prism-bar-band', 'pointer-events': 'none' });\n ctx.chartArea.insertBefore(band, groups.series);\n }\n\n band.style.display = 'none';\n\n // ─── Event handlers (close over render-derived state) ─────────────────────\n\n const colors = seriesList.map((s, i) => seriesColor(i, s.color));\n const labelOf = (catIdx: number): string => String(model.labels.get(categories[catIdx]) ?? categories[catIdx]);\n const tooltipFormat = typeof config.tooltip === 'object' ? config.tooltip : undefined;\n const keyOf = (catIdx: number): Datum['key'] => model.labels.get(categories[catIdx]) ?? categories[catIdx];\n const titleOf = (catIdx: number): string =>\n tooltipFormat?.titleFormat ? tooltipFormat.titleFormat(keyOf(catIdx)) : labelOf(catIdx);\n const formatValue = tooltipFormat?.valueFormat ?? String;\n let activeCat = -1;\n\n const valuesAt = (catIdx: number): SeriesValue[] =>\n seriesList.map((series, si) => ({ datum: allData[si]?.[catIdx], series }));\n\n const eventAt = (catIdx: number, seriesIdx: number, originalEvent: Event): ChartEvent | null => {\n const values = valuesAt(catIdx);\n const preferred = values[seriesIdx]?.datum ? seriesIdx : values.findIndex((v) => v.datum);\n const datum = values[preferred]?.datum;\n\n return datum ? { datum, originalEvent, series: seriesList[preferred], values } : null;\n };\n\n const setActive = (catIdx: number): void => {\n activeCat = catIdx;\n groups.series.classList.toggle('prism-bars-focused', catIdx >= 0);\n\n for (const group of groups.series.children) {\n for (const [i, rect] of [...group.children].entries())\n rect.classList.toggle('prism-bar--active', i === catIdx);\n }\n\n if (!band) return;\n\n band.style.display = catIdx < 0 ? 'none' : '';\n\n if (catIdx < 0) return;\n\n const start = sc.bandCenter(categories[catIdx]) - catScale.bandwidth() / 2 - catScale.gap() / 2;\n const size = catScale.bandwidth() + catScale.gap();\n const a = chartArea(ctx.dimensions.width, ctx.dimensions.height, ctx.dimensions.margin);\n\n setAttributes(\n band,\n horizontal\n ? { height: size, width: a.width, x: 0, y: start }\n : { height: a.height, width: size, x: start, y: 0 },\n );\n };\n\n const activate = (catIdx: number, seriesIdx: number, originalEvent: Event): void => {\n const event = eventAt(catIdx, seriesIdx, originalEvent);\n\n if (!event) return;\n\n setActive(catIdx);\n\n const values = event.values ?? [];\n const spoken = describeValues(titleOf(catIdx), values, formatValue);\n\n if (tooltip) {\n const tops = values.map((v, si) =>\n stacked ? (stackedTops[si]?.[catIdx] ?? 0) : Math.max(0, v.datum?.value ?? 0),\n );\n const valuePx = valScale.map(Math.max(...tops));\n const bandCenterPx = sc.bandCenter(categories[catIdx]);\n const { margin } = ctx.dimensions;\n const rows = values.flatMap((v, si) =>\n v.datum\n ? [{ color: colors[si], name: v.series.name, value: formatValue(v.datum.value, v.datum, v.series) }]\n : [],\n );\n\n tooltip.show(\n (horizontal ? valuePx : bandCenterPx) + margin.left,\n (horizontal ? bandCenterPx : valuePx) + margin.top,\n event.datum,\n event.series,\n comparisonContent(ctx.svg.ownerDocument, titleOf(catIdx), rows, spoken),\n );\n } else {\n ctx.announcer.announce(spoken);\n }\n\n config.onHover?.(event);\n };\n\n const deactivate = (): void => {\n setActive(-1);\n tooltip?.hide();\n ctx.announcer.clear();\n config.onHover?.(null);\n };\n\n const hit = (event: MouseEvent): { catIdx: number; seriesIdx: number } | null => {\n const d = ctx.dimensions;\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 null;\n\n const catIdx = findCatIdx(horizontal ? pos.y : pos.x, categories, sc);\n\n return catIdx === -1\n ? null\n : { catIdx, seriesIdx: findSeriesIdx(pos, catIdx, categories, sc, seriesList.length) };\n };\n\n const onMouseMove = (event: MouseEvent) => {\n const target = hit(event);\n\n if (target) activate(target.catIdx, target.seriesIdx, event);\n else if (activeCat >= 0) deactivate();\n };\n\n const onClick = (event: MouseEvent) => {\n const target = config.onClick && hit(event);\n const chartEvent = target && eventAt(target.catIdx, target.seriesIdx, event);\n\n if (chartEvent) config.onClick?.(chartEvent);\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const last = categories.length - 1;\n const prev = activeCat < 0 ? last : Math.max(0, activeCat - 1);\n const next = activeCat < 0 ? 0 : Math.min(last, activeCat + 1);\n const target: Record<string, number> = {\n ArrowDown: next,\n ArrowLeft: prev,\n ArrowRight: next,\n ArrowUp: prev,\n End: last,\n Home: 0,\n };\n\n if (event.key in target) {\n event.preventDefault();\n activate(target[event.key], 0, event);\n } else if ((event.key === 'Enter' || event.key === ' ') && activeCat >= 0 && config.onClick) {\n event.preventDefault();\n\n const chartEvent = eventAt(activeCat, 0, event);\n\n if (chartEvent) config.onClick(chartEvent);\n } else if (event.key === 'Escape') {\n deactivate();\n }\n };\n\n return { onClick, onKeyDown, onMouseLeave: deactivate, onMouseMove };\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require("../../svg/element.cjs"),t=require("../../animation/motion.cjs"),n=require("../../animation/transition.cjs");var
|
|
1
|
+
const e=require("../../svg/element.cjs"),t=require("../../animation/motion.cjs"),n=require("../../animation/transition.cjs"),r=require("../../animation/reveal.cjs");var i=20,a=400,o=new WeakMap;function barsOf(e){return[...e.children].filter(e=>e.classList.contains(`prism-bar`))}function renderBars(s,c,l,u,d,f){o.get(s)?.(),o.delete(s);let p=barsOf(s);for(let e of p.slice(c.length))e.remove();let m=l.bandwidth(),h=f.stacked?m:m/f.seriesCount,g=Math.max(0,h-1),_=f.stacked?0:h*f.seriesIndex,v=f.horizontal??!1,y=p.length===0,b=[],x=[],S=[],C=t.resolveMotion(f.transition,{defaultStagger:y?0:i}),w=C.duration>0,T=Math.min(C.stagger,a/Math.max(1,c.length));for(let t=0;t<c.length;t++){let n=c[t],r=l.map(n.key)+_,i=f.baselineYs?f.baselineYs[t]:d,a=u.map(n.y),o=p[t],m=!o;if(o||(o=e.createSvgElement(`rect`,{class:`prism-bar`}),s.appendChild(o)),o.style.display=n.present?``:`none`,e.setAttributes(o,{opacity:n.opacity,stroke:n.dash?f.color:void 0,"stroke-dasharray":n.dash,"stroke-width":n.dash?1:void 0}),v){let t=Math.max(0,Math.abs(i-a)),n=Math.min(a,i);e.setAttributes(o,{fill:f.color,height:g,rx:f.borderRadius,ry:f.borderRadius,y:r}),y?(e.setAttributes(o,{width:t,x:n}),w&&S.push({anchor:i,height:g,width:t,x:n,y:r})):w?m?(e.setAttributes(o,{width:0,x:i}),b.push({attrs:{width:{from:0,to:t},x:{from:i,to:n}},el:o})):x.push({attrs:{width:{from:Number(o.getAttribute(`width`)??t),to:t},x:{from:Number(o.getAttribute(`x`)??n),to:n}},el:o}):e.setAttributes(o,{width:t,x:n})}else{let t=Math.max(0,Math.abs(i-a)),n=Math.min(a,i);e.setAttributes(o,{fill:f.color,rx:f.borderRadius,ry:f.borderRadius,width:g,x:r}),y?(e.setAttributes(o,{height:t,y:n}),w&&S.push({anchor:i,height:t,width:g,x:r,y:n})):w?m?(e.setAttributes(o,{height:0,y:i}),b.push({attrs:{height:{from:0,to:t},y:{from:i,to:n}},el:o})):x.push({attrs:{height:{from:Number(o.getAttribute(`height`)??t),to:t},y:{from:Number(o.getAttribute(`y`)??n),to:n}},el:o}):e.setAttributes(o,{height:t,y:n})}}if(w){let e=[];y&&S.length>0&&e.push(r.playGrowReveal(s,S,()=>{},C,{axis:v?`x`:`y`,signal:f.disposalSignal,stagger:T})),b.length>0&&e.push(n.animate(b,{...C,stagger:T},void 0,f.disposalSignal)),x.length>0&&e.push(n.animate(x,{...C,stagger:0},void 0,f.disposalSignal)),o.set(s,()=>{for(let t of e)t()})}}exports.renderBars=renderBars;
|
|
2
2
|
//# sourceMappingURL=bar-renderer.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-renderer.cjs","names":[],"sources":["../../../src/charts/bar/bar-renderer.ts"],"sourcesContent":["import { resolveMotion } from '../../animation/motion';\nimport type { AnimationTarget } from '../../animation/transition';\nimport { animate } from '../../animation/transition';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { BandScale, Scale, TransitionOption } from '../../types';\n\nexport interface BarRenderOptions {\n baselineYs?: number[];\n borderRadius: number;\n color: string;\n /** Aborted when the owning chart is disposed: stops in-flight transitions from rescheduling. */\n disposalSignal?: AbortSignal;\n horizontal?: boolean;\n seriesCount: number;\n seriesIndex: number;\n stacked?: boolean;\n transition?: TransitionOption;\n}\n\n/** Per-bar entrance delay; {@link MAX_STAGGER_TOTAL} bounds how long the last bar waits. */\nconst DEFAULT_BAR_STAGGER = 20;\n/** Upper bound on the total staggered delay a bar chart may add, whatever the per-bar value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeBarAnimations = new WeakMap<SVGGElement, () => void>();\n\nexport function renderBars(\n parent: SVGGElement,\n data: { base: number; dash?: string; key: string; opacity?: number; present: boolean; y: number }[],\n xScale: BandScale,\n yScale: Scale<number>,\n baselineY: number,\n options: BarRenderOptions,\n): void {\n while (parent.children.length > data.length) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n const bandwidth = xScale.bandwidth();\n const barBand = options.stacked ? bandwidth : bandwidth / options.seriesCount;\n const offset = options.stacked ? 0 : barBand * options.seriesIndex;\n const horizontal = options.horizontal ?? false;\n\n const enterTargets: AnimationTarget[] = [];\n const updateTargets: AnimationTarget[] = [];\n const motion = resolveMotion(options.transition, { defaultStagger: DEFAULT_BAR_STAGGER });\n const animateBars = motion.duration > 0;\n // A long category axis must not stretch the entrance past ~400 ms of added delay.\n const enterStagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, data.length));\n\n for (let i = 0; i < data.length; i++) {\n const d = data[i];\n const bandPos = xScale.map(d.key) + offset;\n const barBaselineY = options.baselineYs ? options.baselineYs[i] : baselineY;\n const valuePx = yScale.map(d.y);\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n const isNew = !rect;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-bar' });\n parent.appendChild(rect);\n }\n\n rect.style.display = d.present ? '' : 'none';\n\n // Presentation attributes (not inline styles) so CSS interaction states\n // like the focus-dim rule keep winning over per-datum styling.\n setAttributes(rect, {\n opacity: d.opacity,\n stroke: d.dash ? options.color : undefined,\n 'stroke-dasharray': d.dash,\n 'stroke-width': d.dash ? 1 : undefined,\n });\n\n if (horizontal) {\n // Horizontal: category on Y axis, value on X axis\n // baselineY here is actually the baseline X (yScale.map(0) in value-space mapped to screen X)\n const finalWidth = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalX = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n height: Math.max(0, barBand - 1),\n rx: options.borderRadius,\n ry: options.borderRadius,\n y: bandPos,\n });\n\n if (animateBars) {\n if (isNew) {\n setAttributes(rect, { width: 0, x: barBaselineY });\n enterTargets.push({\n attrs: { width: { from: 0, to: finalWidth }, x: { from: barBaselineY, to: finalX } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n width: { from: Number(rect.getAttribute('width') ?? finalWidth), to: finalWidth },\n x: { from: Number(rect.getAttribute('x') ?? finalX), to: finalX },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { width: finalWidth, x: finalX });\n }\n } else {\n // Vertical (default)\n const finalHeight = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalY = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n rx: options.borderRadius,\n ry: options.borderRadius,\n width: Math.max(0, barBand - 1),\n x: bandPos,\n });\n\n if (animateBars) {\n if (isNew) {\n setAttributes(rect, { height: 0, y: barBaselineY });\n enterTargets.push({\n attrs: { height: { from: 0, to: finalHeight }, y: { from: barBaselineY, to: finalY } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n height: { from: Number(rect.getAttribute('height') ?? finalHeight), to: finalHeight },\n y: { from: Number(rect.getAttribute('y') ?? finalY), to: finalY },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { height: finalHeight, y: finalY });\n }\n }\n }\n\n if (animateBars) {\n activeBarAnimations.get(parent)?.();\n\n const cancels: (() => void)[] = [];\n\n if (enterTargets.length > 0) {\n cancels.push(animate(enterTargets, { ...motion, stagger: enterStagger }, undefined, options.disposalSignal));\n }\n\n if (updateTargets.length > 0) {\n cancels.push(animate(updateTargets, { ...motion, stagger: 0 }, undefined, options.disposalSignal));\n }\n\n activeBarAnimations.set(parent, () => {\n for (const cancel of cancels) cancel();\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bar-renderer.cjs","names":[],"sources":["../../../src/charts/bar/bar-renderer.ts"],"sourcesContent":["import { resolveMotion } from '../../animation/motion';\nimport { type GrowRevealLane, playGrowReveal } from '../../animation/reveal';\nimport type { AnimationTarget } from '../../animation/transition';\nimport { animate } from '../../animation/transition';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { BandScale, Scale, TransitionOption } from '../../types';\n\nexport interface BarRenderOptions {\n baselineYs?: number[];\n borderRadius: number;\n color: string;\n /** Aborted when the owning chart is disposed: stops in-flight transitions from rescheduling. */\n disposalSignal?: AbortSignal;\n horizontal?: boolean;\n seriesCount: number;\n seriesIndex: number;\n stacked?: boolean;\n transition?: TransitionOption;\n}\n\n/** Preserve the stagger for bars inserted by a data update, not the initial entrance. */\nconst DEFAULT_NEW_BAR_STAGGER = 20;\n/** Upper bound on the total staggered delay a bar chart may add, whatever the per-bar value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeBarAnimations = new WeakMap<SVGGElement, () => void>();\n\n/**\n * The group's bars in data order. Queried by class rather than by `children` index\n * because a mount reveal injects a `<defs>` into the same group.\n */\nfunction barsOf(parent: SVGGElement): SVGRectElement[] {\n return [...parent.children].filter((child): child is SVGRectElement => child.classList.contains('prism-bar'));\n}\n\nexport function renderBars(\n parent: SVGGElement,\n data: { base: number; dash?: string; key: string; opacity?: number; present: boolean; y: number }[],\n xScale: BandScale,\n yScale: Scale<number>,\n baselineY: number,\n options: BarRenderOptions,\n): void {\n activeBarAnimations.get(parent)?.();\n activeBarAnimations.delete(parent);\n const existingBars = barsOf(parent);\n\n for (const extra of existingBars.slice(data.length)) extra.remove();\n\n const bandwidth = xScale.bandwidth();\n const barBand = options.stacked ? bandwidth : bandwidth / options.seriesCount;\n const bandSize = Math.max(0, barBand - 1);\n const offset = options.stacked ? 0 : barBand * options.seriesIndex;\n const horizontal = options.horizontal ?? false;\n // A group with no bars yet is mounting: every bar enters together through a grow\n // reveal. A group that already has bars updates in place (with per-bar attr tweens).\n const isMount = existingBars.length === 0;\n\n const enterTargets: AnimationTarget[] = [];\n const updateTargets: AnimationTarget[] = [];\n const lanes: GrowRevealLane[] = [];\n const motion = resolveMotion(options.transition, { defaultStagger: isMount ? 0 : DEFAULT_NEW_BAR_STAGGER });\n const animateBars = motion.duration > 0;\n // A long category axis must not stretch the entrance past ~400 ms of added delay.\n const enterStagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, data.length));\n\n for (let i = 0; i < data.length; i++) {\n const d = data[i];\n const bandPos = xScale.map(d.key) + offset;\n const barBaselineY = options.baselineYs ? options.baselineYs[i] : baselineY;\n const valuePx = yScale.map(d.y);\n\n let rect = existingBars[i];\n\n const isNew = !rect;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-bar' });\n parent.appendChild(rect);\n }\n\n rect.style.display = d.present ? '' : 'none';\n\n // Presentation attributes (not inline styles) so CSS interaction states\n // like the focus-dim rule keep winning over per-datum styling.\n setAttributes(rect, {\n opacity: d.opacity,\n stroke: d.dash ? options.color : undefined,\n 'stroke-dasharray': d.dash,\n 'stroke-width': d.dash ? 1 : undefined,\n });\n\n if (horizontal) {\n // Horizontal: category on Y axis, value on X axis\n // baselineY here is actually the baseline X (yScale.map(0) in value-space mapped to screen X)\n const finalWidth = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalX = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n height: bandSize,\n rx: options.borderRadius,\n ry: options.borderRadius,\n y: bandPos,\n });\n\n if (isMount) {\n // Final geometry now; the grow reveal below uncovers it lane by lane.\n setAttributes(rect, { width: finalWidth, x: finalX });\n\n if (animateBars) {\n lanes.push({ anchor: barBaselineY, height: bandSize, width: finalWidth, x: finalX, y: bandPos });\n }\n } else if (animateBars) {\n if (isNew) {\n setAttributes(rect, { width: 0, x: barBaselineY });\n enterTargets.push({\n attrs: { width: { from: 0, to: finalWidth }, x: { from: barBaselineY, to: finalX } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n width: { from: Number(rect.getAttribute('width') ?? finalWidth), to: finalWidth },\n x: { from: Number(rect.getAttribute('x') ?? finalX), to: finalX },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { width: finalWidth, x: finalX });\n }\n } else {\n // Vertical (default)\n const finalHeight = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalY = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n rx: options.borderRadius,\n ry: options.borderRadius,\n width: bandSize,\n x: bandPos,\n });\n\n if (isMount) {\n // Final geometry now; the grow reveal below uncovers it lane by lane, so a\n // rounded bar never renders as a corner-clamped 1-3 px sliver mid-grow.\n setAttributes(rect, { height: finalHeight, y: finalY });\n\n if (animateBars) {\n lanes.push({ anchor: barBaselineY, height: finalHeight, width: bandSize, x: bandPos, y: finalY });\n }\n } else if (animateBars) {\n if (isNew) {\n setAttributes(rect, { height: 0, y: barBaselineY });\n enterTargets.push({\n attrs: { height: { from: 0, to: finalHeight }, y: { from: barBaselineY, to: finalY } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n height: { from: Number(rect.getAttribute('height') ?? finalHeight), to: finalHeight },\n y: { from: Number(rect.getAttribute('y') ?? finalY), to: finalY },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { height: finalHeight, y: finalY });\n }\n }\n }\n\n if (animateBars) {\n const cancels: (() => void)[] = [];\n\n if (isMount && lanes.length > 0) {\n cancels.push(\n playGrowReveal(parent, lanes, () => {}, motion, {\n axis: horizontal ? 'x' : 'y',\n signal: options.disposalSignal,\n stagger: enterStagger,\n }),\n );\n }\n\n if (enterTargets.length > 0) {\n cancels.push(animate(enterTargets, { ...motion, stagger: enterStagger }, undefined, options.disposalSignal));\n }\n\n if (updateTargets.length > 0) {\n cancels.push(animate(updateTargets, { ...motion, stagger: 0 }, undefined, options.disposalSignal));\n }\n\n activeBarAnimations.set(parent, () => {\n for (const cancel of cancels) cancel();\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/bar/bar-renderer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bar-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/bar/bar-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEtE,MAAM,WAAW,gBAAgB;IAC/B,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,gGAAgG;IAChG,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAiBD,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,EACnG,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EACrB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,gBAAgB,GACxB,IAAI,CA8JN"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveMotion as n}from"../../animation/motion.js";import{animate as r}from"../../animation/transition.js";var
|
|
1
|
+
import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveMotion as n}from"../../animation/motion.js";import{animate as r}from"../../animation/transition.js";import{playGrowReveal as i}from"../../animation/reveal.js";var a=20,o=400,s=new WeakMap;function barsOf(e){return[...e.children].filter(e=>e.classList.contains(`prism-bar`))}function renderBars(c,l,u,d,f,p){s.get(c)?.(),s.delete(c);let m=barsOf(c);for(let e of m.slice(l.length))e.remove();let h=u.bandwidth(),g=p.stacked?h:h/p.seriesCount,_=Math.max(0,g-1),v=p.stacked?0:g*p.seriesIndex,y=p.horizontal??!1,b=m.length===0,x=[],S=[],C=[],w=n(p.transition,{defaultStagger:b?0:a}),T=w.duration>0,E=Math.min(w.stagger,o/Math.max(1,l.length));for(let n=0;n<l.length;n++){let r=l[n],i=u.map(r.key)+v,a=p.baselineYs?p.baselineYs[n]:f,o=d.map(r.y),s=m[n],h=!s;if(s||(s=e(`rect`,{class:`prism-bar`}),c.appendChild(s)),s.style.display=r.present?``:`none`,t(s,{opacity:r.opacity,stroke:r.dash?p.color:void 0,"stroke-dasharray":r.dash,"stroke-width":r.dash?1:void 0}),y){let e=Math.max(0,Math.abs(a-o)),n=Math.min(o,a);t(s,{fill:p.color,height:_,rx:p.borderRadius,ry:p.borderRadius,y:i}),b?(t(s,{width:e,x:n}),T&&C.push({anchor:a,height:_,width:e,x:n,y:i})):T?h?(t(s,{width:0,x:a}),x.push({attrs:{width:{from:0,to:e},x:{from:a,to:n}},el:s})):S.push({attrs:{width:{from:Number(s.getAttribute(`width`)??e),to:e},x:{from:Number(s.getAttribute(`x`)??n),to:n}},el:s}):t(s,{width:e,x:n})}else{let e=Math.max(0,Math.abs(a-o)),n=Math.min(o,a);t(s,{fill:p.color,rx:p.borderRadius,ry:p.borderRadius,width:_,x:i}),b?(t(s,{height:e,y:n}),T&&C.push({anchor:a,height:e,width:_,x:i,y:n})):T?h?(t(s,{height:0,y:a}),x.push({attrs:{height:{from:0,to:e},y:{from:a,to:n}},el:s})):S.push({attrs:{height:{from:Number(s.getAttribute(`height`)??e),to:e},y:{from:Number(s.getAttribute(`y`)??n),to:n}},el:s}):t(s,{height:e,y:n})}}if(T){let e=[];b&&C.length>0&&e.push(i(c,C,()=>{},w,{axis:y?`x`:`y`,signal:p.disposalSignal,stagger:E})),x.length>0&&e.push(r(x,{...w,stagger:E},void 0,p.disposalSignal)),S.length>0&&e.push(r(S,{...w,stagger:0},void 0,p.disposalSignal)),s.set(c,()=>{for(let t of e)t()})}}export{renderBars};
|
|
2
2
|
//# sourceMappingURL=bar-renderer.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bar-renderer.js","names":[],"sources":["../../../src/charts/bar/bar-renderer.ts"],"sourcesContent":["import { resolveMotion } from '../../animation/motion';\nimport type { AnimationTarget } from '../../animation/transition';\nimport { animate } from '../../animation/transition';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { BandScale, Scale, TransitionOption } from '../../types';\n\nexport interface BarRenderOptions {\n baselineYs?: number[];\n borderRadius: number;\n color: string;\n /** Aborted when the owning chart is disposed: stops in-flight transitions from rescheduling. */\n disposalSignal?: AbortSignal;\n horizontal?: boolean;\n seriesCount: number;\n seriesIndex: number;\n stacked?: boolean;\n transition?: TransitionOption;\n}\n\n/** Per-bar entrance delay; {@link MAX_STAGGER_TOTAL} bounds how long the last bar waits. */\nconst DEFAULT_BAR_STAGGER = 20;\n/** Upper bound on the total staggered delay a bar chart may add, whatever the per-bar value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeBarAnimations = new WeakMap<SVGGElement, () => void>();\n\nexport function renderBars(\n parent: SVGGElement,\n data: { base: number; dash?: string; key: string; opacity?: number; present: boolean; y: number }[],\n xScale: BandScale,\n yScale: Scale<number>,\n baselineY: number,\n options: BarRenderOptions,\n): void {\n while (parent.children.length > data.length) {\n const last = parent.lastElementChild;\n\n if (last) parent.removeChild(last);\n }\n\n const bandwidth = xScale.bandwidth();\n const barBand = options.stacked ? bandwidth : bandwidth / options.seriesCount;\n const offset = options.stacked ? 0 : barBand * options.seriesIndex;\n const horizontal = options.horizontal ?? false;\n\n const enterTargets: AnimationTarget[] = [];\n const updateTargets: AnimationTarget[] = [];\n const motion = resolveMotion(options.transition, { defaultStagger: DEFAULT_BAR_STAGGER });\n const animateBars = motion.duration > 0;\n // A long category axis must not stretch the entrance past ~400 ms of added delay.\n const enterStagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, data.length));\n\n for (let i = 0; i < data.length; i++) {\n const d = data[i];\n const bandPos = xScale.map(d.key) + offset;\n const barBaselineY = options.baselineYs ? options.baselineYs[i] : baselineY;\n const valuePx = yScale.map(d.y);\n\n let rect = parent.children[i] as SVGRectElement | undefined;\n\n const isNew = !rect;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-bar' });\n parent.appendChild(rect);\n }\n\n rect.style.display = d.present ? '' : 'none';\n\n // Presentation attributes (not inline styles) so CSS interaction states\n // like the focus-dim rule keep winning over per-datum styling.\n setAttributes(rect, {\n opacity: d.opacity,\n stroke: d.dash ? options.color : undefined,\n 'stroke-dasharray': d.dash,\n 'stroke-width': d.dash ? 1 : undefined,\n });\n\n if (horizontal) {\n // Horizontal: category on Y axis, value on X axis\n // baselineY here is actually the baseline X (yScale.map(0) in value-space mapped to screen X)\n const finalWidth = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalX = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n height: Math.max(0, barBand - 1),\n rx: options.borderRadius,\n ry: options.borderRadius,\n y: bandPos,\n });\n\n if (animateBars) {\n if (isNew) {\n setAttributes(rect, { width: 0, x: barBaselineY });\n enterTargets.push({\n attrs: { width: { from: 0, to: finalWidth }, x: { from: barBaselineY, to: finalX } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n width: { from: Number(rect.getAttribute('width') ?? finalWidth), to: finalWidth },\n x: { from: Number(rect.getAttribute('x') ?? finalX), to: finalX },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { width: finalWidth, x: finalX });\n }\n } else {\n // Vertical (default)\n const finalHeight = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalY = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n rx: options.borderRadius,\n ry: options.borderRadius,\n width: Math.max(0, barBand - 1),\n x: bandPos,\n });\n\n if (animateBars) {\n if (isNew) {\n setAttributes(rect, { height: 0, y: barBaselineY });\n enterTargets.push({\n attrs: { height: { from: 0, to: finalHeight }, y: { from: barBaselineY, to: finalY } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n height: { from: Number(rect.getAttribute('height') ?? finalHeight), to: finalHeight },\n y: { from: Number(rect.getAttribute('y') ?? finalY), to: finalY },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { height: finalHeight, y: finalY });\n }\n }\n }\n\n if (animateBars) {\n activeBarAnimations.get(parent)?.();\n\n const cancels: (() => void)[] = [];\n\n if (enterTargets.length > 0) {\n cancels.push(animate(enterTargets, { ...motion, stagger: enterStagger }, undefined, options.disposalSignal));\n }\n\n if (updateTargets.length > 0) {\n cancels.push(animate(updateTargets, { ...motion, stagger: 0 }, undefined, options.disposalSignal));\n }\n\n activeBarAnimations.set(parent, () => {\n for (const cancel of cancels) cancel();\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"bar-renderer.js","names":[],"sources":["../../../src/charts/bar/bar-renderer.ts"],"sourcesContent":["import { resolveMotion } from '../../animation/motion';\nimport { type GrowRevealLane, playGrowReveal } from '../../animation/reveal';\nimport type { AnimationTarget } from '../../animation/transition';\nimport { animate } from '../../animation/transition';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { BandScale, Scale, TransitionOption } from '../../types';\n\nexport interface BarRenderOptions {\n baselineYs?: number[];\n borderRadius: number;\n color: string;\n /** Aborted when the owning chart is disposed: stops in-flight transitions from rescheduling. */\n disposalSignal?: AbortSignal;\n horizontal?: boolean;\n seriesCount: number;\n seriesIndex: number;\n stacked?: boolean;\n transition?: TransitionOption;\n}\n\n/** Preserve the stagger for bars inserted by a data update, not the initial entrance. */\nconst DEFAULT_NEW_BAR_STAGGER = 20;\n/** Upper bound on the total staggered delay a bar chart may add, whatever the per-bar value. */\nconst MAX_STAGGER_TOTAL = 400;\n\nconst activeBarAnimations = new WeakMap<SVGGElement, () => void>();\n\n/**\n * The group's bars in data order. Queried by class rather than by `children` index\n * because a mount reveal injects a `<defs>` into the same group.\n */\nfunction barsOf(parent: SVGGElement): SVGRectElement[] {\n return [...parent.children].filter((child): child is SVGRectElement => child.classList.contains('prism-bar'));\n}\n\nexport function renderBars(\n parent: SVGGElement,\n data: { base: number; dash?: string; key: string; opacity?: number; present: boolean; y: number }[],\n xScale: BandScale,\n yScale: Scale<number>,\n baselineY: number,\n options: BarRenderOptions,\n): void {\n activeBarAnimations.get(parent)?.();\n activeBarAnimations.delete(parent);\n const existingBars = barsOf(parent);\n\n for (const extra of existingBars.slice(data.length)) extra.remove();\n\n const bandwidth = xScale.bandwidth();\n const barBand = options.stacked ? bandwidth : bandwidth / options.seriesCount;\n const bandSize = Math.max(0, barBand - 1);\n const offset = options.stacked ? 0 : barBand * options.seriesIndex;\n const horizontal = options.horizontal ?? false;\n // A group with no bars yet is mounting: every bar enters together through a grow\n // reveal. A group that already has bars updates in place (with per-bar attr tweens).\n const isMount = existingBars.length === 0;\n\n const enterTargets: AnimationTarget[] = [];\n const updateTargets: AnimationTarget[] = [];\n const lanes: GrowRevealLane[] = [];\n const motion = resolveMotion(options.transition, { defaultStagger: isMount ? 0 : DEFAULT_NEW_BAR_STAGGER });\n const animateBars = motion.duration > 0;\n // A long category axis must not stretch the entrance past ~400 ms of added delay.\n const enterStagger = Math.min(motion.stagger, MAX_STAGGER_TOTAL / Math.max(1, data.length));\n\n for (let i = 0; i < data.length; i++) {\n const d = data[i];\n const bandPos = xScale.map(d.key) + offset;\n const barBaselineY = options.baselineYs ? options.baselineYs[i] : baselineY;\n const valuePx = yScale.map(d.y);\n\n let rect = existingBars[i];\n\n const isNew = !rect;\n\n if (!rect) {\n rect = createSvgElement('rect', { class: 'prism-bar' });\n parent.appendChild(rect);\n }\n\n rect.style.display = d.present ? '' : 'none';\n\n // Presentation attributes (not inline styles) so CSS interaction states\n // like the focus-dim rule keep winning over per-datum styling.\n setAttributes(rect, {\n opacity: d.opacity,\n stroke: d.dash ? options.color : undefined,\n 'stroke-dasharray': d.dash,\n 'stroke-width': d.dash ? 1 : undefined,\n });\n\n if (horizontal) {\n // Horizontal: category on Y axis, value on X axis\n // baselineY here is actually the baseline X (yScale.map(0) in value-space mapped to screen X)\n const finalWidth = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalX = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n height: bandSize,\n rx: options.borderRadius,\n ry: options.borderRadius,\n y: bandPos,\n });\n\n if (isMount) {\n // Final geometry now; the grow reveal below uncovers it lane by lane.\n setAttributes(rect, { width: finalWidth, x: finalX });\n\n if (animateBars) {\n lanes.push({ anchor: barBaselineY, height: bandSize, width: finalWidth, x: finalX, y: bandPos });\n }\n } else if (animateBars) {\n if (isNew) {\n setAttributes(rect, { width: 0, x: barBaselineY });\n enterTargets.push({\n attrs: { width: { from: 0, to: finalWidth }, x: { from: barBaselineY, to: finalX } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n width: { from: Number(rect.getAttribute('width') ?? finalWidth), to: finalWidth },\n x: { from: Number(rect.getAttribute('x') ?? finalX), to: finalX },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { width: finalWidth, x: finalX });\n }\n } else {\n // Vertical (default)\n const finalHeight = Math.max(0, Math.abs(barBaselineY - valuePx));\n const finalY = Math.min(valuePx, barBaselineY);\n\n setAttributes(rect, {\n fill: options.color,\n rx: options.borderRadius,\n ry: options.borderRadius,\n width: bandSize,\n x: bandPos,\n });\n\n if (isMount) {\n // Final geometry now; the grow reveal below uncovers it lane by lane, so a\n // rounded bar never renders as a corner-clamped 1-3 px sliver mid-grow.\n setAttributes(rect, { height: finalHeight, y: finalY });\n\n if (animateBars) {\n lanes.push({ anchor: barBaselineY, height: finalHeight, width: bandSize, x: bandPos, y: finalY });\n }\n } else if (animateBars) {\n if (isNew) {\n setAttributes(rect, { height: 0, y: barBaselineY });\n enterTargets.push({\n attrs: { height: { from: 0, to: finalHeight }, y: { from: barBaselineY, to: finalY } },\n el: rect,\n });\n } else {\n updateTargets.push({\n attrs: {\n height: { from: Number(rect.getAttribute('height') ?? finalHeight), to: finalHeight },\n y: { from: Number(rect.getAttribute('y') ?? finalY), to: finalY },\n },\n el: rect,\n });\n }\n } else {\n setAttributes(rect, { height: finalHeight, y: finalY });\n }\n }\n }\n\n if (animateBars) {\n const cancels: (() => void)[] = [];\n\n if (isMount && lanes.length > 0) {\n cancels.push(\n playGrowReveal(parent, lanes, () => {}, motion, {\n axis: horizontal ? 'x' : 'y',\n signal: options.disposalSignal,\n stagger: enterStagger,\n }),\n );\n }\n\n if (enterTargets.length > 0) {\n cancels.push(animate(enterTargets, { ...motion, stagger: enterStagger }, undefined, options.disposalSignal));\n }\n\n if (updateTargets.length > 0) {\n cancels.push(animate(updateTargets, { ...motion, stagger: 0 }, undefined, options.disposalSignal));\n }\n\n activeBarAnimations.set(parent, () => {\n for (const cancel of cancels) cancel();\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
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("../../core/series-id.cjs"),s=require("../../interaction/crosshair.cjs"),c=require("../../interaction/series-interaction.cjs"),l=require("../../theme/index.cjs"),u=require("./line-renderer.cjs");function createLineChart(d,f){let p=null,m=null,h=null,g=f.series;return a.createChartScaffold(d,f,d=>{let{groups:
|
|
1
|
+
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("../../core/series-id.cjs"),s=require("../../interaction/crosshair.cjs"),c=require("../../interaction/series-interaction.cjs"),l=require("../../theme/index.cjs"),u=require("./line-renderer.cjs");function createLineChart(d,f){let p=null,m=null,h=null,g=f.series;return a.createChartScaffold(d,f,(d,_)=>{let{groups:v,legend:y,tooltip:b}=d;y?.update(g.map((e,t)=>({color:l.seriesColor(t,e.color),name:e.name})));let x=d.dimensions,S=g.some(e=>e.yAxis===`right`),C=g.some(e=>e.yAxis!==`right`&&e.data.length>0),w={...i.resolveMargin(f.margin),right:f.margin?.right??(S?f.rightYAxis?.label?72:50:i.resolveMargin(f.margin).right)},T=i.chartArea(x.width,x.height,w),E=g.map(e=>e.data),D=E.flat().map(e=>e.key),O=g.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),k=g.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(D.length===0){a.clearCartesianDom(v,y,b,p),m?.replaceChildren(),h?.replaceChildren();return}f.crosshair&&!p&&(p=s.createCrosshair(d.chartArea,f.crosshair));let A=r.buildXScale(D,T.width),j=r.buildYScale(O,T.height),M=r.buildYScale(k,T.height),N=f.xAxis===!1?!1:f.xAxis??{},P=f.yAxis!==!1&&{grid:!0,...f.yAxis};if(P&&P.grid&&(!S||C)?n.renderGrid(v.grid,j,P.grid,T.width,`horizontal`,t.resolveTicks(j,P,t.resolveTickCount(P,T.height,`left`))):v.grid.replaceChildren(),N&&N.grid&&n.renderGrid(v.grid,A,N.grid,T.height,`vertical`,t.resolveTicks(A,N,t.resolveTickCount(N,T.width,`bottom`))),N?(t.positionAxis(v.xAxis,N.position??`bottom`,T.width,T.height),t.renderAxis(v.xAxis,A,N,T.width,`bottom`)):v.xAxis.replaceChildren(),P&&(!S||C)){let e={...P,position:S?`left`:P.position??`left`};t.positionAxis(v.yAxis,e.position,T.width,T.height),t.renderAxis(v.yAxis,j,e,T.height,`left`)}else v.yAxis.replaceChildren();if(S){h||(h=e.createSvgElement(`g`,{class:`prism-y-axis-right`}),d.chartArea.appendChild(h));let n={...f.rightYAxis,position:`right`};t.positionAxis(h,`right`,T.width,T.height),t.renderAxis(h,M,n,T.height,`right`)}else h?.replaceChildren();for(;v.series.children.length>g.length;)v.series.removeChild(v.series.lastChild);let F=[];for(let t=0;t<g.length;t++){let n=g[t],r=v.series.children[t];r||(r=e.createSvgElement(`g`,{class:`prism-line-series`}),v.series.appendChild(r)),r.setAttribute(`data-series-id`,o.seriesDomId(n,t));let i=n.yAxis===`right`?M:j,a=u.computePoints(E[t],A,i);F.push(a),u.renderLine(r,a,{bounds:{height:T.height,width:T.width},color:l.seriesColor(t,n.color),curve:n.curve??`linear`,disposalSignal:d.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:_!==`resize`&&f.transition})}return b?.hide(),m=c.ensureMarkerGroup(d.chartArea,m),c.createSeriesInteraction({announcer:d.announcer,colors:()=>g.map((e,t)=>l.seriesColor(t,e.color)),crosshair:p,dims:()=>d.dimensions,getData:()=>E,getPoints:()=>F,getSeriesList:()=>g,margin:w,markers:m,onClick:f.onClick,onHover:f.onHover,seriesGroup:v.series,svg:d.svg,tooltip:b,tooltipFormat:typeof f.tooltip==`object`?f.tooltip:void 0})},e=>{g=e})}exports.createLineChart=createLineChart;
|
|
2
2
|
//# sourceMappingURL=line-chart.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-chart.cjs","names":[],"sources":["../../../src/charts/line/line-chart.ts"],"sourcesContent":["import { positionAxis, 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, resolveMargin } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction, ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, LineChartConfig, LineSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computePoints, renderLine } from './line-renderer';\n\nexport function createLineChart(container: HTMLElement, config: LineChartConfig): ChartHandle<LineSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let rightAxis: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx) => {\n const { groups, legend, tooltip } = ctx;\n const dims = ctx.dimensions;\n const hasRight = seriesList.some((series) => series.yAxis === 'right');\n const hasLeftData = seriesList.some((series) => series.yAxis !== 'right' && series.data.length > 0);\n // The right axis widens the right margin; the effective margin stays local to this\n // render pass (and is handed to the interaction layer) instead of mutating shared dims.\n const margin = {\n ...resolveMargin(config.margin),\n right:\n config.margin?.right ??\n (hasRight ? (config.rightYAxis?.label ? 72 : 50) : resolveMargin(config.margin).right),\n };\n const area = chartArea(dims.width, dims.height, margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const leftY = seriesList\n .filter((series) => series.yAxis !== 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n const rightY = seriesList\n .filter((series) => series.yAxis === 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n rightAxis?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n const yScale = buildYScale(leftY, area.height);\n const rightYScale = buildYScale(rightY, area.height);\n\n // Axes render by default (value axis with gridlines); `false` opts out.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : (config.yAxis ?? { grid: true });\n\n if (yAxisConfig && yAxisConfig.grid && (!hasRight || hasLeftData)) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTickCount(yAxisConfig, area.height, 'left'),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTickCount(xAxisConfig, area.width, 'bottom'),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig && (!hasRight || hasLeftData)) {\n const axis = { ...yAxisConfig, position: hasRight ? ('left' as const) : (yAxisConfig.position ?? 'left') };\n positionAxis(groups.yAxis, axis.position, area.width, area.height);\n renderAxis(groups.yAxis, yScale, axis, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n if (hasRight) {\n if (!rightAxis) {\n rightAxis = createSvgElement('g', { class: 'prism-y-axis-right' });\n ctx.chartArea.appendChild(rightAxis);\n }\n const axis = { ...config.rightYAxis, position: 'right' as const };\n positionAxis(rightAxis, 'right', area.width, area.height);\n renderAxis(rightAxis, rightYScale, axis, area.height, 'right');\n } else {\n rightAxis?.replaceChildren();\n }\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-line-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const seriesScale = series.yAxis === 'right' ? rightYScale : yScale;\n const points = computePoints(allData[i], xScale, seriesScale);\n\n allPoints.push(points);\n\n renderLine(group, points, {\n baselineY: seriesScale.map(0),\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n showPoints: series.showPoints ?? false,\n strokeWidth: series.strokeWidth,\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 markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createSeriesInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"line-chart.cjs","names":[],"sources":["../../../src/charts/line/line-chart.ts"],"sourcesContent":["import { positionAxis, renderAxis, resolveTickCount, resolveTicks } from '../../axes/axis';\nimport { renderGrid } from '../../axes/grid';\nimport { buildXScale, buildYScale } from '../../core/cartesian-scales';\nimport { clearCartesianDom, createChartScaffold } from '../../core/chart-scaffold';\nimport { chartArea, resolveMargin } from '../../core/layout';\nimport { seriesDomId } from '../../core/series-id';\nimport { createCrosshair } from '../../interaction/crosshair';\nimport { createSeriesInteraction, ensureMarkerGroup } from '../../interaction/series-interaction';\nimport { createSvgElement } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { seriesColor } from '../../theme';\nimport type { ChartHandle, LineChartConfig, LineSeriesConfig, XAxisConfig, YAxisConfig } from '../../types';\nimport { computePoints, renderLine } from './line-renderer';\n\nexport function createLineChart(container: HTMLElement, config: LineChartConfig): ChartHandle<LineSeriesConfig[]> {\n let crosshair: ReturnType<typeof createCrosshair> | null = null;\n let markers: SVGGElement | null = null;\n let rightAxis: SVGGElement | null = null;\n let seriesList = config.series;\n\n return createChartScaffold(\n container,\n config,\n (ctx, reason) => {\n const { groups, legend, tooltip } = ctx;\n legend?.update(seriesList.map((s, i) => ({ color: seriesColor(i, s.color), name: s.name })));\n const dims = ctx.dimensions;\n const hasRight = seriesList.some((series) => series.yAxis === 'right');\n const hasLeftData = seriesList.some((series) => series.yAxis !== 'right' && series.data.length > 0);\n // The right axis widens the right margin; the effective margin stays local to this\n // render pass (and is handed to the interaction layer) instead of mutating shared dims.\n const margin = {\n ...resolveMargin(config.margin),\n right:\n config.margin?.right ??\n (hasRight ? (config.rightYAxis?.label ? 72 : 50) : resolveMargin(config.margin).right),\n };\n const area = chartArea(dims.width, dims.height, margin);\n const allData = seriesList.map((series) => series.data);\n const allX = allData.flat().map((datum) => datum.key);\n const leftY = seriesList\n .filter((series) => series.yAxis !== 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n const rightY = seriesList\n .filter((series) => series.yAxis === 'right')\n .flatMap((series) => series.data.map((datum) => datum.value));\n\n if (allX.length === 0) {\n clearCartesianDom(groups, legend, tooltip, crosshair);\n markers?.replaceChildren();\n rightAxis?.replaceChildren();\n\n return;\n }\n\n if (config.crosshair && !crosshair) {\n crosshair = createCrosshair(ctx.chartArea, config.crosshair);\n }\n\n const xScale = buildXScale(allX, area.width);\n const yScale = buildYScale(leftY, area.height);\n const rightYScale = buildYScale(rightY, area.height);\n\n // Axes render by default (value axis with gridlines); `false` opts out. The value\n // axis merges over its default so a partial config (e.g. only `tickFormat`) keeps\n // the default gridlines.\n const xAxisConfig: XAxisConfig | false = config.xAxis === false ? false : (config.xAxis ?? {});\n const yAxisConfig: YAxisConfig | false = config.yAxis === false ? false : { grid: true, ...config.yAxis };\n\n if (yAxisConfig && yAxisConfig.grid && (!hasRight || hasLeftData)) {\n renderGrid(\n groups.grid,\n yScale,\n yAxisConfig.grid,\n area.width,\n 'horizontal',\n resolveTicks(yScale, yAxisConfig, resolveTickCount(yAxisConfig, area.height, 'left')),\n );\n } else {\n groups.grid.replaceChildren();\n }\n\n if (xAxisConfig && xAxisConfig.grid) {\n renderGrid(\n groups.grid,\n xScale,\n xAxisConfig.grid,\n area.height,\n 'vertical',\n resolveTicks(xScale, xAxisConfig, resolveTickCount(xAxisConfig, area.width, 'bottom')),\n );\n }\n\n if (xAxisConfig) {\n positionAxis(groups.xAxis, xAxisConfig.position ?? 'bottom', area.width, area.height);\n renderAxis(groups.xAxis, xScale, xAxisConfig, area.width, 'bottom');\n } else {\n groups.xAxis.replaceChildren();\n }\n\n if (yAxisConfig && (!hasRight || hasLeftData)) {\n const axis = { ...yAxisConfig, position: hasRight ? ('left' as const) : (yAxisConfig.position ?? 'left') };\n positionAxis(groups.yAxis, axis.position, area.width, area.height);\n renderAxis(groups.yAxis, yScale, axis, area.height, 'left');\n } else {\n groups.yAxis.replaceChildren();\n }\n\n if (hasRight) {\n if (!rightAxis) {\n rightAxis = createSvgElement('g', { class: 'prism-y-axis-right' });\n ctx.chartArea.appendChild(rightAxis);\n }\n const axis = { ...config.rightYAxis, position: 'right' as const };\n positionAxis(rightAxis, 'right', area.width, area.height);\n renderAxis(rightAxis, rightYScale, axis, area.height, 'right');\n } else {\n rightAxis?.replaceChildren();\n }\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-line-series' });\n groups.series.appendChild(group);\n }\n\n group.setAttribute('data-series-id', seriesDomId(series, i));\n\n const seriesScale = series.yAxis === 'right' ? rightYScale : yScale;\n const points = computePoints(allData[i], xScale, seriesScale);\n\n allPoints.push(points);\n\n renderLine(group, points, {\n bounds: { height: area.height, width: area.width },\n color: seriesColor(i, series.color),\n curve: series.curve ?? 'linear',\n disposalSignal: ctx.disposalSignal,\n marks: series.data,\n pointRadius: series.pointRadius ?? 3,\n showPoints: series.showPoints ?? false,\n strokeWidth: series.strokeWidth,\n transition: reason === 'resize' ? false : config.transition,\n });\n }\n\n tooltip?.hide();\n markers = ensureMarkerGroup(ctx.chartArea, markers);\n\n return createSeriesInteraction({\n announcer: ctx.announcer,\n colors: () => seriesList.map((s, i) => seriesColor(i, s.color)),\n crosshair,\n dims: () => ctx.dimensions,\n getData: () => allData,\n getPoints: () => allPoints,\n getSeriesList: () => seriesList,\n margin,\n markers,\n onClick: config.onClick,\n onHover: config.onHover,\n seriesGroup: groups.series,\n svg: ctx.svg,\n tooltip,\n tooltipFormat: typeof config.tooltip === 'object' ? config.tooltip : undefined,\n });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"line-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-chart.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAA4B,MAAM,aAAa,CAAC;AAG5G,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC,gBAAgB,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"line-chart.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-chart.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,WAAW,EAAE,eAAe,EAAE,gBAAgB,EAA4B,MAAM,aAAa,CAAC;AAG5G,wBAAgB,eAAe,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,EAAE,eAAe,GAAG,WAAW,CAAC,gBAAgB,EAAE,CAAC,CAsKhH"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{createSvgElement as e}from"../../svg/element.js";import{positionAxis as t,renderAxis as n,resolveTickCount as r}from"../../axes/axis.js";import{renderGrid as
|
|
1
|
+
import{createSvgElement as e}from"../../svg/element.js";import{positionAxis as t,renderAxis as n,resolveTickCount as r,resolveTicks as i}from"../../axes/axis.js";import{renderGrid as a}from"../../axes/grid.js";import{buildXScale as o,buildYScale as s}from"../../core/cartesian-scales.js";import{chartArea as c,resolveMargin as l}from"../../core/layout.js";import{clearCartesianDom as u,createChartScaffold as d}from"../../core/chart-scaffold.js";import{seriesDomId as f}from"../../core/series-id.js";import{createCrosshair as p}from"../../interaction/crosshair.js";import{createSeriesInteraction as m,ensureMarkerGroup as h}from"../../interaction/series-interaction.js";import{seriesColor as g}from"../../theme/index.js";import{computePoints as _,renderLine as v}from"./line-renderer.js";function createLineChart(y,b){let x=null,S=null,C=null,w=b.series;return d(y,b,(d,y)=>{let{groups:T,legend:E,tooltip:D}=d;E?.update(w.map((e,t)=>({color:g(t,e.color),name:e.name})));let O=d.dimensions,k=w.some(e=>e.yAxis===`right`),A=w.some(e=>e.yAxis!==`right`&&e.data.length>0),j={...l(b.margin),right:b.margin?.right??(k?b.rightYAxis?.label?72:50:l(b.margin).right)},M=c(O.width,O.height,j),N=w.map(e=>e.data),P=N.flat().map(e=>e.key),F=w.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),I=w.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(P.length===0){u(T,E,D,x),S?.replaceChildren(),C?.replaceChildren();return}b.crosshair&&!x&&(x=p(d.chartArea,b.crosshair));let L=o(P,M.width),R=s(F,M.height),z=s(I,M.height),B=b.xAxis===!1?!1:b.xAxis??{},V=b.yAxis!==!1&&{grid:!0,...b.yAxis};if(V&&V.grid&&(!k||A)?a(T.grid,R,V.grid,M.width,`horizontal`,i(R,V,r(V,M.height,`left`))):T.grid.replaceChildren(),B&&B.grid&&a(T.grid,L,B.grid,M.height,`vertical`,i(L,B,r(B,M.width,`bottom`))),B?(t(T.xAxis,B.position??`bottom`,M.width,M.height),n(T.xAxis,L,B,M.width,`bottom`)):T.xAxis.replaceChildren(),V&&(!k||A)){let e={...V,position:k?`left`:V.position??`left`};t(T.yAxis,e.position,M.width,M.height),n(T.yAxis,R,e,M.height,`left`)}else T.yAxis.replaceChildren();if(k){C||(C=e(`g`,{class:`prism-y-axis-right`}),d.chartArea.appendChild(C));let r={...b.rightYAxis,position:`right`};t(C,`right`,M.width,M.height),n(C,z,r,M.height,`right`)}else C?.replaceChildren();for(;T.series.children.length>w.length;)T.series.removeChild(T.series.lastChild);let H=[];for(let t=0;t<w.length;t++){let n=w[t],r=T.series.children[t];r||(r=e(`g`,{class:`prism-line-series`}),T.series.appendChild(r)),r.setAttribute(`data-series-id`,f(n,t));let i=n.yAxis===`right`?z:R,a=_(N[t],L,i);H.push(a),v(r,a,{bounds:{height:M.height,width:M.width},color:g(t,n.color),curve:n.curve??`linear`,disposalSignal:d.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:y!==`resize`&&b.transition})}return D?.hide(),S=h(d.chartArea,S),m({announcer:d.announcer,colors:()=>w.map((e,t)=>g(t,e.color)),crosshair:x,dims:()=>d.dimensions,getData:()=>N,getPoints:()=>H,getSeriesList:()=>w,margin:j,markers:S,onClick:b.onClick,onHover:b.onHover,seriesGroup:T.series,svg:d.svg,tooltip:D,tooltipFormat:typeof b.tooltip==`object`?b.tooltip:void 0})},e=>{w=e})}export{createLineChart};
|
|
2
2
|
//# sourceMappingURL=line-chart.js.map
|