@vielzeug/prism 26.10.4 → 26.10.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +14 -25
  2. package/dist/animation/reveal.cjs +2 -0
  3. package/dist/animation/reveal.cjs.map +1 -0
  4. package/dist/animation/reveal.d.ts +29 -0
  5. package/dist/animation/reveal.d.ts.map +1 -0
  6. package/dist/animation/reveal.js +2 -0
  7. package/dist/animation/reveal.js.map +1 -0
  8. package/dist/charts/area/area-chart.cjs +1 -1
  9. package/dist/charts/area/area-chart.cjs.map +1 -1
  10. package/dist/charts/area/area-chart.js +1 -1
  11. package/dist/charts/area/area-chart.js.map +1 -1
  12. package/dist/charts/bar/bar-chart.cjs +1 -1
  13. package/dist/charts/bar/bar-chart.cjs.map +1 -1
  14. package/dist/charts/bar/bar-chart.js +1 -1
  15. package/dist/charts/bar/bar-chart.js.map +1 -1
  16. package/dist/charts/bar/bar-renderer.cjs +1 -1
  17. package/dist/charts/bar/bar-renderer.cjs.map +1 -1
  18. package/dist/charts/bar/bar-renderer.d.ts.map +1 -1
  19. package/dist/charts/bar/bar-renderer.js +1 -1
  20. package/dist/charts/bar/bar-renderer.js.map +1 -1
  21. package/dist/charts/line/line-chart.cjs +1 -1
  22. package/dist/charts/line/line-chart.cjs.map +1 -1
  23. package/dist/charts/line/line-chart.js +1 -1
  24. package/dist/charts/line/line-chart.js.map +1 -1
  25. package/dist/charts/line/line-renderer.cjs +1 -1
  26. package/dist/charts/line/line-renderer.cjs.map +1 -1
  27. package/dist/charts/line/line-renderer.d.ts +5 -2
  28. package/dist/charts/line/line-renderer.d.ts.map +1 -1
  29. package/dist/charts/line/line-renderer.js +1 -1
  30. package/dist/charts/line/line-renderer.js.map +1 -1
  31. package/dist/charts/pie/pie-chart.cjs +1 -1
  32. package/dist/charts/pie/pie-chart.cjs.map +1 -1
  33. package/dist/charts/pie/pie-chart.d.ts.map +1 -1
  34. package/dist/charts/pie/pie-chart.js +1 -1
  35. package/dist/charts/pie/pie-chart.js.map +1 -1
  36. package/dist/core/chart-base.cjs +1 -1
  37. package/dist/core/chart-base.cjs.map +1 -1
  38. package/dist/core/chart-base.d.ts +1 -0
  39. package/dist/core/chart-base.d.ts.map +1 -1
  40. package/dist/core/chart-base.js +1 -1
  41. package/dist/core/chart-base.js.map +1 -1
  42. package/dist/core/chart-scaffold.cjs +1 -1
  43. package/dist/core/chart-scaffold.cjs.map +1 -1
  44. package/dist/core/chart-scaffold.d.ts +4 -2
  45. package/dist/core/chart-scaffold.d.ts.map +1 -1
  46. package/dist/core/chart-scaffold.js +1 -1
  47. package/dist/core/chart-scaffold.js.map +1 -1
  48. package/dist/interaction/legend.cjs +1 -1
  49. package/dist/interaction/legend.cjs.map +1 -1
  50. package/dist/interaction/legend.d.ts +1 -1
  51. package/dist/interaction/legend.d.ts.map +1 -1
  52. package/dist/interaction/legend.js +1 -1
  53. package/dist/interaction/legend.js.map +1 -1
  54. package/dist/prism.cjs +1 -1
  55. package/dist/prism.cjs.map +1 -1
  56. package/dist/prism.iife.js +1 -1
  57. package/dist/prism.iife.js.map +1 -1
  58. package/dist/prism.js +1 -1
  59. package/dist/prism.js.map +1 -1
  60. package/dist/types.d.ts +1 -1
  61. package/dist/types.d.ts.map +1 -1
  62. package/package.json +2 -2
@@ -1,2 +1,2 @@
1
- const e=require("../../svg/element.cjs"),t=require("../../animation/motion.cjs"),n=require("../../animation/transition.cjs");var r=20,i=400,a=new WeakMap;function renderBars(o,s,c,l,u,d){for(;o.children.length>s.length;){let e=o.lastElementChild;e&&o.removeChild(e)}let f=c.bandwidth(),p=d.stacked?f:f/d.seriesCount,m=d.stacked?0:p*d.seriesIndex,h=d.horizontal??!1,g=[],_=[],v=t.resolveMotion(d.transition,{defaultStagger:r}),y=v.duration>0,b=Math.min(v.stagger,i/Math.max(1,s.length));for(let t=0;t<s.length;t++){let n=s[t],r=c.map(n.key)+m,i=d.baselineYs?d.baselineYs[t]:u,a=l.map(n.y),f=o.children[t],v=!f;if(f||(f=e.createSvgElement(`rect`,{class:`prism-bar`}),o.appendChild(f)),f.style.display=n.present?``:`none`,e.setAttributes(f,{opacity:n.opacity,stroke:n.dash?d.color:void 0,"stroke-dasharray":n.dash,"stroke-width":n.dash?1:void 0}),h){let t=Math.max(0,Math.abs(i-a)),n=Math.min(a,i);e.setAttributes(f,{fill:d.color,height:Math.max(0,p-1),rx:d.borderRadius,ry:d.borderRadius,y:r}),y?v?(e.setAttributes(f,{width:0,x:i}),g.push({attrs:{width:{from:0,to:t},x:{from:i,to:n}},el:f})):_.push({attrs:{width:{from:Number(f.getAttribute(`width`)??t),to:t},x:{from:Number(f.getAttribute(`x`)??n),to:n}},el:f}):e.setAttributes(f,{width:t,x:n})}else{let t=Math.max(0,Math.abs(i-a)),n=Math.min(a,i);e.setAttributes(f,{fill:d.color,rx:d.borderRadius,ry:d.borderRadius,width:Math.max(0,p-1),x:r}),y?v?(e.setAttributes(f,{height:0,y:i}),g.push({attrs:{height:{from:0,to:t},y:{from:i,to:n}},el:f})):_.push({attrs:{height:{from:Number(f.getAttribute(`height`)??t),to:t},y:{from:Number(f.getAttribute(`y`)??n),to:n}},el:f}):e.setAttributes(f,{height:t,y:n})}}if(y){a.get(o)?.();let e=[];g.length>0&&e.push(n.animate(g,{...v,stagger:b},void 0,d.disposalSignal)),_.length>0&&e.push(n.animate(_,{...v,stagger:0},void 0,d.disposalSignal)),a.set(o,()=>{for(let t of e)t()})}}exports.renderBars=renderBars;
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":"AAIA,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;AASD,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,CAkIN"}
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 i=20,a=400,o=new WeakMap;function renderBars(s,c,l,u,d,f){for(;s.children.length>c.length;){let e=s.lastElementChild;e&&s.removeChild(e)}let p=l.bandwidth(),m=f.stacked?p:p/f.seriesCount,h=f.stacked?0:m*f.seriesIndex,g=f.horizontal??!1,_=[],v=[],y=n(f.transition,{defaultStagger:i}),b=y.duration>0,x=Math.min(y.stagger,a/Math.max(1,c.length));for(let n=0;n<c.length;n++){let r=c[n],i=l.map(r.key)+h,a=f.baselineYs?f.baselineYs[n]:d,o=u.map(r.y),p=s.children[n],y=!p;if(p||(p=e(`rect`,{class:`prism-bar`}),s.appendChild(p)),p.style.display=r.present?``:`none`,t(p,{opacity:r.opacity,stroke:r.dash?f.color:void 0,"stroke-dasharray":r.dash,"stroke-width":r.dash?1:void 0}),g){let e=Math.max(0,Math.abs(a-o)),n=Math.min(o,a);t(p,{fill:f.color,height:Math.max(0,m-1),rx:f.borderRadius,ry:f.borderRadius,y:i}),b?y?(t(p,{width:0,x:a}),_.push({attrs:{width:{from:0,to:e},x:{from:a,to:n}},el:p})):v.push({attrs:{width:{from:Number(p.getAttribute(`width`)??e),to:e},x:{from:Number(p.getAttribute(`x`)??n),to:n}},el:p}):t(p,{width:e,x:n})}else{let e=Math.max(0,Math.abs(a-o)),n=Math.min(o,a);t(p,{fill:f.color,rx:f.borderRadius,ry:f.borderRadius,width:Math.max(0,m-1),x:i}),b?y?(t(p,{height:0,y:a}),_.push({attrs:{height:{from:0,to:e},y:{from:a,to:n}},el:p})):v.push({attrs:{height:{from:Number(p.getAttribute(`height`)??e),to:e},y:{from:Number(p.getAttribute(`y`)??n),to:n}},el:p}):t(p,{height:e,y:n})}}if(b){o.get(s)?.();let e=[];_.length>0&&e.push(r(_,{...y,stagger:x},void 0,f.disposalSignal)),v.length>0&&e.push(r(v,{...y,stagger:0},void 0,f.disposalSignal)),o.set(s,()=>{for(let t of e)t()})}}export{renderBars};
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:_,legend:v,tooltip:y}=d,b=d.dimensions,x=g.some(e=>e.yAxis===`right`),S=g.some(e=>e.yAxis!==`right`&&e.data.length>0),C={...i.resolveMargin(f.margin),right:f.margin?.right??(x?f.rightYAxis?.label?72:50:i.resolveMargin(f.margin).right)},w=i.chartArea(b.width,b.height,C),T=g.map(e=>e.data),E=T.flat().map(e=>e.key),D=g.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),O=g.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(E.length===0){a.clearCartesianDom(_,v,y,p),m?.replaceChildren(),h?.replaceChildren();return}f.crosshair&&!p&&(p=s.createCrosshair(d.chartArea,f.crosshair));let k=r.buildXScale(E,w.width),A=r.buildYScale(D,w.height),j=r.buildYScale(O,w.height),M=f.xAxis===!1?!1:f.xAxis??{},N=f.yAxis===!1?!1:f.yAxis??{grid:!0};if(N&&N.grid&&(!x||S)?n.renderGrid(_.grid,A,N.grid,w.width,`horizontal`,t.resolveTickCount(N,w.height,`left`)):_.grid.replaceChildren(),M&&M.grid&&n.renderGrid(_.grid,k,M.grid,w.height,`vertical`,t.resolveTickCount(M,w.width,`bottom`)),M?(t.positionAxis(_.xAxis,M.position??`bottom`,w.width,w.height),t.renderAxis(_.xAxis,k,M,w.width,`bottom`)):_.xAxis.replaceChildren(),N&&(!x||S)){let e={...N,position:x?`left`:N.position??`left`};t.positionAxis(_.yAxis,e.position,w.width,w.height),t.renderAxis(_.yAxis,A,e,w.height,`left`)}else _.yAxis.replaceChildren();if(x){h||(h=e.createSvgElement(`g`,{class:`prism-y-axis-right`}),d.chartArea.appendChild(h));let n={...f.rightYAxis,position:`right`};t.positionAxis(h,`right`,w.width,w.height),t.renderAxis(h,j,n,w.height,`right`)}else h?.replaceChildren();for(;_.series.children.length>g.length;)_.series.removeChild(_.series.lastChild);let P=[];for(let t=0;t<g.length;t++){let n=g[t],r=_.series.children[t];r||(r=e.createSvgElement(`g`,{class:`prism-line-series`}),_.series.appendChild(r)),r.setAttribute(`data-series-id`,o.seriesDomId(n,t));let i=n.yAxis===`right`?j:A,a=u.computePoints(T[t],k,i);P.push(a),u.renderLine(r,a,{baselineY:i.map(0),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:f.transition})}return v?.update(g.map((e,t)=>({color:l.seriesColor(t,e.color),name:e.name}))),y?.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:()=>T,getPoints:()=>P,getSeriesList:()=>g,margin:C,markers:m,onClick:f.onClick,onHover:f.onHover,seriesGroup:_.series,svg:d.svg,tooltip:y})},e=>{g=e})}exports.createLineChart=createLineChart;
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?!1:f.yAxis??{grid:!0};if(P&&P.grid&&(!S||C)?n.renderGrid(v.grid,j,P.grid,T.width,`horizontal`,t.resolveTickCount(P,T.height,`left`)):v.grid.replaceChildren(),N&&N.grid&&n.renderGrid(v.grid,A,N.grid,T.height,`vertical`,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})},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 } 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.\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 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 });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
@@ -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 i}from"../../axes/grid.js";import{buildXScale as a,buildYScale as o}from"../../core/cartesian-scales.js";import{chartArea as s,resolveMargin as c}from"../../core/layout.js";import{clearCartesianDom as l,createChartScaffold as u}from"../../core/chart-scaffold.js";import{seriesDomId as d}from"../../core/series-id.js";import{createCrosshair as f}from"../../interaction/crosshair.js";import{createSeriesInteraction as p,ensureMarkerGroup as m}from"../../interaction/series-interaction.js";import{seriesColor as h}from"../../theme/index.js";import{computePoints as g,renderLine as _}from"./line-renderer.js";function createLineChart(v,y){let b=null,x=null,S=null,C=y.series;return u(v,y,u=>{let{groups:v,legend:w,tooltip:T}=u,E=u.dimensions,D=C.some(e=>e.yAxis===`right`),O=C.some(e=>e.yAxis!==`right`&&e.data.length>0),k={...c(y.margin),right:y.margin?.right??(D?y.rightYAxis?.label?72:50:c(y.margin).right)},A=s(E.width,E.height,k),j=C.map(e=>e.data),M=j.flat().map(e=>e.key),N=C.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),P=C.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(M.length===0){l(v,w,T,b),x?.replaceChildren(),S?.replaceChildren();return}y.crosshair&&!b&&(b=f(u.chartArea,y.crosshair));let F=a(M,A.width),I=o(N,A.height),L=o(P,A.height),R=y.xAxis===!1?!1:y.xAxis??{},z=y.yAxis===!1?!1:y.yAxis??{grid:!0};if(z&&z.grid&&(!D||O)?i(v.grid,I,z.grid,A.width,`horizontal`,r(z,A.height,`left`)):v.grid.replaceChildren(),R&&R.grid&&i(v.grid,F,R.grid,A.height,`vertical`,r(R,A.width,`bottom`)),R?(t(v.xAxis,R.position??`bottom`,A.width,A.height),n(v.xAxis,F,R,A.width,`bottom`)):v.xAxis.replaceChildren(),z&&(!D||O)){let e={...z,position:D?`left`:z.position??`left`};t(v.yAxis,e.position,A.width,A.height),n(v.yAxis,I,e,A.height,`left`)}else v.yAxis.replaceChildren();if(D){S||(S=e(`g`,{class:`prism-y-axis-right`}),u.chartArea.appendChild(S));let r={...y.rightYAxis,position:`right`};t(S,`right`,A.width,A.height),n(S,L,r,A.height,`right`)}else S?.replaceChildren();for(;v.series.children.length>C.length;)v.series.removeChild(v.series.lastChild);let B=[];for(let t=0;t<C.length;t++){let n=C[t],r=v.series.children[t];r||(r=e(`g`,{class:`prism-line-series`}),v.series.appendChild(r)),r.setAttribute(`data-series-id`,d(n,t));let i=n.yAxis===`right`?L:I,a=g(j[t],F,i);B.push(a),_(r,a,{baselineY:i.map(0),color:h(t,n.color),curve:n.curve??`linear`,disposalSignal:u.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:y.transition})}return w?.update(C.map((e,t)=>({color:h(t,e.color),name:e.name}))),T?.hide(),x=m(u.chartArea,x),p({announcer:u.announcer,colors:()=>C.map((e,t)=>h(t,e.color)),crosshair:b,dims:()=>u.dimensions,getData:()=>j,getPoints:()=>B,getSeriesList:()=>C,margin:k,markers:x,onClick:y.onClick,onHover:y.onHover,seriesGroup:v.series,svg:u.svg,tooltip:T})},e=>{C=e})}export{createLineChart};
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 i}from"../../axes/grid.js";import{buildXScale as a,buildYScale as o}from"../../core/cartesian-scales.js";import{chartArea as s,resolveMargin as c}from"../../core/layout.js";import{clearCartesianDom as l,createChartScaffold as u}from"../../core/chart-scaffold.js";import{seriesDomId as d}from"../../core/series-id.js";import{createCrosshair as f}from"../../interaction/crosshair.js";import{createSeriesInteraction as p,ensureMarkerGroup as m}from"../../interaction/series-interaction.js";import{seriesColor as h}from"../../theme/index.js";import{computePoints as g,renderLine as _}from"./line-renderer.js";function createLineChart(v,y){let b=null,x=null,S=null,C=y.series;return u(v,y,(u,v)=>{let{groups:w,legend:T,tooltip:E}=u;T?.update(C.map((e,t)=>({color:h(t,e.color),name:e.name})));let D=u.dimensions,O=C.some(e=>e.yAxis===`right`),k=C.some(e=>e.yAxis!==`right`&&e.data.length>0),A={...c(y.margin),right:y.margin?.right??(O?y.rightYAxis?.label?72:50:c(y.margin).right)},j=s(D.width,D.height,A),M=C.map(e=>e.data),N=M.flat().map(e=>e.key),P=C.filter(e=>e.yAxis!==`right`).flatMap(e=>e.data.map(e=>e.value)),F=C.filter(e=>e.yAxis===`right`).flatMap(e=>e.data.map(e=>e.value));if(N.length===0){l(w,T,E,b),x?.replaceChildren(),S?.replaceChildren();return}y.crosshair&&!b&&(b=f(u.chartArea,y.crosshair));let I=a(N,j.width),L=o(P,j.height),R=o(F,j.height),z=y.xAxis===!1?!1:y.xAxis??{},B=y.yAxis===!1?!1:y.yAxis??{grid:!0};if(B&&B.grid&&(!O||k)?i(w.grid,L,B.grid,j.width,`horizontal`,r(B,j.height,`left`)):w.grid.replaceChildren(),z&&z.grid&&i(w.grid,I,z.grid,j.height,`vertical`,r(z,j.width,`bottom`)),z?(t(w.xAxis,z.position??`bottom`,j.width,j.height),n(w.xAxis,I,z,j.width,`bottom`)):w.xAxis.replaceChildren(),B&&(!O||k)){let e={...B,position:O?`left`:B.position??`left`};t(w.yAxis,e.position,j.width,j.height),n(w.yAxis,L,e,j.height,`left`)}else w.yAxis.replaceChildren();if(O){S||(S=e(`g`,{class:`prism-y-axis-right`}),u.chartArea.appendChild(S));let r={...y.rightYAxis,position:`right`};t(S,`right`,j.width,j.height),n(S,R,r,j.height,`right`)}else S?.replaceChildren();for(;w.series.children.length>C.length;)w.series.removeChild(w.series.lastChild);let V=[];for(let t=0;t<C.length;t++){let n=C[t],r=w.series.children[t];r||(r=e(`g`,{class:`prism-line-series`}),w.series.appendChild(r)),r.setAttribute(`data-series-id`,d(n,t));let i=n.yAxis===`right`?R:L,a=g(M[t],I,i);V.push(a),_(r,a,{bounds:{height:j.height,width:j.width},color:h(t,n.color),curve:n.curve??`linear`,disposalSignal:u.disposalSignal,marks:n.data,pointRadius:n.pointRadius??3,showPoints:n.showPoints??!1,strokeWidth:n.strokeWidth,transition:v!==`resize`&&y.transition})}return E?.hide(),x=m(u.chartArea,x),p({announcer:u.announcer,colors:()=>C.map((e,t)=>h(t,e.color)),crosshair:b,dims:()=>u.dimensions,getData:()=>M,getPoints:()=>V,getSeriesList:()=>C,margin:A,markers:x,onClick:y.onClick,onHover:y.onHover,seriesGroup:w.series,svg:u.svg,tooltip:E})},e=>{C=e})}export{createLineChart};
2
2
  //# sourceMappingURL=line-chart.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-chart.js","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":"kwBAcA,SAAgB,gBAAgB,EAAwB,EAA0D,CAChH,IAAI,EAAuD,KACvD,EAA8B,KAC9B,EAAgC,KAChC,EAAa,EAAO,OAExB,OAAO,EACL,EACA,EACC,GAAQ,CACP,GAAM,CAAE,SAAQ,SAAQ,WAAY,EAC9B,EAAO,EAAI,WACX,EAAW,EAAW,KAAM,GAAW,EAAO,QAAU,OAAO,EAC/D,EAAc,EAAW,KAAM,GAAW,EAAO,QAAU,SAAW,EAAO,KAAK,OAAS,CAAC,EAG5F,EAAS,CACb,GAAG,EAAc,EAAO,MAAM,EAC9B,MACE,EAAO,QAAQ,QACd,EAAY,EAAO,YAAY,MAAQ,GAAK,GAAM,EAAc,EAAO,MAAM,CAAC,CAAC,MACpF,EACM,EAAO,EAAU,EAAK,MAAO,EAAK,OAAQ,CAAM,EAChD,EAAU,EAAW,IAAK,GAAW,EAAO,IAAI,EAChD,EAAO,EAAQ,KAAK,CAAC,CAAC,IAAK,GAAU,EAAM,GAAG,EAC9C,EAAQ,EACX,OAAQ,GAAW,EAAO,QAAU,OAAO,CAAC,CAC5C,QAAS,GAAW,EAAO,KAAK,IAAK,GAAU,EAAM,KAAK,CAAC,EACxD,EAAS,EACZ,OAAQ,GAAW,EAAO,QAAU,OAAO,CAAC,CAC5C,QAAS,GAAW,EAAO,KAAK,IAAK,GAAU,EAAM,KAAK,CAAC,EAE9D,GAAI,EAAK,SAAW,EAAG,CACrB,EAAkB,EAAQ,EAAQ,EAAS,CAAS,EACpD,GAAS,gBAAgB,EACzB,GAAW,gBAAgB,EAE3B,MACF,CAEI,EAAO,WAAa,CAAC,IACvB,EAAY,EAAgB,EAAI,UAAW,EAAO,SAAS,GAG7D,IAAM,EAAS,EAAY,EAAM,EAAK,KAAK,EACrC,EAAS,EAAY,EAAO,EAAK,MAAM,EACvC,EAAc,EAAY,EAAQ,EAAK,MAAM,EAG7C,EAAmC,EAAO,QAAU,GAAQ,GAAS,EAAO,OAAS,CAAC,EACtF,EAAmC,EAAO,QAAU,GAAQ,GAAS,EAAO,OAAS,CAAE,KAAM,EAAK,EAiCxG,GA/BI,GAAe,EAAY,OAAS,CAAC,GAAY,GACnD,EACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,MACL,aACA,EAAiB,EAAa,EAAK,OAAQ,MAAM,CACnD,EAEA,EAAO,KAAK,gBAAgB,EAG1B,GAAe,EAAY,MAC7B,EACE,EAAO,KACP,EACA,EAAY,KACZ,EAAK,OACL,WACA,EAAiB,EAAa,EAAK,MAAO,QAAQ,CACpD,EAGE,GACF,EAAa,EAAO,MAAO,EAAY,UAAY,SAAU,EAAK,MAAO,EAAK,MAAM,EACpF,EAAW,EAAO,MAAO,EAAQ,EAAa,EAAK,MAAO,QAAQ,GAElE,EAAO,MAAM,gBAAgB,EAG3B,IAAgB,CAAC,GAAY,GAAc,CAC7C,IAAM,EAAO,CAAE,GAAG,EAAa,SAAU,EAAY,OAAoB,EAAY,UAAY,MAAQ,EACzG,EAAa,EAAO,MAAO,EAAK,SAAU,EAAK,MAAO,EAAK,MAAM,EACjE,EAAW,EAAO,MAAO,EAAQ,EAAM,EAAK,OAAQ,MAAM,CAC5D,MACE,EAAO,MAAM,gBAAgB,EAG/B,GAAI,EAAU,CACP,IACH,EAAY,EAAiB,IAAK,CAAE,MAAO,oBAAqB,CAAC,EACjE,EAAI,UAAU,YAAY,CAAS,GAErC,IAAM,EAAO,CAAE,GAAG,EAAO,WAAY,SAAU,OAAiB,EAChE,EAAa,EAAW,QAAS,EAAK,MAAO,EAAK,MAAM,EACxD,EAAW,EAAW,EAAa,EAAM,EAAK,OAAQ,OAAO,CAC/D,MACE,GAAW,gBAAgB,EAG7B,KAAO,EAAO,OAAO,SAAS,OAAS,EAAW,QAChD,EAAO,OAAO,YAAY,EAAO,OAAO,SAAU,EAGpD,IAAM,EAAuB,CAAC,EAE9B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAW,OAAQ,IAAK,CAC1C,IAAM,EAAS,EAAW,GACtB,EAAQ,EAAO,OAAO,SAAS,GAE9B,IACH,EAAQ,EAAiB,IAAK,CAAE,MAAO,mBAAoB,CAAC,EAC5D,EAAO,OAAO,YAAY,CAAK,GAGjC,EAAM,aAAa,iBAAkB,EAAY,EAAQ,CAAC,CAAC,EAE3D,IAAM,EAAc,EAAO,QAAU,QAAU,EAAc,EACvD,EAAS,EAAc,EAAQ,GAAI,EAAQ,CAAW,EAE5D,EAAU,KAAK,CAAM,EAErB,EAAW,EAAO,EAAQ,CACxB,UAAW,EAAY,IAAI,CAAC,EAC5B,MAAO,EAAY,EAAG,EAAO,KAAK,EAClC,MAAO,EAAO,OAAS,SACvB,eAAgB,EAAI,eACpB,MAAO,EAAO,KACd,YAAa,EAAO,aAAe,EACnC,WAAY,EAAO,YAAc,GACjC,YAAa,EAAO,YACpB,WAAY,EAAO,UACrB,CAAC,CACH,CAMA,OAJA,GAAQ,OAAO,EAAW,KAAK,EAAG,KAAO,CAAE,MAAO,EAAY,EAAG,EAAE,KAAK,EAAG,KAAM,EAAE,IAAK,EAAE,CAAC,EAC3F,GAAS,KAAK,EACd,EAAU,EAAkB,EAAI,UAAW,CAAO,EAE3C,EAAwB,CAC7B,UAAW,EAAI,UACf,WAAc,EAAW,KAAK,EAAG,IAAM,EAAY,EAAG,EAAE,KAAK,CAAC,EAC9D,YACA,SAAY,EAAI,WAChB,YAAe,EACf,cAAiB,EACjB,kBAAqB,EACrB,SACA,UACA,QAAS,EAAO,QAChB,QAAS,EAAO,QAChB,YAAa,EAAO,OACpB,IAAK,EAAI,IACT,SACF,CAAC,CACH,EACC,GAAS,CACR,EAAa,CACf,CACF,CACF"}
1
+ {"version":3,"file":"line-chart.js","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, 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.\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 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 });\n },\n (data) => {\n seriesList = data;\n },\n );\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../animation/easing.cjs"),n=require("../../animation/motion.cjs"),r=require("../../animation/tween.cjs"),i=require("../../animation/transition.cjs"),a=require("../../core/datum-style.cjs"),o=require("../../svg/path.cjs");var s=new WeakMap,c=new WeakMap;function buildPath(e,t){return t===`monotone`?o.monotonePath(e):t===`step`?o.stepPath(e):o.linePath(e)}function renderLine(o,l,u){let d=a.hasStyledRuns(u.marks),f=u.marks??[],p=n.resolveMotion(u.transition),m=p.duration,h=t.resolveEasing(p.easing),g=null,_=[],v=[];if(d){_=a.computeStyleRuns(f,l.length);let t=[...o.querySelectorAll(`.prism-line-path`)];for(let e of t.slice(_.length))e.remove();v=_.map((n,r)=>{let i=t[r];if(i)return i;let a=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`});return o.appendChild(a),a});for(let[t,n]of _.entries())e.setAttributes(v[t],{opacity:n.opacity,stroke:u.color,"stroke-dasharray":n.dash,"stroke-width":u.strokeWidth??2}),v[t].style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}else{let t=[...o.querySelectorAll(`.prism-line-path`)];g=t[0]??null;for(let e of t.slice(1))e.remove();g||(g=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`}),o.appendChild(g)),e.setAttributes(g,{opacity:void 0,stroke:u.color,"stroke-dasharray":void 0,"stroke-width":u.strokeWidth??2}),g.style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}let draw=t=>{if(d)for(let[n,r]of _.entries())e.setAttributes(v[n],{d:buildPath(t.slice(r.start,r.end+1),u.curve)});else e.setAttributes(g,{d:buildPath(t,u.curve)})},y=o.querySelector(`.prism-line-dots`);if(u.showPoints?y||(y=e.createSvgElement(`g`,{class:`prism-line-dots`}),o.appendChild(y)):y&&=(y.remove(),null),m===0){if(draw(l),c.set(o,l),y){for(;y.children.length>l.length;)y.removeChild(y.lastChild);for(let t=0;t<l.length;t++){let n=y.children[t];n||(n=e.createSvgElement(`circle`,{class:`prism-line-dot`}),y.appendChild(n)),e.setAttributes(n,{cx:l[t].x,cy:l[t].y,fill:u.color,opacity:f[t]?.opacity,r:u.pointRadius})}}return}s.get(o)?.();let b=!c.has(o),x=b?l.map(e=>({x:e.x,y:u.baselineY})):[];if(y){for(;y.children.length>l.length;)y.removeChild(y.lastChild);for(let t=y.children.length;t<l.length;t++){let n=e.createSvgElement(`circle`,{class:`prism-line-dot`});e.setAttributes(n,{fill:u.color,opacity:f[t]?.opacity,r:u.pointRadius}),y.appendChild(n)}for(let t=0;t<y.children.length;t++)e.setAttributes(y.children[t],{opacity:f[t]?.opacity})}if(!b){let e=c.get(o)??l;for(let[t,n]of l.entries())x.push(e[t]??e.at(-1)??n)}let paintFrame=t=>{let n=l.map((e,n)=>{let i=x[n]??e;return{x:r.tweenNumber(i.x,e.x,t),y:r.tweenNumber(i.y,e.y,t)}});if(c.set(o,n),draw(n),y)for(let t=0;t<l.length;t++){let r=y.children[t];r&&e.setAttributes(r,{cx:n[t].x,cy:n[t].y})}};paintFrame(0),s.set(o,i.startTween({count:1,duration:m,easing:h,onComplete:()=>{s.delete(o),c.set(o,l)},onFrame:e=>paintFrame(e(0)),signal:u.disposalSignal}))}function computePoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}exports.computePoints=computePoints,exports.renderLine=renderLine;
1
+ require("../../_dev.cjs");const e=require("../../svg/element.cjs"),t=require("../../animation/easing.cjs"),n=require("../../animation/motion.cjs"),r=require("../../animation/tween.cjs"),i=require("../../animation/transition.cjs"),a=require("../../core/datum-style.cjs"),o=require("../../svg/path.cjs"),s=require("../../animation/reveal.cjs");var c=new WeakMap,l=new WeakMap;function buildPath(e,t){return t===`monotone`?o.monotonePath(e):t===`step`?o.stepPath(e):o.linePath(e)}function renderLine(o,u,d){let f=a.hasStyledRuns(d.marks),p=d.marks??[],m=n.resolveMotion(d.transition),h=m.duration,g=t.resolveEasing(m.easing),_=null,v=[],y=[];if(f){v=a.computeStyleRuns(p,u.length);let t=[...o.querySelectorAll(`.prism-line-path`)];for(let e of t.slice(v.length))e.remove();y=v.map((n,r)=>{let i=t[r];if(i)return i;let a=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`});return o.appendChild(a),a});for(let[t,n]of v.entries())e.setAttributes(y[t],{opacity:n.opacity,stroke:d.color,"stroke-dasharray":n.dash,"stroke-width":d.strokeWidth??2}),y[t].style.strokeWidth=d.strokeWidth===void 0?``:String(d.strokeWidth)}else{let t=[...o.querySelectorAll(`.prism-line-path`)];_=t[0]??null;for(let e of t.slice(1))e.remove();_||(_=e.createSvgElement(`path`,{class:`prism-line-path`,fill:`none`}),o.appendChild(_)),e.setAttributes(_,{opacity:void 0,stroke:d.color,"stroke-dasharray":void 0,"stroke-width":d.strokeWidth??2}),_.style.strokeWidth=d.strokeWidth===void 0?``:String(d.strokeWidth)}let draw=t=>{if(f)for(let[n,r]of v.entries())e.setAttributes(y[n],{d:buildPath(t.slice(r.start,r.end+1),d.curve)});else e.setAttributes(_,{d:buildPath(t,d.curve)})},b=o.querySelector(`.prism-line-dots`);if(d.showPoints?b||(b=e.createSvgElement(`g`,{class:`prism-line-dots`}),o.appendChild(b)):b&&=(b.remove(),null),h===0){if(c.get(o)?.(),s.cancelReveal(o),draw(u),l.set(o,u),b){for(;b.children.length>u.length;)b.removeChild(b.lastChild);for(let t=0;t<u.length;t++){let n=b.children[t];n||(n=e.createSvgElement(`circle`,{class:`prism-line-dot`}),b.appendChild(n)),e.setAttributes(n,{cx:u[t].x,cy:u[t].y,fill:d.color,opacity:p[t]?.opacity,r:d.pointRadius})}}return}c.get(o)?.(),s.cancelReveal(o);let x=!l.has(o);if(b){for(;b.children.length>u.length;)b.removeChild(b.lastChild);for(let t=b.children.length;t<u.length;t++){let n=e.createSvgElement(`circle`,{class:`prism-line-dot`});e.setAttributes(n,{fill:d.color,opacity:p[t]?.opacity,r:d.pointRadius}),b.appendChild(n)}for(let t=0;t<b.children.length;t++)e.setAttributes(b.children[t],{opacity:p[t]?.opacity})}if(x){if(draw(u),l.set(o,u),b)for(let[t,n]of u.entries()){let r=b.children[t];r&&e.setAttributes(r,{cx:n.x,cy:n.y})}if(u.length>1){let e=_??y[0],t=d.strokeWidth??(Number.parseFloat(getComputedStyle(e).strokeWidth)||2),r=f?v.map((e,t)=>({d:y[t].getAttribute(`d`),end:e.end/(u.length-1),start:e.start/(u.length-1)})):[{d:_.getAttribute(`d`),end:1,start:0}];s.playTraceReveal(o,d.bounds,r,Math.max(t,d.showPoints?d.pointRadius*2:0)+2,n.resolveMotion(d.transition,{defaultDuration:420}),d.disposalSignal)}return}let S=[],C=l.get(o)??u;for(let[e,t]of u.entries())S.push(C[e]??C.at(-1)??t);let paintFrame=t=>{let n=u.map((e,n)=>{let i=S[n]??e;return{x:r.tweenNumber(i.x,e.x,t),y:r.tweenNumber(i.y,e.y,t)}});if(l.set(o,n),draw(n),b)for(let t=0;t<u.length;t++){let r=b.children[t];r&&e.setAttributes(r,{cx:n[t].x,cy:n[t].y})}};paintFrame(0),c.set(o,i.startTween({count:1,duration:h,easing:g,onComplete:()=>{c.delete(o),l.set(o,u)},onFrame:e=>paintFrame(e(0)),signal:d.disposalSignal}))}function computePoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}exports.computePoints=computePoints,exports.renderLine=renderLine;
2
2
  //# sourceMappingURL=line-renderer.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.cjs","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface LineRenderOptions {\n /** Plot-area bottom in area-local coordinates: the mount animation raises the line from here. */\n baselineY: number;\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionOption;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Geometry currently on screen, so an update interpolates from it even when the\n// series hides its point markers (the dots would otherwise be the only record).\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = drawnPoints.has(parent);\n // A first render has no drawn shape to interpolate between: the mount animation\n // raises the whole line from the plot baseline instead.\n const isMount = !hasExisting;\n\n const fromPts: Point[] = isMount ? points.map((p) => ({ x: p.x, y: options.baselineY })) : [];\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n if (!isMount) {\n const drawn = drawnPoints.get(parent) ?? points;\n\n for (const [i, to] of points.entries()) {\n fromPts.push(drawn[i] ?? drawn.at(-1) ?? to);\n }\n }\n\n const paintFrame = (e: number): void => {\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n drawnPoints.set(parent, interpolated);\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n };\n\n // The starting geometry goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one blank frame.\n paintFrame(0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => {\n activeAnimations.delete(parent);\n drawnPoints.set(parent, points);\n },\n onFrame: (progress) => paintFrame(progress(0)),\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"line-renderer.cjs","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { cancelReveal, playTraceReveal } from '../../animation/reveal';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface LineRenderOptions {\n /** Plot-area size in area-local coordinates: bounds the entrance mask. */\n bounds: { height: number; width: number };\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionOption;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Geometry currently on screen, so an update interpolates from it even when the\n// series hides its point markers (the dots would otherwise be the only record).\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n activeAnimations.get(parent)?.();\n cancelReveal(parent);\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n cancelReveal(parent);\n\n const isMount = !drawnPoints.has(parent);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n if (isMount) {\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n for (const [i, point] of points.entries()) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: point.x, cy: point.y });\n }\n }\n\n if (points.length > 1) {\n const renderedPath = path ?? runPaths[0];\n const strokeWidth = options.strokeWidth ?? (Number.parseFloat(getComputedStyle(renderedPath).strokeWidth) || 2);\n const traces = styled\n ? runs.map((run, i) => ({\n d: runPaths[i].getAttribute('d')!,\n end: run.end / (points.length - 1),\n start: run.start / (points.length - 1),\n }))\n : [{ d: path!.getAttribute('d')!, end: 1, start: 0 }];\n\n // A wide trace also uncovers markers as it reaches them, without a second timeline.\n playTraceReveal(\n parent,\n options.bounds,\n traces,\n Math.max(strokeWidth, options.showPoints ? options.pointRadius * 2 : 0) + 2,\n resolveMotion(options.transition, { defaultDuration: 420 }),\n options.disposalSignal,\n );\n }\n\n return;\n }\n\n const fromPts: Point[] = [];\n const drawn = drawnPoints.get(parent) ?? points;\n\n for (const [i, to] of points.entries()) {\n fromPts.push(drawn[i] ?? drawn.at(-1) ?? to);\n }\n\n const paintFrame = (e: number): void => {\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n drawnPoints.set(parent, interpolated);\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n };\n\n // The starting geometry goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one blank frame.\n paintFrame(0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => {\n activeAnimations.delete(parent);\n drawnPoints.set(parent, points);\n },\n onFrame: (progress) => paintFrame(progress(0)),\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
@@ -2,8 +2,11 @@ import { type DatumMark } from '../../core/datum-style';
2
2
  import type { Point } from '../../svg/path';
3
3
  import type { ContinuousDatum, Scale, TransitionOption } from '../../types';
4
4
  export interface LineRenderOptions {
5
- /** Plot-area bottom in area-local coordinates: the mount animation raises the line from here. */
6
- baselineY: number;
5
+ /** Plot-area size in area-local coordinates: bounds the entrance mask. */
6
+ bounds: {
7
+ height: number;
8
+ width: number;
9
+ };
7
10
  color: string;
8
11
  curve: 'linear' | 'monotone' | 'step';
9
12
  /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-renderer.ts"],"names":[],"mappings":"AAKA,OAAO,EAAoB,KAAK,SAAS,EAAgC,MAAM,wBAAwB,CAAC;AAExG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,iGAAiG;IACjG,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,wHAAwH;IACxH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAWD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAuLjG;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAanH"}
1
+ {"version":3,"file":"line-renderer.d.ts","sourceRoot":"","sources":["../../../src/charts/line/line-renderer.ts"],"names":[],"mappings":"AAMA,OAAO,EAAoB,KAAK,SAAS,EAAgC,MAAM,wBAAwB,CAAC;AAExG,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAE5C,OAAO,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE5E,MAAM,WAAW,iBAAiB;IAChC,0EAA0E;IAC1E,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;IACtC,wHAAwH;IACxH,cAAc,CAAC,EAAE,WAAW,CAAC;IAC7B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,gBAAgB,CAAC;CAC/B;AAWD,wBAAgB,UAAU,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAyNjG;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,GAAG,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,CAanH"}
@@ -1,2 +1,2 @@
1
- import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveEasing as n}from"../../animation/easing.js";import{resolveMotion as r}from"../../animation/motion.js";import{tweenNumber as i}from"../../animation/tween.js";import{startTween as a}from"../../animation/transition.js";import{computeStyleRuns as o,hasStyledRuns as s}from"../../core/datum-style.js";import{linePath as c,monotonePath as l,stepPath as u}from"../../svg/path.js";var d=new WeakMap,f=new WeakMap;function buildPath(e,t){return t===`monotone`?l(e):t===`step`?u(e):c(e)}function renderLine(c,l,u){let p=s(u.marks),m=u.marks??[],h=r(u.transition),g=h.duration,_=n(h.easing),v=null,y=[],b=[];if(p){y=o(m,l.length);let n=[...c.querySelectorAll(`.prism-line-path`)];for(let e of n.slice(y.length))e.remove();b=y.map((t,r)=>{let i=n[r];if(i)return i;let a=e(`path`,{class:`prism-line-path`,fill:`none`});return c.appendChild(a),a});for(let[e,n]of y.entries())t(b[e],{opacity:n.opacity,stroke:u.color,"stroke-dasharray":n.dash,"stroke-width":u.strokeWidth??2}),b[e].style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}else{let n=[...c.querySelectorAll(`.prism-line-path`)];v=n[0]??null;for(let e of n.slice(1))e.remove();v||(v=e(`path`,{class:`prism-line-path`,fill:`none`}),c.appendChild(v)),t(v,{opacity:void 0,stroke:u.color,"stroke-dasharray":void 0,"stroke-width":u.strokeWidth??2}),v.style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}let draw=e=>{if(p)for(let[n,r]of y.entries())t(b[n],{d:buildPath(e.slice(r.start,r.end+1),u.curve)});else t(v,{d:buildPath(e,u.curve)})},x=c.querySelector(`.prism-line-dots`);if(u.showPoints?x||(x=e(`g`,{class:`prism-line-dots`}),c.appendChild(x)):x&&=(x.remove(),null),g===0){if(draw(l),f.set(c,l),x){for(;x.children.length>l.length;)x.removeChild(x.lastChild);for(let n=0;n<l.length;n++){let r=x.children[n];r||(r=e(`circle`,{class:`prism-line-dot`}),x.appendChild(r)),t(r,{cx:l[n].x,cy:l[n].y,fill:u.color,opacity:m[n]?.opacity,r:u.pointRadius})}}return}d.get(c)?.();let S=!f.has(c),C=S?l.map(e=>({x:e.x,y:u.baselineY})):[];if(x){for(;x.children.length>l.length;)x.removeChild(x.lastChild);for(let n=x.children.length;n<l.length;n++){let r=e(`circle`,{class:`prism-line-dot`});t(r,{fill:u.color,opacity:m[n]?.opacity,r:u.pointRadius}),x.appendChild(r)}for(let e=0;e<x.children.length;e++)t(x.children[e],{opacity:m[e]?.opacity})}if(!S){let e=f.get(c)??l;for(let[t,n]of l.entries())C.push(e[t]??e.at(-1)??n)}let paintFrame=e=>{let n=l.map((t,n)=>{let r=C[n]??t;return{x:i(r.x,t.x,e),y:i(r.y,t.y,e)}});if(f.set(c,n),draw(n),x)for(let e=0;e<l.length;e++){let r=x.children[e];r&&t(r,{cx:n[e].x,cy:n[e].y})}};paintFrame(0),d.set(c,a({count:1,duration:g,easing:_,onComplete:()=>{d.delete(c),f.set(c,l)},onFrame:e=>paintFrame(e(0)),signal:u.disposalSignal}))}function computePoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}export{computePoints,renderLine};
1
+ import"../../_dev.js";import{createSvgElement as e,setAttributes as t}from"../../svg/element.js";import{resolveEasing as n}from"../../animation/easing.js";import{resolveMotion as r}from"../../animation/motion.js";import{tweenNumber as i}from"../../animation/tween.js";import{startTween as a}from"../../animation/transition.js";import{computeStyleRuns as o,hasStyledRuns as s}from"../../core/datum-style.js";import{linePath as c,monotonePath as l,stepPath as u}from"../../svg/path.js";import{cancelReveal as d,playTraceReveal as f}from"../../animation/reveal.js";var p=new WeakMap,m=new WeakMap;function buildPath(e,t){return t===`monotone`?l(e):t===`step`?u(e):c(e)}function renderLine(c,l,u){let h=s(u.marks),g=u.marks??[],_=r(u.transition),v=_.duration,y=n(_.easing),b=null,x=[],S=[];if(h){x=o(g,l.length);let n=[...c.querySelectorAll(`.prism-line-path`)];for(let e of n.slice(x.length))e.remove();S=x.map((t,r)=>{let i=n[r];if(i)return i;let a=e(`path`,{class:`prism-line-path`,fill:`none`});return c.appendChild(a),a});for(let[e,n]of x.entries())t(S[e],{opacity:n.opacity,stroke:u.color,"stroke-dasharray":n.dash,"stroke-width":u.strokeWidth??2}),S[e].style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}else{let n=[...c.querySelectorAll(`.prism-line-path`)];b=n[0]??null;for(let e of n.slice(1))e.remove();b||(b=e(`path`,{class:`prism-line-path`,fill:`none`}),c.appendChild(b)),t(b,{opacity:void 0,stroke:u.color,"stroke-dasharray":void 0,"stroke-width":u.strokeWidth??2}),b.style.strokeWidth=u.strokeWidth===void 0?``:String(u.strokeWidth)}let draw=e=>{if(h)for(let[n,r]of x.entries())t(S[n],{d:buildPath(e.slice(r.start,r.end+1),u.curve)});else t(b,{d:buildPath(e,u.curve)})},C=c.querySelector(`.prism-line-dots`);if(u.showPoints?C||(C=e(`g`,{class:`prism-line-dots`}),c.appendChild(C)):C&&=(C.remove(),null),v===0){if(p.get(c)?.(),d(c),draw(l),m.set(c,l),C){for(;C.children.length>l.length;)C.removeChild(C.lastChild);for(let n=0;n<l.length;n++){let r=C.children[n];r||(r=e(`circle`,{class:`prism-line-dot`}),C.appendChild(r)),t(r,{cx:l[n].x,cy:l[n].y,fill:u.color,opacity:g[n]?.opacity,r:u.pointRadius})}}return}p.get(c)?.(),d(c);let w=!m.has(c);if(C){for(;C.children.length>l.length;)C.removeChild(C.lastChild);for(let n=C.children.length;n<l.length;n++){let r=e(`circle`,{class:`prism-line-dot`});t(r,{fill:u.color,opacity:g[n]?.opacity,r:u.pointRadius}),C.appendChild(r)}for(let e=0;e<C.children.length;e++)t(C.children[e],{opacity:g[e]?.opacity})}if(w){if(draw(l),m.set(c,l),C)for(let[e,n]of l.entries()){let r=C.children[e];r&&t(r,{cx:n.x,cy:n.y})}if(l.length>1){let e=b??S[0],t=u.strokeWidth??(Number.parseFloat(getComputedStyle(e).strokeWidth)||2),n=h?x.map((e,t)=>({d:S[t].getAttribute(`d`),end:e.end/(l.length-1),start:e.start/(l.length-1)})):[{d:b.getAttribute(`d`),end:1,start:0}];f(c,u.bounds,n,Math.max(t,u.showPoints?u.pointRadius*2:0)+2,r(u.transition,{defaultDuration:420}),u.disposalSignal)}return}let T=[],E=m.get(c)??l;for(let[e,t]of l.entries())T.push(E[e]??E.at(-1)??t);let paintFrame=e=>{let n=l.map((t,n)=>{let r=T[n]??t;return{x:i(r.x,t.x,e),y:i(r.y,t.y,e)}});if(m.set(c,n),draw(n),C)for(let e=0;e<l.length;e++){let r=C.children[e];r&&t(r,{cx:n[e].x,cy:n[e].y})}};paintFrame(0),p.set(c,a({count:1,duration:v,easing:y,onComplete:()=>{p.delete(c),m.set(c,l)},onFrame:e=>paintFrame(e(0)),signal:u.disposalSignal}))}function computePoints(e,t,n){return e.some(e=>e.key==null)||e.some(e=>typeof e.key==`string`),e.map(e=>({x:t.map(e.key),y:n.map(e.value)}))}export{computePoints,renderLine};
2
2
  //# sourceMappingURL=line-renderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"line-renderer.js","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface LineRenderOptions {\n /** Plot-area bottom in area-local coordinates: the mount animation raises the line from here. */\n baselineY: number;\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionOption;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Geometry currently on screen, so an update interpolates from it even when the\n// series hides its point markers (the dots would otherwise be the only record).\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n\n const hasExisting = drawnPoints.has(parent);\n // A first render has no drawn shape to interpolate between: the mount animation\n // raises the whole line from the plot baseline instead.\n const isMount = !hasExisting;\n\n const fromPts: Point[] = isMount ? points.map((p) => ({ x: p.x, y: options.baselineY })) : [];\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n if (!isMount) {\n const drawn = drawnPoints.get(parent) ?? points;\n\n for (const [i, to] of points.entries()) {\n fromPts.push(drawn[i] ?? drawn.at(-1) ?? to);\n }\n }\n\n const paintFrame = (e: number): void => {\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n drawnPoints.set(parent, interpolated);\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n };\n\n // The starting geometry goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one blank frame.\n paintFrame(0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => {\n activeAnimations.delete(parent);\n drawnPoints.set(parent, points);\n },\n onFrame: (progress) => paintFrame(progress(0)),\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"line-renderer.js","names":[],"sources":["../../../src/charts/line/line-renderer.ts"],"sourcesContent":["import { warn } from '../../_dev';\nimport { resolveEasing } from '../../animation/easing';\nimport { resolveMotion } from '../../animation/motion';\nimport { cancelReveal, playTraceReveal } from '../../animation/reveal';\nimport { startTween } from '../../animation/transition';\nimport { tweenNumber } from '../../animation/tween';\nimport { computeStyleRuns, type DatumMark, hasStyledRuns, type StyleRun } from '../../core/datum-style';\nimport { createSvgElement, setAttributes } from '../../svg/element';\nimport type { Point } from '../../svg/path';\nimport { linePath, monotonePath, stepPath } from '../../svg/path';\nimport type { ContinuousDatum, Scale, TransitionOption } from '../../types';\n\nexport interface LineRenderOptions {\n /** Plot-area size in area-local coordinates: bounds the entrance mask. */\n bounds: { height: number; width: number };\n color: string;\n curve: 'linear' | 'monotone' | 'step';\n /** Aborted when the owning chart is disposed: stops the transition's `requestAnimationFrame` loop from rescheduling. */\n disposalSignal?: AbortSignal;\n /** Per-datum presentation parallel to `points`; styled runs split the line into subpaths. */\n marks?: readonly DatumMark[];\n pointRadius: number;\n showPoints: boolean;\n /** Explicit width beats the `--prism-line-width` theme token. */\n strokeWidth?: number;\n transition?: TransitionOption;\n}\n\nconst activeAnimations = new WeakMap<SVGGElement, () => void>();\n// Geometry currently on screen, so an update interpolates from it even when the\n// series hides its point markers (the dots would otherwise be the only record).\nconst drawnPoints = new WeakMap<SVGGElement, Point[]>();\n\nfunction buildPath(pts: Point[], curve: LineRenderOptions['curve']): string {\n return curve === 'monotone' ? monotonePath(pts) : curve === 'step' ? stepPath(pts) : linePath(pts);\n}\n\nexport function renderLine(parent: SVGGElement, points: Point[], options: LineRenderOptions): void {\n const styled = hasStyledRuns(options.marks);\n const marks = options.marks ?? [];\n const motion = resolveMotion(options.transition);\n const dur = motion.duration;\n const easing = resolveEasing(motion.easing);\n\n let path: SVGPathElement | null = null;\n let runs: readonly StyleRun[] = [];\n let runPaths: SVGPathElement[] = [];\n\n if (styled) {\n runs = computeStyleRuns(marks, points.length);\n\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n for (const extra of existing.slice(runs.length)) extra.remove();\n\n runPaths = runs.map((_, r) => {\n const reuse = existing[r];\n\n if (reuse) return reuse;\n\n const created = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n\n parent.appendChild(created);\n\n return created;\n });\n\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], {\n opacity: run.opacity,\n stroke: options.color,\n 'stroke-dasharray': run.dash,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n runPaths[r].style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n } else {\n const existing = [...parent.querySelectorAll<SVGPathElement>('.prism-line-path')];\n\n path = existing[0] ?? null;\n\n for (const stale of existing.slice(1)) stale.remove();\n\n if (!path) {\n path = createSvgElement('path', { class: 'prism-line-path', fill: 'none' });\n parent.appendChild(path);\n }\n\n setAttributes(path, {\n opacity: undefined,\n stroke: options.color,\n 'stroke-dasharray': undefined,\n 'stroke-width': options.strokeWidth ?? 2,\n });\n path.style.strokeWidth = options.strokeWidth === undefined ? '' : String(options.strokeWidth);\n }\n\n const draw = (pts: Point[]): void => {\n if (styled) {\n for (const [r, run] of runs.entries()) {\n setAttributes(runPaths[r], { d: buildPath(pts.slice(run.start, run.end + 1), options.curve) });\n }\n } else {\n setAttributes(path!, { d: buildPath(pts, options.curve) });\n }\n };\n\n let dotsGroup = parent.querySelector<SVGGElement>('.prism-line-dots');\n\n if (options.showPoints) {\n if (!dotsGroup) {\n dotsGroup = createSvgElement('g', { class: 'prism-line-dots' });\n parent.appendChild(dotsGroup);\n }\n } else if (dotsGroup) {\n dotsGroup.remove();\n dotsGroup = null;\n }\n\n if (dur === 0) {\n activeAnimations.get(parent)?.();\n cancelReveal(parent);\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = 0; i < points.length; i++) {\n let c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (!c) {\n c = createSvgElement('circle', { class: 'prism-line-dot' });\n dotsGroup.appendChild(c);\n }\n\n setAttributes(c, {\n cx: points[i].x,\n cy: points[i].y,\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n }\n }\n\n return;\n }\n\n activeAnimations.get(parent)?.();\n cancelReveal(parent);\n\n const isMount = !drawnPoints.has(parent);\n\n if (dotsGroup) {\n while (dotsGroup.children.length > points.length) dotsGroup.removeChild(dotsGroup.lastChild!);\n\n for (let i = dotsGroup.children.length; i < points.length; i++) {\n const c = createSvgElement('circle', { class: 'prism-line-dot' });\n\n setAttributes(c, {\n fill: options.color,\n opacity: marks[i]?.opacity,\n r: options.pointRadius,\n });\n dotsGroup.appendChild(c);\n }\n\n for (let i = 0; i < dotsGroup.children.length; i++) {\n setAttributes(dotsGroup.children[i] as SVGCircleElement, { opacity: marks[i]?.opacity });\n }\n }\n\n if (isMount) {\n draw(points);\n drawnPoints.set(parent, points);\n\n if (dotsGroup) {\n for (const [i, point] of points.entries()) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: point.x, cy: point.y });\n }\n }\n\n if (points.length > 1) {\n const renderedPath = path ?? runPaths[0];\n const strokeWidth = options.strokeWidth ?? (Number.parseFloat(getComputedStyle(renderedPath).strokeWidth) || 2);\n const traces = styled\n ? runs.map((run, i) => ({\n d: runPaths[i].getAttribute('d')!,\n end: run.end / (points.length - 1),\n start: run.start / (points.length - 1),\n }))\n : [{ d: path!.getAttribute('d')!, end: 1, start: 0 }];\n\n // A wide trace also uncovers markers as it reaches them, without a second timeline.\n playTraceReveal(\n parent,\n options.bounds,\n traces,\n Math.max(strokeWidth, options.showPoints ? options.pointRadius * 2 : 0) + 2,\n resolveMotion(options.transition, { defaultDuration: 420 }),\n options.disposalSignal,\n );\n }\n\n return;\n }\n\n const fromPts: Point[] = [];\n const drawn = drawnPoints.get(parent) ?? points;\n\n for (const [i, to] of points.entries()) {\n fromPts.push(drawn[i] ?? drawn.at(-1) ?? to);\n }\n\n const paintFrame = (e: number): void => {\n const interpolated: Point[] = points.map((to, i) => {\n const from = fromPts[i] ?? to;\n\n return { x: tweenNumber(from.x, to.x, e), y: tweenNumber(from.y, to.y, e) };\n });\n\n drawnPoints.set(parent, interpolated);\n draw(interpolated);\n\n if (dotsGroup) {\n for (let i = 0; i < points.length; i++) {\n const c = dotsGroup.children[i] as SVGCircleElement | undefined;\n\n if (c) setAttributes(c, { cx: interpolated[i].x, cy: interpolated[i].y });\n }\n }\n };\n\n // The starting geometry goes on screen immediately: `startTween` only paints on\n // the first frame callback, which would otherwise leave one blank frame.\n paintFrame(0);\n\n activeAnimations.set(\n parent,\n startTween({\n count: 1,\n duration: dur,\n easing,\n onComplete: () => {\n activeAnimations.delete(parent);\n drawnPoints.set(parent, points);\n },\n onFrame: (progress) => paintFrame(progress(0)),\n signal: options.disposalSignal,\n }),\n );\n}\n\nexport function computePoints(data: ContinuousDatum[], xScale: Scale<Date | number>, yScale: Scale<number>): Point[] {\n if (data.some((d) => d.key == null)) {\n warn(\n 'computePoints: datum.key is null or undefined: data must use the Datum shape { key, value }. Did you pass { x, y } instead?',\n );\n } else if (data.some((d) => typeof d.key === 'string')) {\n warn('computePoints: string keys are not supported for line/area charts: use numeric or Date keys.');\n }\n\n return data.map((d) => ({\n x: xScale.map(d.key as Date | number),\n y: yScale.map(d.value),\n }));\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- const e=require("../../svg/element.cjs"),t=require("../../svg/text.cjs"),n=require("../../core/chart-scaffold.cjs"),r=require("../../theme/index.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("./pie-renderer.cjs");var l=2*Math.PI,u=12;function labelFits(e,n){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=u*1.4&&a>=t.estimateTextWidth(n,u)+8}var d=-Math.PI/2,f=Math.PI/2;function semiAngles(e){return e===`semi`?{end:f,start:d}:{end:l,start:0}}function createPieChart(t,l){let u=l.variant??`pie`,d=l.padPixels??(u===`pie`?0:8),f=l.cornerRadius??(u===`pie`?0:8),p=l.data,m=e.createSvgElement(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),h=e.createSvgElement(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),g=e.createSvgElement(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),_=[],v=[],y=null;function renderLabels(t){g.replaceChildren();for(let n=0;n<_.length;n++){let r=_[n],i=t[n];if(!i?.label||!labelFits(r,i.label))continue;let{x:a,y:o}=c.arcCentroid(r),s=e.createSvgElement(`text`,{class:`prism-pie-label`});e.setAttributes(s,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:a,y:o}),s.textContent=i.label,g.appendChild(s)}}return n.createRadialScaffold(t,{a11y:l.a11y,legend:l.legend,tooltip:l.tooltip},n=>{let{legend:b,svg:x,tooltip:S}=n;x.contains(m)||(x.appendChild(m),x.appendChild(h),x.appendChild(g));let{height:C,width:w}=n.dimensions,T=u===`semi`,E=w/2,D=T?C*.85:C/2,O=T?Math.min(E,D)-8:Math.min(w,C)/2-8,k=u===`pie`?0:Math.round(O*.55),A=l.innerRadius===void 0?k:l.innerRadius,j=Math.max(A+1,O),M=p,{end:N,start:P}=semiAngles(u);for(_=c.computeArcs(M,E,D,j,A,P,N,d,f,e=>r.seriesColor(e),!1),e.setAttributes(m,{cx:E,cy:D,r:A>0?A:0}),m.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);h.children.length>_.length;)h.removeChild(h.lastChild);g.replaceChildren();let F=a.resolveMotion(l.transition),I=F.duration,L=i.resolveEasing(F.easing);for(let t=0;t<_.length;t++){let n=_[t],r=h.children[t];r||(r=e.createSvgElement(`path`,{class:`prism-pie-slice`}),h.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=l.onClick||l.onHover?`pointer`:``}y?.();let R=v.length===0,z=v;y=s.startTween({count:1,duration:I,easing:L,onComplete:()=>renderLabels(M),onFrame:t=>{let n=t(0);if(R){let t=o.tweenNumber(P,N,n);v=_.map((n,r)=>{let i=h.children[r];if(!i)return n;if(t<=n.startAngle)return e.setAttributes(i,{d:``}),{...n,endAngle:n.startAngle};let a=Math.min(n.endAngle,t);return e.setAttributes(i,{d:c.arcPath({...n,endAngle:a})}),{...n,endAngle:a}});return}v=_.map((t,r)=>{let i=h.children[r],a=z.at(-1),s=z[r]??{...t,endAngle:a?.endAngle??P,startAngle:a?.endAngle??P},l={...t,endAngle:o.tweenNumber(s.endAngle,t.endAngle,n),innerRadius:o.tweenNumber(s.innerRadius,t.innerRadius,n),outerRadius:o.tweenNumber(s.outerRadius,t.outerRadius,n),padAngle:o.tweenNumber(s.padAngle,t.padAngle,n),startAngle:o.tweenNumber(s.startAngle,t.startAngle,n)};return i&&e.setAttributes(i,{d:l.endAngle-l.startAngle<=1e-6?``:c.arcPath(l)}),l})},signal:n.disposalSignal}),b?.update(_.map(e=>({color:e.color,name:e.slice.label??``}))),S?.hide();let B=_.reduce((e,t)=>e+Math.max(0,t.slice.value),0),V=-1,describe=e=>{let t=B>0?Math.round(Math.max(0,e.slice.value)/B*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{V=e,h.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[...h.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=(e,r)=>{let i=_[e];if(!i)return;setActive(e),l.onHover?.({index:e,originalEvent:r,slice:i.slice});let a=describe(i);if(!S){n.announcer.announce(a);return}let{x:o,y:s}=c.arcCentroid(i),u=x.getBoundingClientRect(),d=t.getBoundingClientRect();S.show(o+(u.left-d.left),s+(u.top-d.top),{key:e,value:i.slice.value},{color:i.color,data:[],name:i.slice.label??``},a)},deactivate=()=>{setActive(-1),S?.hide(),n.announcer.clear(),l.onHover?.(null)},hitAt=e=>{let t=x.getBoundingClientRect();return hitTestArc(_,e.clientX-t.left,e.clientY-t.top,u)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==V&&activate(t,e):V>=0&&deactivate()},onClick=e=>{if(!l.onClick)return;let t=hitAt(e);t>=0&&l.onClick({index:t,originalEvent:e,slice:_[t].slice})},onKeyDown=e=>{let t=_.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(V<0?n[e.key]>0?0:t-1:(V+n[e.key]+t)%t,e)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1,e)):(e.key===`Enter`||e.key===` `)&&V>=0&&l.onClick?(e.preventDefault(),l.onClick({index:V,originalEvent:e,slice:_[V].slice})):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{p=e})}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,c=Math.sqrt(o*o+s*s);if(c<a.outerRadius&&c>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+l:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}exports.createPieChart=createPieChart;
1
+ const e=require("../../svg/element.cjs"),t=require("../../svg/text.cjs"),n=require("../../core/chart-scaffold.cjs"),r=require("../../theme/index.cjs"),i=require("../../animation/easing.cjs"),a=require("../../animation/motion.cjs"),o=require("../../animation/tween.cjs"),s=require("../../animation/transition.cjs"),c=require("./pie-renderer.cjs");var l=2*Math.PI,u=12;function labelFits(e,n){let r=e.outerRadius-e.innerRadius,i=(e.outerRadius+e.innerRadius)/2,a=(e.endAngle-e.startAngle-2*e.padAngle)*i;return r>=u*1.4&&a>=t.estimateTextWidth(n,u)+8}var d=-Math.PI/2,f=Math.PI/2;function semiAngles(e){return e===`semi`?{end:f,start:d}:{end:l,start:0}}function createPieChart(t,l){let u=l.variant??`pie`,d=l.padPixels??(u===`pie`?0:8),f=l.cornerRadius??(u===`pie`?0:8),p=l.data,m=e.createSvgElement(`circle`,{class:`prism-pie-bg`,"pointer-events":`none`}),h=e.createSvgElement(`g`,{class:`prism-pie-slices`,"shape-rendering":`geometricPrecision`}),g=e.createSvgElement(`g`,{class:`prism-pie-labels`,"pointer-events":`none`}),_=[],v=[],y=null;function renderLabels(t){g.replaceChildren();for(let n=0;n<_.length;n++){let r=_[n],i=t[n];if(!i?.label||!labelFits(r,i.label))continue;let{x:a,y:o}=c.arcCentroid(r),s=e.createSvgElement(`text`,{class:`prism-pie-label`});e.setAttributes(s,{"dominant-baseline":`middle`,fill:`var(--prism-pie-label-color, #fff)`,"font-family":`var(--prism-font-family, system-ui)`,"font-size":`var(--prism-pie-label-size, 12px)`,"text-anchor":`middle`,x:a,y:o}),s.textContent=i.label,g.appendChild(s)}}return n.createRadialScaffold(t,{a11y:l.a11y,legend:l.legend,tooltip:l.tooltip},n=>{let{legend:b,svg:x,tooltip:S}=n,C=p.some(e=>e.value>0);b?.update(C?p.map((e,t)=>({color:e.color??r.seriesColor(t),name:e.label??``})):[]),x.contains(m)||(x.appendChild(m),x.appendChild(h),x.appendChild(g));let{height:w,width:T}=n.dimensions,E=u===`semi`,D=T/2,O=E?w*.85:w/2,k=E?Math.min(D,O)-8:Math.min(T,w)/2-8,A=u===`pie`?0:Math.round(k*.55),j=l.innerRadius===void 0?A:l.innerRadius,M=Math.max(j+1,k),N=p,{end:P,start:F}=semiAngles(u);for(_=c.computeArcs(N,D,O,M,j,F,P,d,f,e=>r.seriesColor(e),!1),e.setAttributes(m,{cx:D,cy:O,r:j>0?j:0}),m.setAttribute(`style`,`fill:var(--prism-bg,#fff)`);h.children.length>_.length;)h.removeChild(h.lastChild);g.replaceChildren();let I=a.resolveMotion(l.transition),L=I.duration,R=i.resolveEasing(I.easing);for(let t=0;t<_.length;t++){let n=_[t],r=h.children[t];r||(r=e.createSvgElement(`path`,{class:`prism-pie-slice`}),h.appendChild(r)),r.setAttribute(`fill`,n.color),r.setAttribute(`stroke`,`none`),r.style.cursor=l.onClick||l.onHover?`pointer`:``}y?.();let z=v.length===0,B=v;y=s.startTween({count:1,duration:L,easing:R,onComplete:()=>renderLabels(N),onFrame:t=>{let n=t(0);if(z){let t=o.tweenNumber(F,P,n);v=_.map((n,r)=>{let i=h.children[r];if(!i)return n;if(t<=n.startAngle)return e.setAttributes(i,{d:``}),{...n,endAngle:n.startAngle};let a=Math.min(n.endAngle,t);return e.setAttributes(i,{d:c.arcPath({...n,endAngle:a})}),{...n,endAngle:a}});return}v=_.map((t,r)=>{let i=h.children[r],a=B.at(-1),s=B[r]??{...t,endAngle:a?.endAngle??F,startAngle:a?.endAngle??F},l={...t,endAngle:o.tweenNumber(s.endAngle,t.endAngle,n),innerRadius:o.tweenNumber(s.innerRadius,t.innerRadius,n),outerRadius:o.tweenNumber(s.outerRadius,t.outerRadius,n),padAngle:o.tweenNumber(s.padAngle,t.padAngle,n),startAngle:o.tweenNumber(s.startAngle,t.startAngle,n)};return i&&e.setAttributes(i,{d:l.endAngle-l.startAngle<=1e-6?``:c.arcPath(l)}),l})},signal:n.disposalSignal}),S?.hide();let V=_.reduce((e,t)=>e+Math.max(0,t.slice.value),0),H=-1,describe=e=>{let t=V>0?Math.round(Math.max(0,e.slice.value)/V*1e3)/10:0;return`${e.slice.label??`Slice ${e.index+1}`}: ${e.slice.value} (${t}%)`},setActive=e=>{H=e,h.classList.toggle(`prism-pie-focused`,e>=0);for(let[t,n]of[...h.children].entries())n.classList.toggle(`prism-pie-slice--active`,t===e)},activate=(e,r)=>{let i=_[e];if(!i)return;setActive(e),l.onHover?.({index:e,originalEvent:r,slice:i.slice});let a=describe(i);if(!S){n.announcer.announce(a);return}let{x:o,y:s}=c.arcCentroid(i),u=x.getBoundingClientRect(),d=t.getBoundingClientRect();S.show(o+(u.left-d.left),s+(u.top-d.top),{key:e,value:i.slice.value},{color:i.color,data:[],name:i.slice.label??``},a)},deactivate=()=>{setActive(-1),S?.hide(),n.announcer.clear(),l.onHover?.(null)},hitAt=e=>{let t=x.getBoundingClientRect();return hitTestArc(_,e.clientX-t.left,e.clientY-t.top,u)},onMouseMove=e=>{let t=hitAt(e);t>=0?t!==H&&activate(t,e):H>=0&&deactivate()},onClick=e=>{if(!l.onClick)return;let t=hitAt(e);t>=0&&l.onClick({index:t,originalEvent:e,slice:_[t].slice})},onKeyDown=e=>{let t=_.length;if(t===0)return;let n={ArrowDown:1,ArrowLeft:-1,ArrowRight:1,ArrowUp:-1};e.key in n?(e.preventDefault(),activate(H<0?n[e.key]>0?0:t-1:(H+n[e.key]+t)%t,e)):e.key===`Home`||e.key===`End`?(e.preventDefault(),activate(e.key===`Home`?0:t-1,e)):(e.key===`Enter`||e.key===` `)&&H>=0&&l.onClick?(e.preventDefault(),l.onClick({index:H,originalEvent:e,slice:_[H].slice})):e.key===`Escape`&&deactivate()};return{onClick,onKeyDown,onMouseLeave:deactivate,onMouseMove}},e=>{p=e})}function hitTestArc(e,t,n,r){for(let i=0;i<e.length;i++){let a=e[i],o=t-a.centerX,s=n-a.centerY,c=Math.sqrt(o*o+s*s);if(c<a.outerRadius&&c>=a.innerRadius){let e=Math.atan2(o,-s);if(r===`semi`){if(e>=a.startAngle-1e-9&&e<=a.endAngle+1e-9)return i}else{let t=e<0?e+l:e;if(t>=a.startAngle-1e-9&&t<=a.endAngle+1e-9)return i}}}return-1}exports.createPieChart=createPieChart;
2
2
  //# sourceMappingURL=pie-chart.cjs.map