minerva-design 1.18.0 → 1.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/custom-elements.json +10 -6
  3. package/dist/angular/fesm2022/minerva-angular.mjs +147 -46
  4. package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
  5. package/dist/angular/types/minerva-angular.d.ts +32 -20
  6. package/dist/charts/core.cjs +1 -1
  7. package/dist/charts/core.d.cts +1 -0
  8. package/dist/charts/core.d.ts +1 -0
  9. package/dist/charts/core.js +22 -21
  10. package/dist/charts/engine/chart.cjs +1 -1
  11. package/dist/charts/engine/chart.cjs.map +1 -1
  12. package/dist/charts/engine/chart.js +270 -240
  13. package/dist/charts/engine/chart.js.map +1 -1
  14. package/dist/charts/engine/overlay.cjs +1 -1
  15. package/dist/charts/engine/overlay.cjs.map +1 -1
  16. package/dist/charts/engine/overlay.js +23 -16
  17. package/dist/charts/engine/overlay.js.map +1 -1
  18. package/dist/charts/engine/quadrant-card.cjs +2 -0
  19. package/dist/charts/engine/quadrant-card.cjs.map +1 -0
  20. package/dist/charts/engine/quadrant-card.d.cts +83 -0
  21. package/dist/charts/engine/quadrant-card.d.ts +83 -0
  22. package/dist/charts/engine/quadrant-card.js +154 -0
  23. package/dist/charts/engine/quadrant-card.js.map +1 -0
  24. package/dist/charts/index.cjs +1 -1
  25. package/dist/charts/index.js +28 -27
  26. package/dist/charts/react/charts.cjs +1 -1
  27. package/dist/charts/react/charts.cjs.map +1 -1
  28. package/dist/charts/react/charts.js +378 -463
  29. package/dist/charts/react/charts.js.map +1 -1
  30. package/dist/core/contracts.cjs +1 -1
  31. package/dist/core/contracts.cjs.map +1 -1
  32. package/dist/core/contracts.js +1 -1
  33. package/dist/core/contracts.js.map +1 -1
  34. package/dist/native/charts/src/engine/overlay.cjs +1 -1
  35. package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
  36. package/dist/native/charts/src/engine/overlay.js +23 -16
  37. package/dist/native/charts/src/engine/overlay.js.map +1 -1
  38. package/dist/taro/index.js +23 -16
  39. package/dist/uni/manifest.d.ts +34 -34
  40. package/dist/uni/manifest.js +34 -39
  41. package/dist/vue/components/Chart/QuadrantChart.vue.d.ts +4 -3
  42. package/dist/vue/components/Chart/QuadrantChart.vue.js.map +1 -1
  43. package/dist/vue/components/Chart/QuadrantChart.vue_vue_type_script_setup_true_lang.js +186 -142
  44. package/dist/vue/components/Chart/QuadrantChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/vue/components/Chart/cartesian.d.ts +5 -1
  46. package/dist/vue/components/Chart/cartesian.js +2 -0
  47. package/dist/vue/components/Chart/cartesian.js.map +1 -1
  48. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue.js.map +1 -1
  49. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue_vue_type_script_setup_true_lang.js +4 -4
  50. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  51. package/dist/weapp/charts/canvas.js +13 -4
  52. package/dist/web-components/components/chart/chart.d.ts +4 -1
  53. package/dist/web-components/components/chart/chart.js +3 -1
  54. package/dist/web-components/components/chart/chart.js.map +1 -1
  55. package/dist/web-components/components/chart/charts.d.ts +34 -14
  56. package/dist/web-components/components/chart/charts.js +145 -98
  57. package/dist/web-components/components/chart/charts.js.map +1 -1
  58. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.d.ts +8 -8
  59. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.js +9 -5
  60. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.js.map +1 -1
  61. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.cjs","names":["mix","relativeLuminance","toScreen","screenRect","toCss","require_color","require_layout","INSIDE_PAD","insideLabelColor","alpha","fill","seen","background","l","font","theme","weight","size","crisp","v","pill","r","h","w","ctx","x","y","textBox","s","at","a","free","px","plot","py","width","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","drawBackground","input","scales","bottomTicks","yTicks","xTicks","leftTicks","bottomPx","leftPx","base","lastRight","order","i","b","left","lastBottom","rows","rowHeight","y2","y2Ticks","right","overlaps","inside","haloText","halo","color","insideBox","bar","x0","x1","y0","y1","CELL_PAD","LABEL_GAP","distanceTo","cellBox","bounds","slack","others","dots","d","c","spaced","occupied","o","own","far","gap","sideY","sides","beside","side","stacked","box","cuts","cw","best","total","keep","boxes","cut","placeLabels","placed","labels","fit","above","below","drawArrows","arrows","pts","first","next","prev","tip","b0","b1","drawForeground","labelHeight","where","title","muted","cy","textColor"],"sources":["../../../../charts/src/engine/overlay.ts"],"sourcesContent":["// Canvas2D layers around the data: background (areas, grid, axes, tick\n// labels) and foreground (reference lines, annotation and point labels).\n\nimport { mix, relativeLuminance, toCss, type Rgba } from \"./color\";\nimport type { AxisTicks } from \"./axis\";\nimport { screenRect, toScreen, type Rect, type Scales } from \"./layout\";\nimport type { AxisModel } from \"./model\";\nimport type { ChartTheme } from \"./theme\";\nimport type { ChartLabelPosition } from \"./types\";\n\nexport interface ResolvedRect {\n type: \"rect\";\n x0?: number;\n x1?: number;\n y0?: number;\n y1?: number;\n color: Rgba;\n opacity: number;\n label?: string;\n labelPosition: ChartLabelPosition;\n labelColor: Rgba;\n badge?: string;\n detail?: string;\n description?: string;\n}\n\nexport interface ResolvedLine {\n type: \"line\";\n axis: \"x\" | \"y\";\n value: number;\n color: Rgba;\n width: number;\n dash: number[];\n label?: string;\n}\n\nexport interface ResolvedText {\n type: \"text\";\n x?: number;\n y?: number;\n text: string;\n anchor: \"center\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n color: Rgba;\n weight: number;\n}\n\nexport type ResolvedAnnotation = ResolvedRect | ResolvedLine | ResolvedText;\n\nexport interface PointLabel {\n x: number;\n y: number;\n /** Radius of the dot */\n r: number;\n text: string;\n /**\n * Fixed side (bar values: above / below, left / right of horizontal\n * bars; `inside` the `bar`); any free side around the dot otherwise\n */\n placement?: \"above\" | \"below\" | \"left\" | \"right\" | \"inside\";\n /** `inside` labels: the bar, in CSS pixels */\n bar?: Rect;\n /** `inside` labels: at the start of the bar (horizontal bars) or centered */\n align?: \"start\" | \"center\";\n /**\n * Text color contrasting with a solid bar (`inside` labels), drawn\n * without a halo; the text color of the theme with a halo otherwise\n */\n color?: string;\n /**\n * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS\n * pixels: on the side of the dot with more room, cut with an ellipsis\n * when it does not fit\n */\n bounds?: Rect;\n /**\n * Placed (it keeps its room) but not drawn: a card over the chart names\n * the point\n */\n hidden?: boolean;\n}\n\n/** Padding of the labels inside the bars, CSS pixels */\nconst INSIDE_PAD = 6;\n\n/**\n * Color of a text written on a bar of color `fill` (alpha included) over\n * `background`: white or near-black, whichever contrasts more; `undefined`\n * for translucent bars (the theme text color with a halo reads better)\n */\nexport const insideLabelColor = (\n fill: Rgba,\n background: Rgba,\n): string | undefined => {\n const alpha = fill[3];\n if (alpha < 0.6) return undefined;\n const seen = mix(background, fill, alpha);\n const l = relativeLuminance(seen);\n // WCAG contrast with white (L = 1) and with #111827 (L ≈ 0.012)\n return 1.05 / (l + 0.05) >= (l + 0.05) / 0.062\n ? \"#ffffff\"\n : \"rgba(17, 24, 39, 0.92)\";\n};\n\nexport const font = (theme: ChartTheme, size = theme.fontSize, weight = 400) =>\n `${weight} ${size}px ${theme.fontFamily}`;\n\nconst crisp = (v: number) => Math.round(v) + 0.5;\n\n/** Path of a rounded box with half-height corners */\nconst pill = (\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n) => {\n const r = Math.min(h / 2, w / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.arcTo(x + w, y, x + w, y + r, r);\n ctx.lineTo(x + w, y + h - r);\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\n ctx.lineTo(x + r, y + h);\n ctx.arcTo(x, y + h, x, y + h - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n};\n\n/** Box of a text annotation, kept inside the plot */\nexport const textBox = (\n a: ResolvedText,\n s: Scales,\n width: number,\n height: number,\n): Rect => {\n const { plot } = s;\n const at = toScreen(s, a.x ?? 0, a.y ?? 0);\n const free = s.horizontal\n ? { x: a.y === undefined, y: a.x === undefined }\n : { x: a.x === undefined, y: a.y === undefined };\n const px = free.x ? plot.x + plot.width / 2 : at.x;\n const py = free.y ? plot.y + plot.height / 2 : at.y;\n const gap = 6;\n let x = px - width / 2;\n let y = py - height / 2;\n if (a.anchor === \"top\") y = py + gap;\n else if (a.anchor === \"bottom\") y = py - gap - height;\n else if (a.anchor === \"left\") x = px + gap;\n else if (a.anchor === \"right\") x = px - gap - width;\n x = Math.max(plot.x + gap, Math.min(x, plot.x + plot.width - gap - width));\n y = Math.max(plot.y + 2, Math.min(y, plot.y + plot.height - 2 - height));\n return { x, y, width, height };\n};\n\n/** Screen box of an area annotation, clipped to the plot */\nexport const rectOf = (a: ResolvedRect, s: Scales): Rect => {\n const { plot } = s;\n // clamp every edge to the plot first: an open edge maps to ±Infinity and\n // `Infinity - Infinity` would make the size NaN (nothing drawn)\n const [xLo, xHi] = s.horizontal\n ? [plot.y, plot.y + plot.height]\n : [plot.x, plot.x + plot.width];\n const [yLo, yHi] = s.horizontal\n ? [plot.x, plot.x + plot.width]\n : [plot.y, plot.y + plot.height];\n const along = (px: number, lo: number, hi: number) =>\n px < lo ? lo : px > hi ? hi : px;\n return screenRect(\n s,\n along(s.xToPx(a.x0 ?? -Infinity), xLo, xHi),\n along(s.xToPx(a.x1 ?? Infinity), xLo, xHi),\n along(s.yToPx(a.y0 ?? -Infinity), yLo, yHi),\n along(s.yToPx(a.y1 ?? Infinity), yLo, yHi),\n );\n};\n\n/** A text of the title block of an area: badge, label, detail or description */\nexport interface AreaText {\n kind: \"badge\" | \"label\" | \"detail\" | \"description\";\n text: string;\n /** Box of the text (the pill of a badge), CSS pixels */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Font size and weight */\n size: number;\n weight: number;\n}\n\n/** Title block of an area annotation, in its `labelPosition` corner */\nexport interface AreaTitle {\n parts: AreaText[];\n /** Box around the parts (the point labels avoid it) */\n box: Rect;\n}\n\n/** Whether an area annotation has a title block */\nexport const hasAreaTitle = (a: ResolvedRect): boolean =>\n !!(a.label || a.badge || a.detail || a.description);\n\n/** Text cut with an ellipsis to fit `max` pixels (\"\" when nothing fits) */\nconst fitText = (\n text: string,\n max: number,\n width: (text: string) => number,\n): string => {\n if (width(text) <= max) return text;\n const chars = Array.from(text);\n let lo = 0;\n let hi = chars.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (width(`${chars.slice(0, mid).join(\"\")}…`) <= max) lo = mid;\n else hi = mid - 1;\n }\n return lo > 0 ? `${chars.slice(0, lo).join(\"\").trimEnd()}…` : \"\";\n};\n\n/**\n * Layout of the title block of an area: `[badge] label detail` on the first\n * line, the description under it; the block sits in the `labelPosition`\n * corner, 10px from the edges, and the texts are cut to the area width\n */\nexport const areaTitleLayout = (\n a: ResolvedRect,\n r: Rect,\n fontSize: number,\n measure: (text: string, size: number, weight: number) => number,\n): AreaTitle | null => {\n if (!hasAreaTitle(a) || r.width <= 0 || r.height <= 0) return null;\n const pad = 10;\n const lineHeight = fontSize + 4;\n const max = Math.max(0, r.width - pad * 2);\n const labelSize = fontSize + 1;\n const badgeSize = Math.max(9, fontSize - 1);\n const gap = 6;\n const badge = a.badge\n ? fitText(a.badge, Math.max(0, max - 10), (t) => measure(t, badgeSize, 700))\n : \"\";\n const badgeWidth = badge ? measure(badge, badgeSize, 700) + 10 : 0;\n let detail = a.detail ?? \"\";\n let detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n const room = () =>\n max - (badge ? badgeWidth + gap : 0) - (detail ? detailWidth + gap : 0);\n // a narrow area keeps the title rather than the detail\n if (detail && a.label && room() < 32) {\n detail = \"\";\n detailWidth = 0;\n }\n if (detail && room() < 0) {\n detail = fitText(\n detail,\n Math.max(0, max - (badge ? badgeWidth + gap : 0)),\n (t) => measure(t, fontSize, 500),\n );\n detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n }\n const label = a.label\n ? fitText(a.label, Math.max(0, room()), (t) => measure(t, labelSize, 600))\n : \"\";\n const line: AreaText[] = [];\n if (badge)\n line.push({\n kind: \"badge\",\n text: badge,\n x: 0,\n y: 0,\n width: badgeWidth,\n height: lineHeight,\n size: badgeSize,\n weight: 700,\n });\n if (label)\n line.push({\n kind: \"label\",\n text: label,\n x: 0,\n y: 0,\n width: measure(label, labelSize, 600),\n height: lineHeight,\n size: labelSize,\n weight: 600,\n });\n if (detail)\n line.push({\n kind: \"detail\",\n text: detail,\n x: 0,\n y: 0,\n width: detailWidth,\n height: lineHeight,\n size: fontSize,\n weight: 500,\n });\n const description = a.description\n ? fitText(a.description, max, (t) => measure(t, fontSize, 400))\n : \"\";\n const lineWidth =\n line.reduce((sum, p) => sum + p.width, 0) +\n Math.max(0, line.length - 1) * gap;\n const descriptionWidth = description\n ? measure(description, fontSize, 400)\n : 0;\n if (!line.length && !description) return null;\n const height =\n (line.length ? lineHeight : 0) +\n (description ? lineHeight + (line.length ? 2 : 0) : 0);\n const pos = a.labelPosition;\n const top = pos.startsWith(\"top\")\n ? r.y + pad\n : pos.startsWith(\"bottom\")\n ? r.y + r.height - pad - height\n : r.y + (r.height - height) / 2;\n const startOf = (width: number) =>\n pos.endsWith(\"left\")\n ? r.x + pad\n : pos.endsWith(\"right\")\n ? r.x + r.width - pad - width\n : r.x + (r.width - width) / 2;\n const parts: AreaText[] = [];\n let x = startOf(lineWidth);\n for (const p of line) {\n parts.push({ ...p, x, y: top });\n x += p.width + gap;\n }\n if (description)\n parts.push({\n kind: \"description\",\n text: description,\n x: startOf(descriptionWidth),\n y: top + (line.length ? lineHeight + 2 : 0),\n width: descriptionWidth,\n height: lineHeight,\n size: fontSize,\n weight: 400,\n });\n const width = Math.max(lineWidth, descriptionWidth);\n return {\n parts,\n box: { x: startOf(width), y: top, width, height },\n };\n};\n\n/**\n * Where a reference line goes: `vertical` lines run at screen x `at`,\n * horizontal ones at screen y `at`\n */\nexport const lineOf = (\n a: ResolvedLine,\n s: Scales,\n): { vertical: boolean; at: number } => {\n const vertical = (a.axis === \"x\") !== s.horizontal;\n return {\n vertical,\n at: a.axis === \"x\" ? s.xToPx(a.value) : s.yToPx(a.value),\n };\n};\n\nexport interface BackgroundInput {\n width: number;\n height: number;\n scales: Scales;\n x: AxisModel;\n y: AxisModel;\n xTicks: AxisTicks;\n yTicks: AxisTicks;\n /** Right axis (dual axis charts) */\n y2?: AxisModel | null;\n y2Ticks?: AxisTicks | null;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n}\n\nexport const drawBackground = (\n ctx: CanvasRenderingContext2D,\n input: BackgroundInput,\n) => {\n const { scales, theme, xTicks, yTicks } = input;\n const { plot } = scales;\n // horizontal charts: the value axis along the bottom, the x axis on the left\n const x = scales.horizontal ? input.y : input.x;\n const y = scales.horizontal ? input.x : input.y;\n const bottomTicks = scales.horizontal ? yTicks : xTicks;\n const leftTicks = scales.horizontal ? xTicks : yTicks;\n const bottomPx = scales.horizontal ? scales.yToPx : scales.xToPx;\n const leftPx = scales.horizontal ? scales.xToPx : scales.yToPx;\n ctx.clearRect(0, 0, input.width, input.height);\n\n // areas\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n for (const a of input.annotations) {\n if (a.type !== \"rect\") continue;\n const r = rectOf(a, scales);\n if (r.width <= 0 || r.height <= 0) continue;\n ctx.fillStyle = toCss(a.color, a.opacity);\n ctx.fillRect(r.x, r.y, r.width, r.height);\n }\n ctx.restore();\n\n // grid\n ctx.lineWidth = 1;\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n if (y.grid) {\n for (const v of leftTicks.values) {\n const py = crisp(leftPx(v));\n if (py < plot.y - 1 || py > plot.y + plot.height + 1) continue;\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n }\n }\n if (x.grid) {\n for (const v of bottomTicks.values) {\n const px = crisp(bottomPx(v));\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n }\n }\n ctx.stroke();\n\n const line = Math.ceil(theme.fontSize * 1.4);\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n\n // x axis\n if (x.visible) {\n ctx.strokeStyle = toCss(theme.axis);\n ctx.beginPath();\n const base = crisp(plot.y + plot.height);\n ctx.moveTo(plot.x, base);\n ctx.lineTo(plot.x + plot.width, base);\n ctx.stroke();\n ctx.textBaseline = \"top\";\n ctx.textAlign = \"center\";\n let lastRight = -Infinity;\n // left to right (reversed axes list their ticks right to left)\n const order = bottomTicks.values\n .map((v, i) => ({ px: bottomPx(v), text: bottomTicks.labels[i] }))\n .sort((a, b) => a.px - b.px);\n for (const { px, text } of order) {\n if (px < plot.x - 0.5 || px > plot.x + plot.width + 0.5) continue;\n const w = ctx.measureText(text).width;\n const left = Math.max(0, Math.min(input.width - w, px - w / 2));\n if (left < lastRight + 6) continue;\n lastRight = left + w;\n ctx.fillText(text, left + w / 2, plot.y + plot.height + 7);\n }\n if (x.title) {\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.fillText(\n x.title,\n plot.x + plot.width / 2,\n plot.y + plot.height + line + 10,\n );\n }\n }\n\n // y axis\n if (y.visible) {\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"middle\";\n let lastBottom = -Infinity;\n // top to bottom: category rows of horizontal charts never overlap\n const rows = leftTicks.values\n .map((v, i) => ({ py: leftPx(v), text: leftTicks.labels[i] }))\n .sort((a, b) => a.py - b.py);\n const rowHeight = theme.fontSize + 2;\n for (const { py, text } of rows) {\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) continue;\n if (scales.horizontal) {\n if (py - rowHeight / 2 < lastBottom) continue;\n lastBottom = py + rowHeight / 2;\n }\n ctx.fillText(text, plot.x - 8, py);\n }\n if (y.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(line / 2 + 4, plot.y + plot.height / 2);\n ctx.rotate(-Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y.title, 0, 0);\n ctx.restore();\n }\n }\n\n // right axis\n const y2 = scales.horizontal ? null : input.y2;\n const y2Ticks = input.y2Ticks;\n if (y2 && y2Ticks && y2.visible) {\n const right = plot.x + plot.width;\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n y2Ticks.values.forEach((v, i) => {\n const py = scales.yToPx(v);\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) return;\n ctx.fillText(y2Ticks.labels[i], right + 8, py);\n });\n if (y2.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(input.width - line / 2 - 4, plot.y + plot.height / 2);\n ctx.rotate(Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y2.title, 0, 0);\n ctx.restore();\n }\n }\n};\n\nconst overlaps = (a: Rect, b: Rect) =>\n a.x < b.x + b.width &&\n b.x < a.x + a.width &&\n a.y < b.y + b.height &&\n b.y < a.y + a.height;\n\nconst inside = (r: Rect, plot: Rect) =>\n r.x >= plot.x &&\n r.y >= plot.y &&\n r.x + r.width <= plot.x + plot.width &&\n r.y + r.height <= plot.y + plot.height;\n\n/** Text with a halo in the background color (readable over data) */\nconst haloText = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n color: string,\n halo: string,\n) => {\n ctx.lineWidth = 3;\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = halo;\n ctx.strokeText(text, x, y);\n ctx.fillStyle = color;\n ctx.fillText(text, x, y);\n};\n\n/**\n * Box of a label inside its bar (the visible part of it): the text cut with\n * an ellipsis to fit, at the start of horizontal bars and centered in\n * vertical ones; `null` when the bar is too small\n */\nconst insideBox = (\n label: PointLabel,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n): { label: PointLabel; box: Rect } | null => {\n const bar = label.bar;\n if (!bar) return null;\n const x0 = Math.max(bar.x, plot.x);\n const x1 = Math.min(bar.x + bar.width, plot.x + plot.width);\n const y0 = Math.max(bar.y, plot.y);\n const y1 = Math.min(bar.y + bar.height, plot.y + plot.height);\n if (y1 - y0 < height - 2) return null;\n const text = fitText(label.text, x1 - x0 - INSIDE_PAD * 2, measure);\n if (!text) return null;\n const w = measure(text);\n const x = label.align === \"start\" ? x0 + INSIDE_PAD : (x0 + x1) / 2 - w / 2;\n return {\n label: text === label.text ? label : { ...label, text },\n box: { x, y: (y0 + y1) / 2 - height / 2, width: w, height },\n };\n};\n\n/** Room kept between a label and the edges of its cell, CSS pixels */\nconst CELL_PAD = 2;\n/** Room kept between two labels of a cell (they never touch), CSS pixels */\nconst LABEL_GAP = { x: 4, y: 2 };\n\n/** Distance from a point to the nearest point of a box */\nconst distanceTo = (x: number, y: number, r: Rect) =>\n Math.hypot(\n Math.max(r.x - x, 0, x - (r.x + r.width)),\n Math.max(r.y - y, 0, y - (r.y + r.height)),\n );\n\n/** A dot of a cell label: its label is told apart from the others by it */\ntype Dot = Pick<PointLabel, \"x\" | \"y\" | \"r\">;\n\n/**\n * Box of a label kept inside a cell of the plot (`bounds`): beside the dot\n * on the side with more room in the cell (moved up or down into the cell\n * near its edges), else above or below it (moved sideways into the cell);\n * cut with an ellipsis to the room left when the whole text fits nowhere;\n * `null` when no free slot is left. A slot is free when it keeps a gap to\n * the other labels and its own dot is the nearest one (it covers no other\n * dot): a crowded cell never pairs a name with the wrong dot\n */\nconst cellBox = (\n label: PointLabel,\n bounds: Rect,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: readonly Rect[],\n dots: readonly Dot[] = [],\n): { label: PointLabel; box: Rect } | null => {\n const x0 = Math.max(bounds.x, plot.x) + CELL_PAD;\n const x1 = Math.min(bounds.x + bounds.width, plot.x + plot.width) - CELL_PAD;\n const y0 = Math.max(bounds.y, plot.y) + CELL_PAD;\n const y1 =\n Math.min(bounds.y + bounds.height, plot.y + plot.height) - CELL_PAD;\n if (x1 - x0 <= 0 || y1 - y0 < height) return null;\n // a hair of slack: a text cut to the exact room ends on the edge\n const slack = {\n x: x0 - 0.01,\n y: y0 - 0.01,\n width: x1 - x0 + 0.02,\n height: y1 - y0 + 0.02,\n };\n // the other dots: those at the very spot of this one count as its own\n const others = dots.filter(\n (d) => Math.abs(d.x - label.x) >= 0.5 || Math.abs(d.y - label.y) >= 0.5,\n );\n const free = (c: Rect) => {\n if (!inside(c, slack)) return false;\n const spaced = {\n x: c.x - LABEL_GAP.x,\n y: c.y - LABEL_GAP.y,\n width: c.width + LABEL_GAP.x * 2,\n height: c.height + LABEL_GAP.y * 2,\n };\n if (occupied.some((o) => overlaps(o, spaced))) return false;\n const own = distanceTo(label.x, label.y, c);\n return others.every((d) => {\n const far = distanceTo(d.x, d.y, c);\n return far >= d.r + 2 && far > own;\n });\n };\n const gap = label.r + 4;\n // centered on the dot, moved into the cell near its top or bottom edge\n const sideY = Math.min(Math.max(label.y - height / 2, y0), y1 - height);\n const room = { right: x1 - (label.x + gap), left: label.x - gap - x0 };\n const sides: (\"right\" | \"left\")[] =\n room.right >= room.left ? [\"right\", \"left\"] : [\"left\", \"right\"];\n const beside = (side: \"right\" | \"left\", w: number): Rect[] => [\n {\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: sideY,\n width: w,\n height,\n },\n ];\n const stacked = (w: number): Rect[] => {\n // slid sideways into the cell near its edges (still over the dot)\n const x = Math.min(Math.max(label.x - w / 2, x0), x1 - w);\n return [\n { x, y: label.y - gap - height, width: w, height },\n { x, y: label.y + gap, width: w, height },\n ];\n };\n const w = measure(label.text);\n const whole = [\n ...beside(sides[0]!, w),\n ...beside(sides[1]!, w),\n ...stacked(w),\n ];\n const box = whole.find(free);\n if (box) return { label, box };\n // the whole text fits nowhere: cut it to the room beside the dot or above\n // / below it, keeping the longest text (the roomiest side on ties)\n const cuts: [number, (w: number) => Rect[]][] = [\n [room[sides[0]!], (cw) => beside(sides[0]!, cw)],\n [room[sides[1]!], (cw) => beside(sides[1]!, cw)],\n [x1 - x0, stacked],\n ];\n let best: { label: PointLabel; box: Rect } | null = null;\n // a cut keeps enough of the name to tell it (else the label is skipped,\n // like an overlapping one: the tooltip still names the point)\n const total = Array.from(label.text).length;\n const keep = Math.min(4, Math.ceil(total * 0.4));\n for (const [max, boxes] of cuts) {\n const text = fitText(label.text, max, measure);\n if (!text || (best && text.length <= best.label.text.length)) continue;\n if (Array.from(text).length - 1 < keep) continue;\n const cut = boxes(measure(text)).find(free);\n if (cut) best = { label: { ...label, text }, box: cut };\n }\n return best;\n};\n\n/** Greedy placement: right, left, above, below the dot; skipped when no slot is free */\nexport const placeLabels = (\n labels: readonly PointLabel[],\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: Rect[] = [],\n): { label: PointLabel; box: Rect }[] => {\n const placed: { label: PointLabel; box: Rect }[] = [];\n // the dots of the labels kept in cells (labels placed later included)\n const dots = labels.filter((label) => label.bounds);\n for (const label of labels) {\n if (label.placement === \"inside\") {\n const fit = insideBox(label, plot, measure, height);\n if (fit) placed.push(fit);\n continue;\n }\n if (label.bounds) {\n const fit = cellBox(\n label,\n label.bounds,\n plot,\n measure,\n height,\n occupied,\n dots,\n );\n if (!fit) continue;\n occupied.push(fit.box);\n placed.push(fit);\n continue;\n }\n const w = measure(label.text);\n const gap = label.r + 4;\n const above = {\n x: label.x - w / 2,\n y: label.y - gap - height,\n width: w,\n height,\n };\n const below = { x: label.x - w / 2, y: label.y + gap, width: w, height };\n const right = {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const left = {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const candidates: Rect[] =\n label.placement === \"above\"\n ? [above]\n : label.placement === \"below\"\n ? [below]\n : label.placement === \"right\"\n ? [right, left]\n : label.placement === \"left\"\n ? [left, right]\n : [\n {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n },\n {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n },\n above,\n below,\n ];\n const box = candidates.find(\n (c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)),\n );\n if (!box) continue;\n occupied.push(box);\n placed.push({ label, box });\n }\n return placed;\n};\n\nexport interface ForegroundInput {\n width: number;\n height: number;\n scales: Scales;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n pointLabels: readonly PointLabel[];\n /**\n * Clears the canvas first (off when the layers share one canvas)\n * @default true\n */\n clear?: boolean;\n /** Lines between consecutive bars (waterfall connectors), drawn first */\n connectors?: readonly {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n color: string;\n width: number;\n dash: readonly number[];\n }[];\n /** Dependency arrows (Gantt charts), drawn over the connectors */\n arrows?: readonly ArrowPath[];\n}\n\n/** An elbow arrow in stage pixels (see `dependencyArrows`) */\nexport interface ArrowPath {\n points: readonly { x: number; y: number }[];\n head: readonly { x: number; y: number }[];\n color: string;\n width: number;\n}\n\n/** Elbow arrows: polylines with rounded corners and filled heads */\nexport const drawArrows = (\n ctx: CanvasRenderingContext2D,\n arrows: readonly ArrowPath[],\n) => {\n for (const a of arrows) {\n const pts = a.points;\n const first = pts[0];\n if (!first) continue;\n ctx.strokeStyle = a.color;\n ctx.fillStyle = a.color;\n ctx.lineWidth = a.width;\n ctx.lineJoin = \"round\";\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (let i = 1; i < pts.length; i++) {\n const p = pts[i]!;\n const next = pts[i + 1];\n const prev = pts[i - 1]!;\n if (next && typeof ctx.arcTo === \"function\") {\n // rounded elbow, at most half of the shorter leg\n const r = Math.min(\n 4,\n Math.hypot(p.x - prev.x, p.y - prev.y) / 2,\n Math.hypot(next.x - p.x, next.y - p.y) / 2,\n );\n ctx.arcTo(p.x, p.y, next.x, next.y, r);\n } else {\n ctx.lineTo(p.x, p.y);\n }\n }\n ctx.stroke();\n const [tip, b0, b1] = a.head;\n if (tip && b0 && b1) {\n ctx.beginPath();\n ctx.moveTo(tip.x, tip.y);\n ctx.lineTo(b0.x, b0.y);\n ctx.lineTo(b1.x, b1.y);\n ctx.closePath();\n ctx.fill();\n }\n }\n};\n\nexport const drawForeground = (\n ctx: CanvasRenderingContext2D,\n input: ForegroundInput,\n) => {\n const { scales, theme } = input;\n const { plot } = scales;\n if (input.clear !== false) ctx.clearRect(0, 0, input.width, input.height);\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n\n for (const c of input.connectors ?? []) {\n ctx.strokeStyle = c.color;\n ctx.lineWidth = c.width;\n ctx.setLineDash([...c.dash]);\n ctx.beginPath();\n // crisp hairlines along the pixel grid\n const along = c.y0 === c.y1;\n const x0 = along ? c.x0 : crisp(c.x0);\n const y0 = along ? crisp(c.y0) : c.y0;\n ctx.moveTo(x0, y0);\n ctx.lineTo(along ? c.x1 : x0, along ? y0 : c.y1);\n ctx.stroke();\n }\n ctx.setLineDash([]);\n if (input.arrows?.length) drawArrows(ctx, input.arrows);\n\n const halo = toCss(theme.background, 0.9);\n const occupied: Rect[] = [];\n const labelHeight = theme.fontSize + 4;\n\n for (const a of input.annotations) {\n if (a.type !== \"line\") continue;\n const color = toCss(a.color);\n ctx.strokeStyle = color;\n ctx.lineWidth = a.width;\n ctx.setLineDash(a.dash);\n ctx.beginPath();\n const where = lineOf(a, scales);\n if (!where.vertical) {\n const py = crisp(where.at);\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"bottom\";\n haloText(ctx, a.label, plot.x + plot.width - 6, py - 3, color, halo);\n }\n } else {\n const px = crisp(where.at);\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n haloText(ctx, a.label, px + 5, plot.y + 5, color, halo);\n }\n }\n }\n ctx.setLineDash([]);\n\n // labels of areas\n for (const a of input.annotations) {\n if (a.type !== \"rect\" || !hasAreaTitle(a)) continue;\n const title = areaTitleLayout(\n a,\n rectOf(a, scales),\n theme.fontSize,\n (text, size, weight) => {\n ctx.font = font(theme, size, weight);\n return ctx.measureText(text).width;\n },\n );\n if (!title) continue;\n const color = toCss(a.labelColor);\n const muted = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n for (const p of title.parts) {\n const cy = p.y + p.height / 2;\n if (p.kind === \"badge\") {\n const h = p.height - 2;\n pill(ctx, p.x, cy - h / 2, p.width, h);\n ctx.fillStyle = toCss(a.labelColor, 0.16);\n ctx.fill();\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = color;\n ctx.fillText(p.text, p.x + 5, cy);\n continue;\n }\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = p.kind === \"label\" ? color : muted;\n ctx.fillText(p.text, p.x, cy);\n }\n occupied.push(title.box);\n }\n\n // free texts\n for (const a of input.annotations) {\n if (a.type !== \"text\" || !a.text) continue;\n ctx.font = font(theme, theme.fontSize, a.weight);\n const box = textBox(a, scales, ctx.measureText(a.text).width, labelHeight);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n haloText(ctx, a.text, box.x, box.y + box.height / 2, toCss(a.color), halo);\n occupied.push(box);\n }\n\n // point labels\n let placed: { label: PointLabel; box: Rect }[] = [];\n if (input.pointLabels.length) {\n ctx.font = font(theme);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n const textColor = toCss(theme.text, 0.85);\n placed = placeLabels(\n input.pointLabels,\n plot,\n (t) => ctx.measureText(t).width,\n labelHeight - 2,\n occupied,\n );\n for (const { label, box } of placed) {\n if (label.hidden) continue;\n const y = box.y + box.height / 2;\n if (label.color) {\n ctx.fillStyle = label.color;\n ctx.fillText(label.text, box.x, y);\n } else haloText(ctx, label.text, box.x, y, textColor, halo);\n }\n }\n ctx.restore();\n return placed;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"overlay.cjs","names":["mix","relativeLuminance","toScreen","screenRect","toCss","require_color","require_layout","INSIDE_PAD","insideLabelColor","alpha","fill","seen","background","l","font","theme","weight","size","crisp","v","pill","r","h","w","ctx","x","y","textBox","s","at","a","free","px","plot","py","width","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","drawBackground","input","scales","bottomTicks","yTicks","xTicks","leftTicks","bottomPx","leftPx","base","lastRight","order","i","b","left","lastBottom","rows","rowHeight","y2","y2Ticks","right","overlaps","inside","haloText","halo","color","insideBox","bar","x0","x1","y0","y1","CELL_PAD","LABEL_GAP","distanceTo","cellBox","bounds","slack","others","dots","d","c","spaced","occupied","o","own","far","gap","sideY","sides","beside","side","corners","stacked","box","cuts","cw","best","total","keep","boxes","cut","placeLabels","placed","labels","fit","above","below","drawArrows","arrows","pts","first","next","prev","tip","b0","b1","drawForeground","labelHeight","where","title","muted","cy","textColor"],"sources":["../../../../charts/src/engine/overlay.ts"],"sourcesContent":["// Canvas2D layers around the data: background (areas, grid, axes, tick\n// labels) and foreground (reference lines, annotation and point labels).\n\nimport { mix, relativeLuminance, toCss, type Rgba } from \"./color\";\nimport type { AxisTicks } from \"./axis\";\nimport { screenRect, toScreen, type Rect, type Scales } from \"./layout\";\nimport type { AxisModel } from \"./model\";\nimport type { ChartTheme } from \"./theme\";\nimport type { ChartLabelPosition } from \"./types\";\n\nexport interface ResolvedRect {\n type: \"rect\";\n x0?: number;\n x1?: number;\n y0?: number;\n y1?: number;\n color: Rgba;\n opacity: number;\n label?: string;\n labelPosition: ChartLabelPosition;\n labelColor: Rgba;\n badge?: string;\n detail?: string;\n description?: string;\n}\n\nexport interface ResolvedLine {\n type: \"line\";\n axis: \"x\" | \"y\";\n value: number;\n color: Rgba;\n width: number;\n dash: number[];\n label?: string;\n}\n\nexport interface ResolvedText {\n type: \"text\";\n x?: number;\n y?: number;\n text: string;\n anchor: \"center\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n color: Rgba;\n weight: number;\n}\n\nexport type ResolvedAnnotation = ResolvedRect | ResolvedLine | ResolvedText;\n\nexport interface PointLabel {\n x: number;\n y: number;\n /** Radius of the dot */\n r: number;\n text: string;\n /**\n * Fixed side (bar values: above / below, left / right of horizontal\n * bars; `inside` the `bar`); any free side around the dot otherwise\n */\n placement?: \"above\" | \"below\" | \"left\" | \"right\" | \"inside\";\n /** `inside` labels: the bar, in CSS pixels */\n bar?: Rect;\n /** `inside` labels: at the start of the bar (horizontal bars) or centered */\n align?: \"start\" | \"center\";\n /**\n * Text color contrasting with a solid bar (`inside` labels), drawn\n * without a halo; the text color of the theme with a halo otherwise\n */\n color?: string;\n /**\n * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS\n * pixels: on the side of the dot with more room, cut with an ellipsis\n * when it does not fit\n */\n bounds?: Rect;\n /**\n * Placed (it keeps its room) but not drawn: a card over the chart names\n * the point\n */\n hidden?: boolean;\n}\n\n/** Padding of the labels inside the bars, CSS pixels */\nconst INSIDE_PAD = 6;\n\n/**\n * Color of a text written on a bar of color `fill` (alpha included) over\n * `background`: white or near-black, whichever contrasts more; `undefined`\n * for translucent bars (the theme text color with a halo reads better)\n */\nexport const insideLabelColor = (\n fill: Rgba,\n background: Rgba,\n): string | undefined => {\n const alpha = fill[3];\n if (alpha < 0.6) return undefined;\n const seen = mix(background, fill, alpha);\n const l = relativeLuminance(seen);\n // WCAG contrast with white (L = 1) and with #111827 (L ≈ 0.012)\n return 1.05 / (l + 0.05) >= (l + 0.05) / 0.062\n ? \"#ffffff\"\n : \"rgba(17, 24, 39, 0.92)\";\n};\n\nexport const font = (theme: ChartTheme, size = theme.fontSize, weight = 400) =>\n `${weight} ${size}px ${theme.fontFamily}`;\n\nconst crisp = (v: number) => Math.round(v) + 0.5;\n\n/** Path of a rounded box with half-height corners */\nconst pill = (\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n) => {\n const r = Math.min(h / 2, w / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.arcTo(x + w, y, x + w, y + r, r);\n ctx.lineTo(x + w, y + h - r);\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\n ctx.lineTo(x + r, y + h);\n ctx.arcTo(x, y + h, x, y + h - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n};\n\n/** Box of a text annotation, kept inside the plot */\nexport const textBox = (\n a: ResolvedText,\n s: Scales,\n width: number,\n height: number,\n): Rect => {\n const { plot } = s;\n const at = toScreen(s, a.x ?? 0, a.y ?? 0);\n const free = s.horizontal\n ? { x: a.y === undefined, y: a.x === undefined }\n : { x: a.x === undefined, y: a.y === undefined };\n const px = free.x ? plot.x + plot.width / 2 : at.x;\n const py = free.y ? plot.y + plot.height / 2 : at.y;\n const gap = 6;\n let x = px - width / 2;\n let y = py - height / 2;\n if (a.anchor === \"top\") y = py + gap;\n else if (a.anchor === \"bottom\") y = py - gap - height;\n else if (a.anchor === \"left\") x = px + gap;\n else if (a.anchor === \"right\") x = px - gap - width;\n x = Math.max(plot.x + gap, Math.min(x, plot.x + plot.width - gap - width));\n y = Math.max(plot.y + 2, Math.min(y, plot.y + plot.height - 2 - height));\n return { x, y, width, height };\n};\n\n/** Screen box of an area annotation, clipped to the plot */\nexport const rectOf = (a: ResolvedRect, s: Scales): Rect => {\n const { plot } = s;\n // clamp every edge to the plot first: an open edge maps to ±Infinity and\n // `Infinity - Infinity` would make the size NaN (nothing drawn)\n const [xLo, xHi] = s.horizontal\n ? [plot.y, plot.y + plot.height]\n : [plot.x, plot.x + plot.width];\n const [yLo, yHi] = s.horizontal\n ? [plot.x, plot.x + plot.width]\n : [plot.y, plot.y + plot.height];\n const along = (px: number, lo: number, hi: number) =>\n px < lo ? lo : px > hi ? hi : px;\n return screenRect(\n s,\n along(s.xToPx(a.x0 ?? -Infinity), xLo, xHi),\n along(s.xToPx(a.x1 ?? Infinity), xLo, xHi),\n along(s.yToPx(a.y0 ?? -Infinity), yLo, yHi),\n along(s.yToPx(a.y1 ?? Infinity), yLo, yHi),\n );\n};\n\n/** A text of the title block of an area: badge, label, detail or description */\nexport interface AreaText {\n kind: \"badge\" | \"label\" | \"detail\" | \"description\";\n text: string;\n /** Box of the text (the pill of a badge), CSS pixels */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Font size and weight */\n size: number;\n weight: number;\n}\n\n/** Title block of an area annotation, in its `labelPosition` corner */\nexport interface AreaTitle {\n parts: AreaText[];\n /** Box around the parts (the point labels avoid it) */\n box: Rect;\n}\n\n/** Whether an area annotation has a title block */\nexport const hasAreaTitle = (a: ResolvedRect): boolean =>\n !!(a.label || a.badge || a.detail || a.description);\n\n/** Text cut with an ellipsis to fit `max` pixels (\"\" when nothing fits) */\nconst fitText = (\n text: string,\n max: number,\n width: (text: string) => number,\n): string => {\n if (width(text) <= max) return text;\n const chars = Array.from(text);\n let lo = 0;\n let hi = chars.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (width(`${chars.slice(0, mid).join(\"\")}…`) <= max) lo = mid;\n else hi = mid - 1;\n }\n return lo > 0 ? `${chars.slice(0, lo).join(\"\").trimEnd()}…` : \"\";\n};\n\n/**\n * Layout of the title block of an area: `[badge] label detail` on the first\n * line, the description under it; the block sits in the `labelPosition`\n * corner, 10px from the edges, and the texts are cut to the area width\n */\nexport const areaTitleLayout = (\n a: ResolvedRect,\n r: Rect,\n fontSize: number,\n measure: (text: string, size: number, weight: number) => number,\n): AreaTitle | null => {\n if (!hasAreaTitle(a) || r.width <= 0 || r.height <= 0) return null;\n const pad = 10;\n const lineHeight = fontSize + 4;\n const max = Math.max(0, r.width - pad * 2);\n const labelSize = fontSize + 1;\n const badgeSize = Math.max(9, fontSize - 1);\n const gap = 6;\n const badge = a.badge\n ? fitText(a.badge, Math.max(0, max - 10), (t) => measure(t, badgeSize, 700))\n : \"\";\n const badgeWidth = badge ? measure(badge, badgeSize, 700) + 10 : 0;\n let detail = a.detail ?? \"\";\n let detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n const room = () =>\n max - (badge ? badgeWidth + gap : 0) - (detail ? detailWidth + gap : 0);\n // a narrow area keeps the title rather than the detail\n if (detail && a.label && room() < 32) {\n detail = \"\";\n detailWidth = 0;\n }\n if (detail && room() < 0) {\n detail = fitText(\n detail,\n Math.max(0, max - (badge ? badgeWidth + gap : 0)),\n (t) => measure(t, fontSize, 500),\n );\n detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n }\n const label = a.label\n ? fitText(a.label, Math.max(0, room()), (t) => measure(t, labelSize, 600))\n : \"\";\n const line: AreaText[] = [];\n if (badge)\n line.push({\n kind: \"badge\",\n text: badge,\n x: 0,\n y: 0,\n width: badgeWidth,\n height: lineHeight,\n size: badgeSize,\n weight: 700,\n });\n if (label)\n line.push({\n kind: \"label\",\n text: label,\n x: 0,\n y: 0,\n width: measure(label, labelSize, 600),\n height: lineHeight,\n size: labelSize,\n weight: 600,\n });\n if (detail)\n line.push({\n kind: \"detail\",\n text: detail,\n x: 0,\n y: 0,\n width: detailWidth,\n height: lineHeight,\n size: fontSize,\n weight: 500,\n });\n const description = a.description\n ? fitText(a.description, max, (t) => measure(t, fontSize, 400))\n : \"\";\n const lineWidth =\n line.reduce((sum, p) => sum + p.width, 0) +\n Math.max(0, line.length - 1) * gap;\n const descriptionWidth = description\n ? measure(description, fontSize, 400)\n : 0;\n if (!line.length && !description) return null;\n const height =\n (line.length ? lineHeight : 0) +\n (description ? lineHeight + (line.length ? 2 : 0) : 0);\n const pos = a.labelPosition;\n const top = pos.startsWith(\"top\")\n ? r.y + pad\n : pos.startsWith(\"bottom\")\n ? r.y + r.height - pad - height\n : r.y + (r.height - height) / 2;\n const startOf = (width: number) =>\n pos.endsWith(\"left\")\n ? r.x + pad\n : pos.endsWith(\"right\")\n ? r.x + r.width - pad - width\n : r.x + (r.width - width) / 2;\n const parts: AreaText[] = [];\n let x = startOf(lineWidth);\n for (const p of line) {\n parts.push({ ...p, x, y: top });\n x += p.width + gap;\n }\n if (description)\n parts.push({\n kind: \"description\",\n text: description,\n x: startOf(descriptionWidth),\n y: top + (line.length ? lineHeight + 2 : 0),\n width: descriptionWidth,\n height: lineHeight,\n size: fontSize,\n weight: 400,\n });\n const width = Math.max(lineWidth, descriptionWidth);\n return {\n parts,\n box: { x: startOf(width), y: top, width, height },\n };\n};\n\n/**\n * Where a reference line goes: `vertical` lines run at screen x `at`,\n * horizontal ones at screen y `at`\n */\nexport const lineOf = (\n a: ResolvedLine,\n s: Scales,\n): { vertical: boolean; at: number } => {\n const vertical = (a.axis === \"x\") !== s.horizontal;\n return {\n vertical,\n at: a.axis === \"x\" ? s.xToPx(a.value) : s.yToPx(a.value),\n };\n};\n\nexport interface BackgroundInput {\n width: number;\n height: number;\n scales: Scales;\n x: AxisModel;\n y: AxisModel;\n xTicks: AxisTicks;\n yTicks: AxisTicks;\n /** Right axis (dual axis charts) */\n y2?: AxisModel | null;\n y2Ticks?: AxisTicks | null;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n}\n\nexport const drawBackground = (\n ctx: CanvasRenderingContext2D,\n input: BackgroundInput,\n) => {\n const { scales, theme, xTicks, yTicks } = input;\n const { plot } = scales;\n // horizontal charts: the value axis along the bottom, the x axis on the left\n const x = scales.horizontal ? input.y : input.x;\n const y = scales.horizontal ? input.x : input.y;\n const bottomTicks = scales.horizontal ? yTicks : xTicks;\n const leftTicks = scales.horizontal ? xTicks : yTicks;\n const bottomPx = scales.horizontal ? scales.yToPx : scales.xToPx;\n const leftPx = scales.horizontal ? scales.xToPx : scales.yToPx;\n ctx.clearRect(0, 0, input.width, input.height);\n\n // areas\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n for (const a of input.annotations) {\n if (a.type !== \"rect\") continue;\n const r = rectOf(a, scales);\n if (r.width <= 0 || r.height <= 0) continue;\n ctx.fillStyle = toCss(a.color, a.opacity);\n ctx.fillRect(r.x, r.y, r.width, r.height);\n }\n ctx.restore();\n\n // grid\n ctx.lineWidth = 1;\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n if (y.grid) {\n for (const v of leftTicks.values) {\n const py = crisp(leftPx(v));\n if (py < plot.y - 1 || py > plot.y + plot.height + 1) continue;\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n }\n }\n if (x.grid) {\n for (const v of bottomTicks.values) {\n const px = crisp(bottomPx(v));\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n }\n }\n ctx.stroke();\n\n const line = Math.ceil(theme.fontSize * 1.4);\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n\n // x axis\n if (x.visible) {\n ctx.strokeStyle = toCss(theme.axis);\n ctx.beginPath();\n const base = crisp(plot.y + plot.height);\n ctx.moveTo(plot.x, base);\n ctx.lineTo(plot.x + plot.width, base);\n ctx.stroke();\n ctx.textBaseline = \"top\";\n ctx.textAlign = \"center\";\n let lastRight = -Infinity;\n // left to right (reversed axes list their ticks right to left)\n const order = bottomTicks.values\n .map((v, i) => ({ px: bottomPx(v), text: bottomTicks.labels[i] }))\n .sort((a, b) => a.px - b.px);\n for (const { px, text } of order) {\n if (px < plot.x - 0.5 || px > plot.x + plot.width + 0.5) continue;\n const w = ctx.measureText(text).width;\n const left = Math.max(0, Math.min(input.width - w, px - w / 2));\n if (left < lastRight + 6) continue;\n lastRight = left + w;\n ctx.fillText(text, left + w / 2, plot.y + plot.height + 7);\n }\n if (x.title) {\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.fillText(\n x.title,\n plot.x + plot.width / 2,\n plot.y + plot.height + line + 10,\n );\n }\n }\n\n // y axis\n if (y.visible) {\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"middle\";\n let lastBottom = -Infinity;\n // top to bottom: category rows of horizontal charts never overlap\n const rows = leftTicks.values\n .map((v, i) => ({ py: leftPx(v), text: leftTicks.labels[i] }))\n .sort((a, b) => a.py - b.py);\n const rowHeight = theme.fontSize + 2;\n for (const { py, text } of rows) {\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) continue;\n if (scales.horizontal) {\n if (py - rowHeight / 2 < lastBottom) continue;\n lastBottom = py + rowHeight / 2;\n }\n ctx.fillText(text, plot.x - 8, py);\n }\n if (y.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(line / 2 + 4, plot.y + plot.height / 2);\n ctx.rotate(-Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y.title, 0, 0);\n ctx.restore();\n }\n }\n\n // right axis\n const y2 = scales.horizontal ? null : input.y2;\n const y2Ticks = input.y2Ticks;\n if (y2 && y2Ticks && y2.visible) {\n const right = plot.x + plot.width;\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n y2Ticks.values.forEach((v, i) => {\n const py = scales.yToPx(v);\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) return;\n ctx.fillText(y2Ticks.labels[i], right + 8, py);\n });\n if (y2.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(input.width - line / 2 - 4, plot.y + plot.height / 2);\n ctx.rotate(Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y2.title, 0, 0);\n ctx.restore();\n }\n }\n};\n\nconst overlaps = (a: Rect, b: Rect) =>\n a.x < b.x + b.width &&\n b.x < a.x + a.width &&\n a.y < b.y + b.height &&\n b.y < a.y + a.height;\n\nconst inside = (r: Rect, plot: Rect) =>\n r.x >= plot.x &&\n r.y >= plot.y &&\n r.x + r.width <= plot.x + plot.width &&\n r.y + r.height <= plot.y + plot.height;\n\n/** Text with a halo in the background color (readable over data) */\nconst haloText = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n color: string,\n halo: string,\n) => {\n ctx.lineWidth = 3;\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = halo;\n ctx.strokeText(text, x, y);\n ctx.fillStyle = color;\n ctx.fillText(text, x, y);\n};\n\n/**\n * Box of a label inside its bar (the visible part of it): the text cut with\n * an ellipsis to fit, at the start of horizontal bars and centered in\n * vertical ones; `null` when the bar is too small\n */\nconst insideBox = (\n label: PointLabel,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n): { label: PointLabel; box: Rect } | null => {\n const bar = label.bar;\n if (!bar) return null;\n const x0 = Math.max(bar.x, plot.x);\n const x1 = Math.min(bar.x + bar.width, plot.x + plot.width);\n const y0 = Math.max(bar.y, plot.y);\n const y1 = Math.min(bar.y + bar.height, plot.y + plot.height);\n if (y1 - y0 < height - 2) return null;\n const text = fitText(label.text, x1 - x0 - INSIDE_PAD * 2, measure);\n if (!text) return null;\n const w = measure(text);\n const x = label.align === \"start\" ? x0 + INSIDE_PAD : (x0 + x1) / 2 - w / 2;\n return {\n label: text === label.text ? label : { ...label, text },\n box: { x, y: (y0 + y1) / 2 - height / 2, width: w, height },\n };\n};\n\n/** Room kept between a label and the edges of its cell, CSS pixels */\nconst CELL_PAD = 2;\n/** Room kept between two labels of a cell (they never touch), CSS pixels */\nconst LABEL_GAP = { x: 4, y: 2 };\n\n/** Distance from a point to the nearest point of a box */\nconst distanceTo = (x: number, y: number, r: Rect) =>\n Math.hypot(\n Math.max(r.x - x, 0, x - (r.x + r.width)),\n Math.max(r.y - y, 0, y - (r.y + r.height)),\n );\n\n/** A dot of a cell label: its label is told apart from the others by it */\ntype Dot = Pick<PointLabel, \"x\" | \"y\" | \"r\">;\n\n/**\n * Box of a label kept inside a cell of the plot (`bounds`): beside the dot\n * on the side with more room in the cell (moved up or down into the cell\n * near its edges), else above or below it (moved sideways into the cell),\n * else beside it half a line up or down;\n * cut with an ellipsis to the room left when the whole text fits nowhere;\n * `null` when no free slot is left. A slot is free when it keeps a gap to\n * the other labels and its own dot is the nearest one (it covers no other\n * dot): a crowded cell never pairs a name with the wrong dot\n */\nconst cellBox = (\n label: PointLabel,\n bounds: Rect,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: readonly Rect[],\n dots: readonly Dot[] = [],\n): { label: PointLabel; box: Rect } | null => {\n const x0 = Math.max(bounds.x, plot.x) + CELL_PAD;\n const x1 = Math.min(bounds.x + bounds.width, plot.x + plot.width) - CELL_PAD;\n const y0 = Math.max(bounds.y, plot.y) + CELL_PAD;\n const y1 =\n Math.min(bounds.y + bounds.height, plot.y + plot.height) - CELL_PAD;\n if (x1 - x0 <= 0 || y1 - y0 < height) return null;\n // a hair of slack: a text cut to the exact room ends on the edge\n const slack = {\n x: x0 - 0.01,\n y: y0 - 0.01,\n width: x1 - x0 + 0.02,\n height: y1 - y0 + 0.02,\n };\n // the other dots: those at the very spot of this one count as its own\n const others = dots.filter(\n (d) => Math.abs(d.x - label.x) >= 0.5 || Math.abs(d.y - label.y) >= 0.5,\n );\n const free = (c: Rect) => {\n if (!inside(c, slack)) return false;\n const spaced = {\n x: c.x - LABEL_GAP.x,\n y: c.y - LABEL_GAP.y,\n width: c.width + LABEL_GAP.x * 2,\n height: c.height + LABEL_GAP.y * 2,\n };\n if (occupied.some((o) => overlaps(o, spaced))) return false;\n const own = distanceTo(label.x, label.y, c);\n return others.every((d) => {\n const far = distanceTo(d.x, d.y, c);\n return far >= d.r + 2 && far > own;\n });\n };\n const gap = label.r + 4;\n // centered on the dot, moved into the cell near its top or bottom edge\n const sideY = Math.min(Math.max(label.y - height / 2, y0), y1 - height);\n const room = { right: x1 - (label.x + gap), left: label.x - gap - x0 };\n const sides: (\"right\" | \"left\")[] =\n room.right >= room.left ? [\"right\", \"left\"] : [\"left\", \"right\"];\n const beside = (side: \"right\" | \"left\", w: number): Rect[] => [\n {\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: sideY,\n width: w,\n height,\n },\n ];\n // beside the dot, raised or lowered by half a line: a crowded cell gets\n // more slots still next to their own dot\n const corners = (side: \"right\" | \"left\", w: number): Rect[] =>\n [label.y - height - 1, label.y + 1].map((y) => ({\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: Math.min(Math.max(y, y0), y1 - height),\n width: w,\n height,\n }));\n const stacked = (w: number): Rect[] => {\n // slid sideways into the cell near its edges (still over the dot)\n const x = Math.min(Math.max(label.x - w / 2, x0), x1 - w);\n return [\n { x, y: label.y - gap - height, width: w, height },\n { x, y: label.y + gap, width: w, height },\n ];\n };\n const w = measure(label.text);\n const whole = [\n ...beside(sides[0]!, w),\n ...beside(sides[1]!, w),\n ...stacked(w),\n ...corners(sides[0]!, w),\n ...corners(sides[1]!, w),\n ];\n const box = whole.find(free);\n if (box) return { label, box };\n // the whole text fits nowhere: cut it to the room beside the dot or above\n // / below it, keeping the longest text (the roomiest side on ties)\n const cuts: [number, (w: number) => Rect[]][] = [\n [\n room[sides[0]!],\n (cw) => [...beside(sides[0]!, cw), ...corners(sides[0]!, cw)],\n ],\n [\n room[sides[1]!],\n (cw) => [...beside(sides[1]!, cw), ...corners(sides[1]!, cw)],\n ],\n [x1 - x0, stacked],\n ];\n let best: { label: PointLabel; box: Rect } | null = null;\n // a cut keeps enough of the name to tell it (else the label is skipped,\n // like an overlapping one: the tooltip still names the point)\n const total = Array.from(label.text).length;\n const keep = Math.min(4, Math.ceil(total * 0.4));\n for (const [max, boxes] of cuts) {\n const text = fitText(label.text, max, measure);\n if (!text || (best && text.length <= best.label.text.length)) continue;\n if (Array.from(text).length - 1 < keep) continue;\n const cut = boxes(measure(text)).find(free);\n if (cut) best = { label: { ...label, text }, box: cut };\n }\n return best;\n};\n\n/** Greedy placement: right, left, above, below the dot; skipped when no slot is free */\nexport const placeLabels = (\n labels: readonly PointLabel[],\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: Rect[] = [],\n): { label: PointLabel; box: Rect }[] => {\n const placed: { label: PointLabel; box: Rect }[] = [];\n // the dots of the labels kept in cells (labels placed later included)\n const dots = labels.filter((label) => label.bounds);\n for (const label of labels) {\n if (label.placement === \"inside\") {\n const fit = insideBox(label, plot, measure, height);\n if (fit) placed.push(fit);\n continue;\n }\n if (label.bounds) {\n const fit = cellBox(\n label,\n label.bounds,\n plot,\n measure,\n height,\n occupied,\n dots,\n );\n if (!fit) continue;\n occupied.push(fit.box);\n placed.push(fit);\n continue;\n }\n const w = measure(label.text);\n const gap = label.r + 4;\n const above = {\n x: label.x - w / 2,\n y: label.y - gap - height,\n width: w,\n height,\n };\n const below = { x: label.x - w / 2, y: label.y + gap, width: w, height };\n const right = {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const left = {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const candidates: Rect[] =\n label.placement === \"above\"\n ? [above]\n : label.placement === \"below\"\n ? [below]\n : label.placement === \"right\"\n ? [right, left]\n : label.placement === \"left\"\n ? [left, right]\n : [\n {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n },\n {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n },\n above,\n below,\n ];\n const box = candidates.find(\n (c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)),\n );\n if (!box) continue;\n occupied.push(box);\n placed.push({ label, box });\n }\n return placed;\n};\n\nexport interface ForegroundInput {\n width: number;\n height: number;\n scales: Scales;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n pointLabels: readonly PointLabel[];\n /**\n * Clears the canvas first (off when the layers share one canvas)\n * @default true\n */\n clear?: boolean;\n /** Lines between consecutive bars (waterfall connectors), drawn first */\n connectors?: readonly {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n color: string;\n width: number;\n dash: readonly number[];\n }[];\n /** Dependency arrows (Gantt charts), drawn over the connectors */\n arrows?: readonly ArrowPath[];\n}\n\n/** An elbow arrow in stage pixels (see `dependencyArrows`) */\nexport interface ArrowPath {\n points: readonly { x: number; y: number }[];\n head: readonly { x: number; y: number }[];\n color: string;\n width: number;\n}\n\n/** Elbow arrows: polylines with rounded corners and filled heads */\nexport const drawArrows = (\n ctx: CanvasRenderingContext2D,\n arrows: readonly ArrowPath[],\n) => {\n for (const a of arrows) {\n const pts = a.points;\n const first = pts[0];\n if (!first) continue;\n ctx.strokeStyle = a.color;\n ctx.fillStyle = a.color;\n ctx.lineWidth = a.width;\n ctx.lineJoin = \"round\";\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (let i = 1; i < pts.length; i++) {\n const p = pts[i]!;\n const next = pts[i + 1];\n const prev = pts[i - 1]!;\n if (next && typeof ctx.arcTo === \"function\") {\n // rounded elbow, at most half of the shorter leg\n const r = Math.min(\n 4,\n Math.hypot(p.x - prev.x, p.y - prev.y) / 2,\n Math.hypot(next.x - p.x, next.y - p.y) / 2,\n );\n ctx.arcTo(p.x, p.y, next.x, next.y, r);\n } else {\n ctx.lineTo(p.x, p.y);\n }\n }\n ctx.stroke();\n const [tip, b0, b1] = a.head;\n if (tip && b0 && b1) {\n ctx.beginPath();\n ctx.moveTo(tip.x, tip.y);\n ctx.lineTo(b0.x, b0.y);\n ctx.lineTo(b1.x, b1.y);\n ctx.closePath();\n ctx.fill();\n }\n }\n};\n\nexport const drawForeground = (\n ctx: CanvasRenderingContext2D,\n input: ForegroundInput,\n) => {\n const { scales, theme } = input;\n const { plot } = scales;\n if (input.clear !== false) ctx.clearRect(0, 0, input.width, input.height);\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n\n for (const c of input.connectors ?? []) {\n ctx.strokeStyle = c.color;\n ctx.lineWidth = c.width;\n ctx.setLineDash([...c.dash]);\n ctx.beginPath();\n // crisp hairlines along the pixel grid\n const along = c.y0 === c.y1;\n const x0 = along ? c.x0 : crisp(c.x0);\n const y0 = along ? crisp(c.y0) : c.y0;\n ctx.moveTo(x0, y0);\n ctx.lineTo(along ? c.x1 : x0, along ? y0 : c.y1);\n ctx.stroke();\n }\n ctx.setLineDash([]);\n if (input.arrows?.length) drawArrows(ctx, input.arrows);\n\n const halo = toCss(theme.background, 0.9);\n const occupied: Rect[] = [];\n const labelHeight = theme.fontSize + 4;\n\n for (const a of input.annotations) {\n if (a.type !== \"line\") continue;\n const color = toCss(a.color);\n ctx.strokeStyle = color;\n ctx.lineWidth = a.width;\n ctx.setLineDash(a.dash);\n ctx.beginPath();\n const where = lineOf(a, scales);\n if (!where.vertical) {\n const py = crisp(where.at);\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"bottom\";\n haloText(ctx, a.label, plot.x + plot.width - 6, py - 3, color, halo);\n }\n } else {\n const px = crisp(where.at);\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n haloText(ctx, a.label, px + 5, plot.y + 5, color, halo);\n }\n }\n }\n ctx.setLineDash([]);\n\n // labels of areas\n for (const a of input.annotations) {\n if (a.type !== \"rect\" || !hasAreaTitle(a)) continue;\n const title = areaTitleLayout(\n a,\n rectOf(a, scales),\n theme.fontSize,\n (text, size, weight) => {\n ctx.font = font(theme, size, weight);\n return ctx.measureText(text).width;\n },\n );\n if (!title) continue;\n const color = toCss(a.labelColor);\n const muted = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n for (const p of title.parts) {\n const cy = p.y + p.height / 2;\n if (p.kind === \"badge\") {\n const h = p.height - 2;\n pill(ctx, p.x, cy - h / 2, p.width, h);\n ctx.fillStyle = toCss(a.labelColor, 0.16);\n ctx.fill();\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = color;\n ctx.fillText(p.text, p.x + 5, cy);\n continue;\n }\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = p.kind === \"label\" ? color : muted;\n ctx.fillText(p.text, p.x, cy);\n }\n occupied.push(title.box);\n }\n\n // free texts\n for (const a of input.annotations) {\n if (a.type !== \"text\" || !a.text) continue;\n ctx.font = font(theme, theme.fontSize, a.weight);\n const box = textBox(a, scales, ctx.measureText(a.text).width, labelHeight);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n haloText(ctx, a.text, box.x, box.y + box.height / 2, toCss(a.color), halo);\n occupied.push(box);\n }\n\n // point labels\n let placed: { label: PointLabel; box: Rect }[] = [];\n if (input.pointLabels.length) {\n ctx.font = font(theme);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n const textColor = toCss(theme.text, 0.85);\n placed = placeLabels(\n input.pointLabels,\n plot,\n (t) => ctx.measureText(t).width,\n labelHeight - 2,\n occupied,\n );\n for (const { label, box } of placed) {\n if (label.hidden) continue;\n const y = box.y + box.height / 2;\n if (label.color) {\n ctx.fillStyle = label.color;\n ctx.fillText(label.text, box.x, y);\n } else haloText(ctx, label.text, box.x, y, textColor, halo);\n }\n }\n ctx.restore();\n return placed;\n};\n"],"mappings":"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"}
@@ -209,7 +209,12 @@ var a = 6, o = (n, r) => {
209
209
  y: g,
210
210
  width: n,
211
211
  height: i
212
- }], T = (t) => {
212
+ }], T = (t, n) => [e.y - i - 1, e.y + 1].map((r) => ({
213
+ x: t === "right" ? e.x + h : e.x - h - n,
214
+ y: Math.min(Math.max(r, l), u - i),
215
+ width: n,
216
+ height: i
217
+ })), E = (t) => {
213
218
  let n = Math.min(Math.max(e.x - t / 2, s), c - t);
214
219
  return [{
215
220
  x: n,
@@ -222,25 +227,27 @@ var a = 6, o = (n, r) => {
222
227
  width: t,
223
228
  height: i
224
229
  }];
225
- }, E = r(e.text), D = [
226
- ...w(b[0], E),
227
- ...w(b[1], E),
228
- ...T(E)
230
+ }, D = r(e.text), O = [
231
+ ...w(b[0], D),
232
+ ...w(b[1], D),
233
+ ...E(D),
234
+ ...T(b[0], D),
235
+ ...T(b[1], D)
229
236
  ].find(m);
230
- if (D) return {
237
+ if (O) return {
231
238
  label: e,
232
- box: D
239
+ box: O
233
240
  };
234
- let O = [
235
- [y[b[0]], (e) => w(b[0], e)],
236
- [y[b[1]], (e) => w(b[1], e)],
237
- [c - s, T]
238
- ], k = null, A = Array.from(e.text).length, j = Math.min(4, Math.ceil(A * .4));
239
- for (let [t, n] of O) {
241
+ let k = [
242
+ [y[b[0]], (e) => [...w(b[0], e), ...T(b[0], e)]],
243
+ [y[b[1]], (e) => [...w(b[1], e), ...T(b[1], e)]],
244
+ [c - s, E]
245
+ ], A = null, j = Array.from(e.text).length, M = Math.min(4, Math.ceil(j * .4));
246
+ for (let [t, n] of k) {
240
247
  let i = p(e.text, t, r);
241
- if (!i || k && i.length <= k.label.text.length || Array.from(i).length - 1 < j) continue;
248
+ if (!i || A && i.length <= A.label.text.length || Array.from(i).length - 1 < M) continue;
242
249
  let a = n(r(i)).find(m);
243
- a && (k = {
250
+ a && (A = {
244
251
  label: {
245
252
  ...e,
246
253
  text: i
@@ -248,7 +255,7 @@ var a = 6, o = (n, r) => {
248
255
  box: a
249
256
  });
250
257
  }
251
- return k;
258
+ return A;
252
259
  }, T = (e, t, n, r, i = []) => {
253
260
  let a = [], o = e.filter((e) => e.bounds);
254
261
  for (let s of e) {
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","names":["INSIDE_PAD","insideLabelColor","alpha","fill","seen","mix","background","l","relativeLuminance","font","theme","weight","size","crisp","v","pill","r","h","w","ctx","x","y","textBox","s","at","toScreen","a","free","px","plot","py","width","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","screenRect","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","drawBackground","input","scales","bottomTicks","yTicks","xTicks","leftTicks","bottomPx","leftPx","toCss","base","lastRight","order","i","b","left","lastBottom","rows","rowHeight","y2","y2Ticks","right","overlaps","inside","haloText","halo","color","insideBox","bar","x0","x1","y0","y1","CELL_PAD","LABEL_GAP","distanceTo","cellBox","bounds","slack","others","dots","d","c","spaced","occupied","o","own","far","gap","sideY","sides","beside","side","stacked","box","cuts","cw","best","total","keep","boxes","cut","placeLabels","placed","labels","fit","above","below","drawArrows","arrows","pts","first","next","prev","tip","b0","b1","drawForeground","labelHeight","where","title","muted","cy","textColor"],"sources":["../../../../charts/src/engine/overlay.ts"],"sourcesContent":["// Canvas2D layers around the data: background (areas, grid, axes, tick\n// labels) and foreground (reference lines, annotation and point labels).\n\nimport { mix, relativeLuminance, toCss, type Rgba } from \"./color\";\nimport type { AxisTicks } from \"./axis\";\nimport { screenRect, toScreen, type Rect, type Scales } from \"./layout\";\nimport type { AxisModel } from \"./model\";\nimport type { ChartTheme } from \"./theme\";\nimport type { ChartLabelPosition } from \"./types\";\n\nexport interface ResolvedRect {\n type: \"rect\";\n x0?: number;\n x1?: number;\n y0?: number;\n y1?: number;\n color: Rgba;\n opacity: number;\n label?: string;\n labelPosition: ChartLabelPosition;\n labelColor: Rgba;\n badge?: string;\n detail?: string;\n description?: string;\n}\n\nexport interface ResolvedLine {\n type: \"line\";\n axis: \"x\" | \"y\";\n value: number;\n color: Rgba;\n width: number;\n dash: number[];\n label?: string;\n}\n\nexport interface ResolvedText {\n type: \"text\";\n x?: number;\n y?: number;\n text: string;\n anchor: \"center\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n color: Rgba;\n weight: number;\n}\n\nexport type ResolvedAnnotation = ResolvedRect | ResolvedLine | ResolvedText;\n\nexport interface PointLabel {\n x: number;\n y: number;\n /** Radius of the dot */\n r: number;\n text: string;\n /**\n * Fixed side (bar values: above / below, left / right of horizontal\n * bars; `inside` the `bar`); any free side around the dot otherwise\n */\n placement?: \"above\" | \"below\" | \"left\" | \"right\" | \"inside\";\n /** `inside` labels: the bar, in CSS pixels */\n bar?: Rect;\n /** `inside` labels: at the start of the bar (horizontal bars) or centered */\n align?: \"start\" | \"center\";\n /**\n * Text color contrasting with a solid bar (`inside` labels), drawn\n * without a halo; the text color of the theme with a halo otherwise\n */\n color?: string;\n /**\n * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS\n * pixels: on the side of the dot with more room, cut with an ellipsis\n * when it does not fit\n */\n bounds?: Rect;\n /**\n * Placed (it keeps its room) but not drawn: a card over the chart names\n * the point\n */\n hidden?: boolean;\n}\n\n/** Padding of the labels inside the bars, CSS pixels */\nconst INSIDE_PAD = 6;\n\n/**\n * Color of a text written on a bar of color `fill` (alpha included) over\n * `background`: white or near-black, whichever contrasts more; `undefined`\n * for translucent bars (the theme text color with a halo reads better)\n */\nexport const insideLabelColor = (\n fill: Rgba,\n background: Rgba,\n): string | undefined => {\n const alpha = fill[3];\n if (alpha < 0.6) return undefined;\n const seen = mix(background, fill, alpha);\n const l = relativeLuminance(seen);\n // WCAG contrast with white (L = 1) and with #111827 (L ≈ 0.012)\n return 1.05 / (l + 0.05) >= (l + 0.05) / 0.062\n ? \"#ffffff\"\n : \"rgba(17, 24, 39, 0.92)\";\n};\n\nexport const font = (theme: ChartTheme, size = theme.fontSize, weight = 400) =>\n `${weight} ${size}px ${theme.fontFamily}`;\n\nconst crisp = (v: number) => Math.round(v) + 0.5;\n\n/** Path of a rounded box with half-height corners */\nconst pill = (\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n) => {\n const r = Math.min(h / 2, w / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.arcTo(x + w, y, x + w, y + r, r);\n ctx.lineTo(x + w, y + h - r);\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\n ctx.lineTo(x + r, y + h);\n ctx.arcTo(x, y + h, x, y + h - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n};\n\n/** Box of a text annotation, kept inside the plot */\nexport const textBox = (\n a: ResolvedText,\n s: Scales,\n width: number,\n height: number,\n): Rect => {\n const { plot } = s;\n const at = toScreen(s, a.x ?? 0, a.y ?? 0);\n const free = s.horizontal\n ? { x: a.y === undefined, y: a.x === undefined }\n : { x: a.x === undefined, y: a.y === undefined };\n const px = free.x ? plot.x + plot.width / 2 : at.x;\n const py = free.y ? plot.y + plot.height / 2 : at.y;\n const gap = 6;\n let x = px - width / 2;\n let y = py - height / 2;\n if (a.anchor === \"top\") y = py + gap;\n else if (a.anchor === \"bottom\") y = py - gap - height;\n else if (a.anchor === \"left\") x = px + gap;\n else if (a.anchor === \"right\") x = px - gap - width;\n x = Math.max(plot.x + gap, Math.min(x, plot.x + plot.width - gap - width));\n y = Math.max(plot.y + 2, Math.min(y, plot.y + plot.height - 2 - height));\n return { x, y, width, height };\n};\n\n/** Screen box of an area annotation, clipped to the plot */\nexport const rectOf = (a: ResolvedRect, s: Scales): Rect => {\n const { plot } = s;\n // clamp every edge to the plot first: an open edge maps to ±Infinity and\n // `Infinity - Infinity` would make the size NaN (nothing drawn)\n const [xLo, xHi] = s.horizontal\n ? [plot.y, plot.y + plot.height]\n : [plot.x, plot.x + plot.width];\n const [yLo, yHi] = s.horizontal\n ? [plot.x, plot.x + plot.width]\n : [plot.y, plot.y + plot.height];\n const along = (px: number, lo: number, hi: number) =>\n px < lo ? lo : px > hi ? hi : px;\n return screenRect(\n s,\n along(s.xToPx(a.x0 ?? -Infinity), xLo, xHi),\n along(s.xToPx(a.x1 ?? Infinity), xLo, xHi),\n along(s.yToPx(a.y0 ?? -Infinity), yLo, yHi),\n along(s.yToPx(a.y1 ?? Infinity), yLo, yHi),\n );\n};\n\n/** A text of the title block of an area: badge, label, detail or description */\nexport interface AreaText {\n kind: \"badge\" | \"label\" | \"detail\" | \"description\";\n text: string;\n /** Box of the text (the pill of a badge), CSS pixels */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Font size and weight */\n size: number;\n weight: number;\n}\n\n/** Title block of an area annotation, in its `labelPosition` corner */\nexport interface AreaTitle {\n parts: AreaText[];\n /** Box around the parts (the point labels avoid it) */\n box: Rect;\n}\n\n/** Whether an area annotation has a title block */\nexport const hasAreaTitle = (a: ResolvedRect): boolean =>\n !!(a.label || a.badge || a.detail || a.description);\n\n/** Text cut with an ellipsis to fit `max` pixels (\"\" when nothing fits) */\nconst fitText = (\n text: string,\n max: number,\n width: (text: string) => number,\n): string => {\n if (width(text) <= max) return text;\n const chars = Array.from(text);\n let lo = 0;\n let hi = chars.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (width(`${chars.slice(0, mid).join(\"\")}…`) <= max) lo = mid;\n else hi = mid - 1;\n }\n return lo > 0 ? `${chars.slice(0, lo).join(\"\").trimEnd()}…` : \"\";\n};\n\n/**\n * Layout of the title block of an area: `[badge] label detail` on the first\n * line, the description under it; the block sits in the `labelPosition`\n * corner, 10px from the edges, and the texts are cut to the area width\n */\nexport const areaTitleLayout = (\n a: ResolvedRect,\n r: Rect,\n fontSize: number,\n measure: (text: string, size: number, weight: number) => number,\n): AreaTitle | null => {\n if (!hasAreaTitle(a) || r.width <= 0 || r.height <= 0) return null;\n const pad = 10;\n const lineHeight = fontSize + 4;\n const max = Math.max(0, r.width - pad * 2);\n const labelSize = fontSize + 1;\n const badgeSize = Math.max(9, fontSize - 1);\n const gap = 6;\n const badge = a.badge\n ? fitText(a.badge, Math.max(0, max - 10), (t) => measure(t, badgeSize, 700))\n : \"\";\n const badgeWidth = badge ? measure(badge, badgeSize, 700) + 10 : 0;\n let detail = a.detail ?? \"\";\n let detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n const room = () =>\n max - (badge ? badgeWidth + gap : 0) - (detail ? detailWidth + gap : 0);\n // a narrow area keeps the title rather than the detail\n if (detail && a.label && room() < 32) {\n detail = \"\";\n detailWidth = 0;\n }\n if (detail && room() < 0) {\n detail = fitText(\n detail,\n Math.max(0, max - (badge ? badgeWidth + gap : 0)),\n (t) => measure(t, fontSize, 500),\n );\n detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n }\n const label = a.label\n ? fitText(a.label, Math.max(0, room()), (t) => measure(t, labelSize, 600))\n : \"\";\n const line: AreaText[] = [];\n if (badge)\n line.push({\n kind: \"badge\",\n text: badge,\n x: 0,\n y: 0,\n width: badgeWidth,\n height: lineHeight,\n size: badgeSize,\n weight: 700,\n });\n if (label)\n line.push({\n kind: \"label\",\n text: label,\n x: 0,\n y: 0,\n width: measure(label, labelSize, 600),\n height: lineHeight,\n size: labelSize,\n weight: 600,\n });\n if (detail)\n line.push({\n kind: \"detail\",\n text: detail,\n x: 0,\n y: 0,\n width: detailWidth,\n height: lineHeight,\n size: fontSize,\n weight: 500,\n });\n const description = a.description\n ? fitText(a.description, max, (t) => measure(t, fontSize, 400))\n : \"\";\n const lineWidth =\n line.reduce((sum, p) => sum + p.width, 0) +\n Math.max(0, line.length - 1) * gap;\n const descriptionWidth = description\n ? measure(description, fontSize, 400)\n : 0;\n if (!line.length && !description) return null;\n const height =\n (line.length ? lineHeight : 0) +\n (description ? lineHeight + (line.length ? 2 : 0) : 0);\n const pos = a.labelPosition;\n const top = pos.startsWith(\"top\")\n ? r.y + pad\n : pos.startsWith(\"bottom\")\n ? r.y + r.height - pad - height\n : r.y + (r.height - height) / 2;\n const startOf = (width: number) =>\n pos.endsWith(\"left\")\n ? r.x + pad\n : pos.endsWith(\"right\")\n ? r.x + r.width - pad - width\n : r.x + (r.width - width) / 2;\n const parts: AreaText[] = [];\n let x = startOf(lineWidth);\n for (const p of line) {\n parts.push({ ...p, x, y: top });\n x += p.width + gap;\n }\n if (description)\n parts.push({\n kind: \"description\",\n text: description,\n x: startOf(descriptionWidth),\n y: top + (line.length ? lineHeight + 2 : 0),\n width: descriptionWidth,\n height: lineHeight,\n size: fontSize,\n weight: 400,\n });\n const width = Math.max(lineWidth, descriptionWidth);\n return {\n parts,\n box: { x: startOf(width), y: top, width, height },\n };\n};\n\n/**\n * Where a reference line goes: `vertical` lines run at screen x `at`,\n * horizontal ones at screen y `at`\n */\nexport const lineOf = (\n a: ResolvedLine,\n s: Scales,\n): { vertical: boolean; at: number } => {\n const vertical = (a.axis === \"x\") !== s.horizontal;\n return {\n vertical,\n at: a.axis === \"x\" ? s.xToPx(a.value) : s.yToPx(a.value),\n };\n};\n\nexport interface BackgroundInput {\n width: number;\n height: number;\n scales: Scales;\n x: AxisModel;\n y: AxisModel;\n xTicks: AxisTicks;\n yTicks: AxisTicks;\n /** Right axis (dual axis charts) */\n y2?: AxisModel | null;\n y2Ticks?: AxisTicks | null;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n}\n\nexport const drawBackground = (\n ctx: CanvasRenderingContext2D,\n input: BackgroundInput,\n) => {\n const { scales, theme, xTicks, yTicks } = input;\n const { plot } = scales;\n // horizontal charts: the value axis along the bottom, the x axis on the left\n const x = scales.horizontal ? input.y : input.x;\n const y = scales.horizontal ? input.x : input.y;\n const bottomTicks = scales.horizontal ? yTicks : xTicks;\n const leftTicks = scales.horizontal ? xTicks : yTicks;\n const bottomPx = scales.horizontal ? scales.yToPx : scales.xToPx;\n const leftPx = scales.horizontal ? scales.xToPx : scales.yToPx;\n ctx.clearRect(0, 0, input.width, input.height);\n\n // areas\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n for (const a of input.annotations) {\n if (a.type !== \"rect\") continue;\n const r = rectOf(a, scales);\n if (r.width <= 0 || r.height <= 0) continue;\n ctx.fillStyle = toCss(a.color, a.opacity);\n ctx.fillRect(r.x, r.y, r.width, r.height);\n }\n ctx.restore();\n\n // grid\n ctx.lineWidth = 1;\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n if (y.grid) {\n for (const v of leftTicks.values) {\n const py = crisp(leftPx(v));\n if (py < plot.y - 1 || py > plot.y + plot.height + 1) continue;\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n }\n }\n if (x.grid) {\n for (const v of bottomTicks.values) {\n const px = crisp(bottomPx(v));\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n }\n }\n ctx.stroke();\n\n const line = Math.ceil(theme.fontSize * 1.4);\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n\n // x axis\n if (x.visible) {\n ctx.strokeStyle = toCss(theme.axis);\n ctx.beginPath();\n const base = crisp(plot.y + plot.height);\n ctx.moveTo(plot.x, base);\n ctx.lineTo(plot.x + plot.width, base);\n ctx.stroke();\n ctx.textBaseline = \"top\";\n ctx.textAlign = \"center\";\n let lastRight = -Infinity;\n // left to right (reversed axes list their ticks right to left)\n const order = bottomTicks.values\n .map((v, i) => ({ px: bottomPx(v), text: bottomTicks.labels[i] }))\n .sort((a, b) => a.px - b.px);\n for (const { px, text } of order) {\n if (px < plot.x - 0.5 || px > plot.x + plot.width + 0.5) continue;\n const w = ctx.measureText(text).width;\n const left = Math.max(0, Math.min(input.width - w, px - w / 2));\n if (left < lastRight + 6) continue;\n lastRight = left + w;\n ctx.fillText(text, left + w / 2, plot.y + plot.height + 7);\n }\n if (x.title) {\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.fillText(\n x.title,\n plot.x + plot.width / 2,\n plot.y + plot.height + line + 10,\n );\n }\n }\n\n // y axis\n if (y.visible) {\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"middle\";\n let lastBottom = -Infinity;\n // top to bottom: category rows of horizontal charts never overlap\n const rows = leftTicks.values\n .map((v, i) => ({ py: leftPx(v), text: leftTicks.labels[i] }))\n .sort((a, b) => a.py - b.py);\n const rowHeight = theme.fontSize + 2;\n for (const { py, text } of rows) {\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) continue;\n if (scales.horizontal) {\n if (py - rowHeight / 2 < lastBottom) continue;\n lastBottom = py + rowHeight / 2;\n }\n ctx.fillText(text, plot.x - 8, py);\n }\n if (y.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(line / 2 + 4, plot.y + plot.height / 2);\n ctx.rotate(-Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y.title, 0, 0);\n ctx.restore();\n }\n }\n\n // right axis\n const y2 = scales.horizontal ? null : input.y2;\n const y2Ticks = input.y2Ticks;\n if (y2 && y2Ticks && y2.visible) {\n const right = plot.x + plot.width;\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n y2Ticks.values.forEach((v, i) => {\n const py = scales.yToPx(v);\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) return;\n ctx.fillText(y2Ticks.labels[i], right + 8, py);\n });\n if (y2.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(input.width - line / 2 - 4, plot.y + plot.height / 2);\n ctx.rotate(Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y2.title, 0, 0);\n ctx.restore();\n }\n }\n};\n\nconst overlaps = (a: Rect, b: Rect) =>\n a.x < b.x + b.width &&\n b.x < a.x + a.width &&\n a.y < b.y + b.height &&\n b.y < a.y + a.height;\n\nconst inside = (r: Rect, plot: Rect) =>\n r.x >= plot.x &&\n r.y >= plot.y &&\n r.x + r.width <= plot.x + plot.width &&\n r.y + r.height <= plot.y + plot.height;\n\n/** Text with a halo in the background color (readable over data) */\nconst haloText = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n color: string,\n halo: string,\n) => {\n ctx.lineWidth = 3;\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = halo;\n ctx.strokeText(text, x, y);\n ctx.fillStyle = color;\n ctx.fillText(text, x, y);\n};\n\n/**\n * Box of a label inside its bar (the visible part of it): the text cut with\n * an ellipsis to fit, at the start of horizontal bars and centered in\n * vertical ones; `null` when the bar is too small\n */\nconst insideBox = (\n label: PointLabel,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n): { label: PointLabel; box: Rect } | null => {\n const bar = label.bar;\n if (!bar) return null;\n const x0 = Math.max(bar.x, plot.x);\n const x1 = Math.min(bar.x + bar.width, plot.x + plot.width);\n const y0 = Math.max(bar.y, plot.y);\n const y1 = Math.min(bar.y + bar.height, plot.y + plot.height);\n if (y1 - y0 < height - 2) return null;\n const text = fitText(label.text, x1 - x0 - INSIDE_PAD * 2, measure);\n if (!text) return null;\n const w = measure(text);\n const x = label.align === \"start\" ? x0 + INSIDE_PAD : (x0 + x1) / 2 - w / 2;\n return {\n label: text === label.text ? label : { ...label, text },\n box: { x, y: (y0 + y1) / 2 - height / 2, width: w, height },\n };\n};\n\n/** Room kept between a label and the edges of its cell, CSS pixels */\nconst CELL_PAD = 2;\n/** Room kept between two labels of a cell (they never touch), CSS pixels */\nconst LABEL_GAP = { x: 4, y: 2 };\n\n/** Distance from a point to the nearest point of a box */\nconst distanceTo = (x: number, y: number, r: Rect) =>\n Math.hypot(\n Math.max(r.x - x, 0, x - (r.x + r.width)),\n Math.max(r.y - y, 0, y - (r.y + r.height)),\n );\n\n/** A dot of a cell label: its label is told apart from the others by it */\ntype Dot = Pick<PointLabel, \"x\" | \"y\" | \"r\">;\n\n/**\n * Box of a label kept inside a cell of the plot (`bounds`): beside the dot\n * on the side with more room in the cell (moved up or down into the cell\n * near its edges), else above or below it (moved sideways into the cell);\n * cut with an ellipsis to the room left when the whole text fits nowhere;\n * `null` when no free slot is left. A slot is free when it keeps a gap to\n * the other labels and its own dot is the nearest one (it covers no other\n * dot): a crowded cell never pairs a name with the wrong dot\n */\nconst cellBox = (\n label: PointLabel,\n bounds: Rect,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: readonly Rect[],\n dots: readonly Dot[] = [],\n): { label: PointLabel; box: Rect } | null => {\n const x0 = Math.max(bounds.x, plot.x) + CELL_PAD;\n const x1 = Math.min(bounds.x + bounds.width, plot.x + plot.width) - CELL_PAD;\n const y0 = Math.max(bounds.y, plot.y) + CELL_PAD;\n const y1 =\n Math.min(bounds.y + bounds.height, plot.y + plot.height) - CELL_PAD;\n if (x1 - x0 <= 0 || y1 - y0 < height) return null;\n // a hair of slack: a text cut to the exact room ends on the edge\n const slack = {\n x: x0 - 0.01,\n y: y0 - 0.01,\n width: x1 - x0 + 0.02,\n height: y1 - y0 + 0.02,\n };\n // the other dots: those at the very spot of this one count as its own\n const others = dots.filter(\n (d) => Math.abs(d.x - label.x) >= 0.5 || Math.abs(d.y - label.y) >= 0.5,\n );\n const free = (c: Rect) => {\n if (!inside(c, slack)) return false;\n const spaced = {\n x: c.x - LABEL_GAP.x,\n y: c.y - LABEL_GAP.y,\n width: c.width + LABEL_GAP.x * 2,\n height: c.height + LABEL_GAP.y * 2,\n };\n if (occupied.some((o) => overlaps(o, spaced))) return false;\n const own = distanceTo(label.x, label.y, c);\n return others.every((d) => {\n const far = distanceTo(d.x, d.y, c);\n return far >= d.r + 2 && far > own;\n });\n };\n const gap = label.r + 4;\n // centered on the dot, moved into the cell near its top or bottom edge\n const sideY = Math.min(Math.max(label.y - height / 2, y0), y1 - height);\n const room = { right: x1 - (label.x + gap), left: label.x - gap - x0 };\n const sides: (\"right\" | \"left\")[] =\n room.right >= room.left ? [\"right\", \"left\"] : [\"left\", \"right\"];\n const beside = (side: \"right\" | \"left\", w: number): Rect[] => [\n {\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: sideY,\n width: w,\n height,\n },\n ];\n const stacked = (w: number): Rect[] => {\n // slid sideways into the cell near its edges (still over the dot)\n const x = Math.min(Math.max(label.x - w / 2, x0), x1 - w);\n return [\n { x, y: label.y - gap - height, width: w, height },\n { x, y: label.y + gap, width: w, height },\n ];\n };\n const w = measure(label.text);\n const whole = [\n ...beside(sides[0]!, w),\n ...beside(sides[1]!, w),\n ...stacked(w),\n ];\n const box = whole.find(free);\n if (box) return { label, box };\n // the whole text fits nowhere: cut it to the room beside the dot or above\n // / below it, keeping the longest text (the roomiest side on ties)\n const cuts: [number, (w: number) => Rect[]][] = [\n [room[sides[0]!], (cw) => beside(sides[0]!, cw)],\n [room[sides[1]!], (cw) => beside(sides[1]!, cw)],\n [x1 - x0, stacked],\n ];\n let best: { label: PointLabel; box: Rect } | null = null;\n // a cut keeps enough of the name to tell it (else the label is skipped,\n // like an overlapping one: the tooltip still names the point)\n const total = Array.from(label.text).length;\n const keep = Math.min(4, Math.ceil(total * 0.4));\n for (const [max, boxes] of cuts) {\n const text = fitText(label.text, max, measure);\n if (!text || (best && text.length <= best.label.text.length)) continue;\n if (Array.from(text).length - 1 < keep) continue;\n const cut = boxes(measure(text)).find(free);\n if (cut) best = { label: { ...label, text }, box: cut };\n }\n return best;\n};\n\n/** Greedy placement: right, left, above, below the dot; skipped when no slot is free */\nexport const placeLabels = (\n labels: readonly PointLabel[],\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: Rect[] = [],\n): { label: PointLabel; box: Rect }[] => {\n const placed: { label: PointLabel; box: Rect }[] = [];\n // the dots of the labels kept in cells (labels placed later included)\n const dots = labels.filter((label) => label.bounds);\n for (const label of labels) {\n if (label.placement === \"inside\") {\n const fit = insideBox(label, plot, measure, height);\n if (fit) placed.push(fit);\n continue;\n }\n if (label.bounds) {\n const fit = cellBox(\n label,\n label.bounds,\n plot,\n measure,\n height,\n occupied,\n dots,\n );\n if (!fit) continue;\n occupied.push(fit.box);\n placed.push(fit);\n continue;\n }\n const w = measure(label.text);\n const gap = label.r + 4;\n const above = {\n x: label.x - w / 2,\n y: label.y - gap - height,\n width: w,\n height,\n };\n const below = { x: label.x - w / 2, y: label.y + gap, width: w, height };\n const right = {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const left = {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const candidates: Rect[] =\n label.placement === \"above\"\n ? [above]\n : label.placement === \"below\"\n ? [below]\n : label.placement === \"right\"\n ? [right, left]\n : label.placement === \"left\"\n ? [left, right]\n : [\n {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n },\n {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n },\n above,\n below,\n ];\n const box = candidates.find(\n (c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)),\n );\n if (!box) continue;\n occupied.push(box);\n placed.push({ label, box });\n }\n return placed;\n};\n\nexport interface ForegroundInput {\n width: number;\n height: number;\n scales: Scales;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n pointLabels: readonly PointLabel[];\n /**\n * Clears the canvas first (off when the layers share one canvas)\n * @default true\n */\n clear?: boolean;\n /** Lines between consecutive bars (waterfall connectors), drawn first */\n connectors?: readonly {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n color: string;\n width: number;\n dash: readonly number[];\n }[];\n /** Dependency arrows (Gantt charts), drawn over the connectors */\n arrows?: readonly ArrowPath[];\n}\n\n/** An elbow arrow in stage pixels (see `dependencyArrows`) */\nexport interface ArrowPath {\n points: readonly { x: number; y: number }[];\n head: readonly { x: number; y: number }[];\n color: string;\n width: number;\n}\n\n/** Elbow arrows: polylines with rounded corners and filled heads */\nexport const drawArrows = (\n ctx: CanvasRenderingContext2D,\n arrows: readonly ArrowPath[],\n) => {\n for (const a of arrows) {\n const pts = a.points;\n const first = pts[0];\n if (!first) continue;\n ctx.strokeStyle = a.color;\n ctx.fillStyle = a.color;\n ctx.lineWidth = a.width;\n ctx.lineJoin = \"round\";\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (let i = 1; i < pts.length; i++) {\n const p = pts[i]!;\n const next = pts[i + 1];\n const prev = pts[i - 1]!;\n if (next && typeof ctx.arcTo === \"function\") {\n // rounded elbow, at most half of the shorter leg\n const r = Math.min(\n 4,\n Math.hypot(p.x - prev.x, p.y - prev.y) / 2,\n Math.hypot(next.x - p.x, next.y - p.y) / 2,\n );\n ctx.arcTo(p.x, p.y, next.x, next.y, r);\n } else {\n ctx.lineTo(p.x, p.y);\n }\n }\n ctx.stroke();\n const [tip, b0, b1] = a.head;\n if (tip && b0 && b1) {\n ctx.beginPath();\n ctx.moveTo(tip.x, tip.y);\n ctx.lineTo(b0.x, b0.y);\n ctx.lineTo(b1.x, b1.y);\n ctx.closePath();\n ctx.fill();\n }\n }\n};\n\nexport const drawForeground = (\n ctx: CanvasRenderingContext2D,\n input: ForegroundInput,\n) => {\n const { scales, theme } = input;\n const { plot } = scales;\n if (input.clear !== false) ctx.clearRect(0, 0, input.width, input.height);\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n\n for (const c of input.connectors ?? []) {\n ctx.strokeStyle = c.color;\n ctx.lineWidth = c.width;\n ctx.setLineDash([...c.dash]);\n ctx.beginPath();\n // crisp hairlines along the pixel grid\n const along = c.y0 === c.y1;\n const x0 = along ? c.x0 : crisp(c.x0);\n const y0 = along ? crisp(c.y0) : c.y0;\n ctx.moveTo(x0, y0);\n ctx.lineTo(along ? c.x1 : x0, along ? y0 : c.y1);\n ctx.stroke();\n }\n ctx.setLineDash([]);\n if (input.arrows?.length) drawArrows(ctx, input.arrows);\n\n const halo = toCss(theme.background, 0.9);\n const occupied: Rect[] = [];\n const labelHeight = theme.fontSize + 4;\n\n for (const a of input.annotations) {\n if (a.type !== \"line\") continue;\n const color = toCss(a.color);\n ctx.strokeStyle = color;\n ctx.lineWidth = a.width;\n ctx.setLineDash(a.dash);\n ctx.beginPath();\n const where = lineOf(a, scales);\n if (!where.vertical) {\n const py = crisp(where.at);\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"bottom\";\n haloText(ctx, a.label, plot.x + plot.width - 6, py - 3, color, halo);\n }\n } else {\n const px = crisp(where.at);\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n haloText(ctx, a.label, px + 5, plot.y + 5, color, halo);\n }\n }\n }\n ctx.setLineDash([]);\n\n // labels of areas\n for (const a of input.annotations) {\n if (a.type !== \"rect\" || !hasAreaTitle(a)) continue;\n const title = areaTitleLayout(\n a,\n rectOf(a, scales),\n theme.fontSize,\n (text, size, weight) => {\n ctx.font = font(theme, size, weight);\n return ctx.measureText(text).width;\n },\n );\n if (!title) continue;\n const color = toCss(a.labelColor);\n const muted = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n for (const p of title.parts) {\n const cy = p.y + p.height / 2;\n if (p.kind === \"badge\") {\n const h = p.height - 2;\n pill(ctx, p.x, cy - h / 2, p.width, h);\n ctx.fillStyle = toCss(a.labelColor, 0.16);\n ctx.fill();\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = color;\n ctx.fillText(p.text, p.x + 5, cy);\n continue;\n }\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = p.kind === \"label\" ? color : muted;\n ctx.fillText(p.text, p.x, cy);\n }\n occupied.push(title.box);\n }\n\n // free texts\n for (const a of input.annotations) {\n if (a.type !== \"text\" || !a.text) continue;\n ctx.font = font(theme, theme.fontSize, a.weight);\n const box = textBox(a, scales, ctx.measureText(a.text).width, labelHeight);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n haloText(ctx, a.text, box.x, box.y + box.height / 2, toCss(a.color), halo);\n occupied.push(box);\n }\n\n // point labels\n let placed: { label: PointLabel; box: Rect }[] = [];\n if (input.pointLabels.length) {\n ctx.font = font(theme);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n const textColor = toCss(theme.text, 0.85);\n placed = placeLabels(\n input.pointLabels,\n plot,\n (t) => ctx.measureText(t).width,\n labelHeight - 2,\n occupied,\n );\n for (const { label, box } of placed) {\n if (label.hidden) continue;\n const y = box.y + box.height / 2;\n if (label.color) {\n ctx.fillStyle = label.color;\n ctx.fillText(label.text, box.x, y);\n } else haloText(ctx, label.text, box.x, y, textColor, halo);\n }\n }\n ctx.restore();\n return placed;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"overlay.js","names":["INSIDE_PAD","insideLabelColor","alpha","fill","seen","mix","background","l","relativeLuminance","font","theme","weight","size","crisp","v","pill","r","h","w","ctx","x","y","textBox","s","at","toScreen","a","free","px","plot","py","width","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","screenRect","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","drawBackground","input","scales","bottomTicks","yTicks","xTicks","leftTicks","bottomPx","leftPx","toCss","base","lastRight","order","i","b","left","lastBottom","rows","rowHeight","y2","y2Ticks","right","overlaps","inside","haloText","halo","color","insideBox","bar","x0","x1","y0","y1","CELL_PAD","LABEL_GAP","distanceTo","cellBox","bounds","slack","others","dots","d","c","spaced","occupied","o","own","far","gap","sideY","sides","beside","side","corners","stacked","box","cuts","cw","best","total","keep","boxes","cut","placeLabels","placed","labels","fit","above","below","drawArrows","arrows","pts","first","next","prev","tip","b0","b1","drawForeground","labelHeight","where","title","muted","cy","textColor"],"sources":["../../../../charts/src/engine/overlay.ts"],"sourcesContent":["// Canvas2D layers around the data: background (areas, grid, axes, tick\n// labels) and foreground (reference lines, annotation and point labels).\n\nimport { mix, relativeLuminance, toCss, type Rgba } from \"./color\";\nimport type { AxisTicks } from \"./axis\";\nimport { screenRect, toScreen, type Rect, type Scales } from \"./layout\";\nimport type { AxisModel } from \"./model\";\nimport type { ChartTheme } from \"./theme\";\nimport type { ChartLabelPosition } from \"./types\";\n\nexport interface ResolvedRect {\n type: \"rect\";\n x0?: number;\n x1?: number;\n y0?: number;\n y1?: number;\n color: Rgba;\n opacity: number;\n label?: string;\n labelPosition: ChartLabelPosition;\n labelColor: Rgba;\n badge?: string;\n detail?: string;\n description?: string;\n}\n\nexport interface ResolvedLine {\n type: \"line\";\n axis: \"x\" | \"y\";\n value: number;\n color: Rgba;\n width: number;\n dash: number[];\n label?: string;\n}\n\nexport interface ResolvedText {\n type: \"text\";\n x?: number;\n y?: number;\n text: string;\n anchor: \"center\" | \"top\" | \"bottom\" | \"left\" | \"right\";\n color: Rgba;\n weight: number;\n}\n\nexport type ResolvedAnnotation = ResolvedRect | ResolvedLine | ResolvedText;\n\nexport interface PointLabel {\n x: number;\n y: number;\n /** Radius of the dot */\n r: number;\n text: string;\n /**\n * Fixed side (bar values: above / below, left / right of horizontal\n * bars; `inside` the `bar`); any free side around the dot otherwise\n */\n placement?: \"above\" | \"below\" | \"left\" | \"right\" | \"inside\";\n /** `inside` labels: the bar, in CSS pixels */\n bar?: Rect;\n /** `inside` labels: at the start of the bar (horizontal bars) or centered */\n align?: \"start\" | \"center\";\n /**\n * Text color contrasting with a solid bar (`inside` labels), drawn\n * without a halo; the text color of the theme with a halo otherwise\n */\n color?: string;\n /**\n * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS\n * pixels: on the side of the dot with more room, cut with an ellipsis\n * when it does not fit\n */\n bounds?: Rect;\n /**\n * Placed (it keeps its room) but not drawn: a card over the chart names\n * the point\n */\n hidden?: boolean;\n}\n\n/** Padding of the labels inside the bars, CSS pixels */\nconst INSIDE_PAD = 6;\n\n/**\n * Color of a text written on a bar of color `fill` (alpha included) over\n * `background`: white or near-black, whichever contrasts more; `undefined`\n * for translucent bars (the theme text color with a halo reads better)\n */\nexport const insideLabelColor = (\n fill: Rgba,\n background: Rgba,\n): string | undefined => {\n const alpha = fill[3];\n if (alpha < 0.6) return undefined;\n const seen = mix(background, fill, alpha);\n const l = relativeLuminance(seen);\n // WCAG contrast with white (L = 1) and with #111827 (L ≈ 0.012)\n return 1.05 / (l + 0.05) >= (l + 0.05) / 0.062\n ? \"#ffffff\"\n : \"rgba(17, 24, 39, 0.92)\";\n};\n\nexport const font = (theme: ChartTheme, size = theme.fontSize, weight = 400) =>\n `${weight} ${size}px ${theme.fontFamily}`;\n\nconst crisp = (v: number) => Math.round(v) + 0.5;\n\n/** Path of a rounded box with half-height corners */\nconst pill = (\n ctx: CanvasRenderingContext2D,\n x: number,\n y: number,\n w: number,\n h: number,\n) => {\n const r = Math.min(h / 2, w / 2);\n ctx.beginPath();\n ctx.moveTo(x + r, y);\n ctx.lineTo(x + w - r, y);\n ctx.arcTo(x + w, y, x + w, y + r, r);\n ctx.lineTo(x + w, y + h - r);\n ctx.arcTo(x + w, y + h, x + w - r, y + h, r);\n ctx.lineTo(x + r, y + h);\n ctx.arcTo(x, y + h, x, y + h - r, r);\n ctx.lineTo(x, y + r);\n ctx.arcTo(x, y, x + r, y, r);\n ctx.closePath();\n};\n\n/** Box of a text annotation, kept inside the plot */\nexport const textBox = (\n a: ResolvedText,\n s: Scales,\n width: number,\n height: number,\n): Rect => {\n const { plot } = s;\n const at = toScreen(s, a.x ?? 0, a.y ?? 0);\n const free = s.horizontal\n ? { x: a.y === undefined, y: a.x === undefined }\n : { x: a.x === undefined, y: a.y === undefined };\n const px = free.x ? plot.x + plot.width / 2 : at.x;\n const py = free.y ? plot.y + plot.height / 2 : at.y;\n const gap = 6;\n let x = px - width / 2;\n let y = py - height / 2;\n if (a.anchor === \"top\") y = py + gap;\n else if (a.anchor === \"bottom\") y = py - gap - height;\n else if (a.anchor === \"left\") x = px + gap;\n else if (a.anchor === \"right\") x = px - gap - width;\n x = Math.max(plot.x + gap, Math.min(x, plot.x + plot.width - gap - width));\n y = Math.max(plot.y + 2, Math.min(y, plot.y + plot.height - 2 - height));\n return { x, y, width, height };\n};\n\n/** Screen box of an area annotation, clipped to the plot */\nexport const rectOf = (a: ResolvedRect, s: Scales): Rect => {\n const { plot } = s;\n // clamp every edge to the plot first: an open edge maps to ±Infinity and\n // `Infinity - Infinity` would make the size NaN (nothing drawn)\n const [xLo, xHi] = s.horizontal\n ? [plot.y, plot.y + plot.height]\n : [plot.x, plot.x + plot.width];\n const [yLo, yHi] = s.horizontal\n ? [plot.x, plot.x + plot.width]\n : [plot.y, plot.y + plot.height];\n const along = (px: number, lo: number, hi: number) =>\n px < lo ? lo : px > hi ? hi : px;\n return screenRect(\n s,\n along(s.xToPx(a.x0 ?? -Infinity), xLo, xHi),\n along(s.xToPx(a.x1 ?? Infinity), xLo, xHi),\n along(s.yToPx(a.y0 ?? -Infinity), yLo, yHi),\n along(s.yToPx(a.y1 ?? Infinity), yLo, yHi),\n );\n};\n\n/** A text of the title block of an area: badge, label, detail or description */\nexport interface AreaText {\n kind: \"badge\" | \"label\" | \"detail\" | \"description\";\n text: string;\n /** Box of the text (the pill of a badge), CSS pixels */\n x: number;\n y: number;\n width: number;\n height: number;\n /** Font size and weight */\n size: number;\n weight: number;\n}\n\n/** Title block of an area annotation, in its `labelPosition` corner */\nexport interface AreaTitle {\n parts: AreaText[];\n /** Box around the parts (the point labels avoid it) */\n box: Rect;\n}\n\n/** Whether an area annotation has a title block */\nexport const hasAreaTitle = (a: ResolvedRect): boolean =>\n !!(a.label || a.badge || a.detail || a.description);\n\n/** Text cut with an ellipsis to fit `max` pixels (\"\" when nothing fits) */\nconst fitText = (\n text: string,\n max: number,\n width: (text: string) => number,\n): string => {\n if (width(text) <= max) return text;\n const chars = Array.from(text);\n let lo = 0;\n let hi = chars.length;\n while (lo < hi) {\n const mid = Math.ceil((lo + hi) / 2);\n if (width(`${chars.slice(0, mid).join(\"\")}…`) <= max) lo = mid;\n else hi = mid - 1;\n }\n return lo > 0 ? `${chars.slice(0, lo).join(\"\").trimEnd()}…` : \"\";\n};\n\n/**\n * Layout of the title block of an area: `[badge] label detail` on the first\n * line, the description under it; the block sits in the `labelPosition`\n * corner, 10px from the edges, and the texts are cut to the area width\n */\nexport const areaTitleLayout = (\n a: ResolvedRect,\n r: Rect,\n fontSize: number,\n measure: (text: string, size: number, weight: number) => number,\n): AreaTitle | null => {\n if (!hasAreaTitle(a) || r.width <= 0 || r.height <= 0) return null;\n const pad = 10;\n const lineHeight = fontSize + 4;\n const max = Math.max(0, r.width - pad * 2);\n const labelSize = fontSize + 1;\n const badgeSize = Math.max(9, fontSize - 1);\n const gap = 6;\n const badge = a.badge\n ? fitText(a.badge, Math.max(0, max - 10), (t) => measure(t, badgeSize, 700))\n : \"\";\n const badgeWidth = badge ? measure(badge, badgeSize, 700) + 10 : 0;\n let detail = a.detail ?? \"\";\n let detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n const room = () =>\n max - (badge ? badgeWidth + gap : 0) - (detail ? detailWidth + gap : 0);\n // a narrow area keeps the title rather than the detail\n if (detail && a.label && room() < 32) {\n detail = \"\";\n detailWidth = 0;\n }\n if (detail && room() < 0) {\n detail = fitText(\n detail,\n Math.max(0, max - (badge ? badgeWidth + gap : 0)),\n (t) => measure(t, fontSize, 500),\n );\n detailWidth = detail ? measure(detail, fontSize, 500) : 0;\n }\n const label = a.label\n ? fitText(a.label, Math.max(0, room()), (t) => measure(t, labelSize, 600))\n : \"\";\n const line: AreaText[] = [];\n if (badge)\n line.push({\n kind: \"badge\",\n text: badge,\n x: 0,\n y: 0,\n width: badgeWidth,\n height: lineHeight,\n size: badgeSize,\n weight: 700,\n });\n if (label)\n line.push({\n kind: \"label\",\n text: label,\n x: 0,\n y: 0,\n width: measure(label, labelSize, 600),\n height: lineHeight,\n size: labelSize,\n weight: 600,\n });\n if (detail)\n line.push({\n kind: \"detail\",\n text: detail,\n x: 0,\n y: 0,\n width: detailWidth,\n height: lineHeight,\n size: fontSize,\n weight: 500,\n });\n const description = a.description\n ? fitText(a.description, max, (t) => measure(t, fontSize, 400))\n : \"\";\n const lineWidth =\n line.reduce((sum, p) => sum + p.width, 0) +\n Math.max(0, line.length - 1) * gap;\n const descriptionWidth = description\n ? measure(description, fontSize, 400)\n : 0;\n if (!line.length && !description) return null;\n const height =\n (line.length ? lineHeight : 0) +\n (description ? lineHeight + (line.length ? 2 : 0) : 0);\n const pos = a.labelPosition;\n const top = pos.startsWith(\"top\")\n ? r.y + pad\n : pos.startsWith(\"bottom\")\n ? r.y + r.height - pad - height\n : r.y + (r.height - height) / 2;\n const startOf = (width: number) =>\n pos.endsWith(\"left\")\n ? r.x + pad\n : pos.endsWith(\"right\")\n ? r.x + r.width - pad - width\n : r.x + (r.width - width) / 2;\n const parts: AreaText[] = [];\n let x = startOf(lineWidth);\n for (const p of line) {\n parts.push({ ...p, x, y: top });\n x += p.width + gap;\n }\n if (description)\n parts.push({\n kind: \"description\",\n text: description,\n x: startOf(descriptionWidth),\n y: top + (line.length ? lineHeight + 2 : 0),\n width: descriptionWidth,\n height: lineHeight,\n size: fontSize,\n weight: 400,\n });\n const width = Math.max(lineWidth, descriptionWidth);\n return {\n parts,\n box: { x: startOf(width), y: top, width, height },\n };\n};\n\n/**\n * Where a reference line goes: `vertical` lines run at screen x `at`,\n * horizontal ones at screen y `at`\n */\nexport const lineOf = (\n a: ResolvedLine,\n s: Scales,\n): { vertical: boolean; at: number } => {\n const vertical = (a.axis === \"x\") !== s.horizontal;\n return {\n vertical,\n at: a.axis === \"x\" ? s.xToPx(a.value) : s.yToPx(a.value),\n };\n};\n\nexport interface BackgroundInput {\n width: number;\n height: number;\n scales: Scales;\n x: AxisModel;\n y: AxisModel;\n xTicks: AxisTicks;\n yTicks: AxisTicks;\n /** Right axis (dual axis charts) */\n y2?: AxisModel | null;\n y2Ticks?: AxisTicks | null;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n}\n\nexport const drawBackground = (\n ctx: CanvasRenderingContext2D,\n input: BackgroundInput,\n) => {\n const { scales, theme, xTicks, yTicks } = input;\n const { plot } = scales;\n // horizontal charts: the value axis along the bottom, the x axis on the left\n const x = scales.horizontal ? input.y : input.x;\n const y = scales.horizontal ? input.x : input.y;\n const bottomTicks = scales.horizontal ? yTicks : xTicks;\n const leftTicks = scales.horizontal ? xTicks : yTicks;\n const bottomPx = scales.horizontal ? scales.yToPx : scales.xToPx;\n const leftPx = scales.horizontal ? scales.xToPx : scales.yToPx;\n ctx.clearRect(0, 0, input.width, input.height);\n\n // areas\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n for (const a of input.annotations) {\n if (a.type !== \"rect\") continue;\n const r = rectOf(a, scales);\n if (r.width <= 0 || r.height <= 0) continue;\n ctx.fillStyle = toCss(a.color, a.opacity);\n ctx.fillRect(r.x, r.y, r.width, r.height);\n }\n ctx.restore();\n\n // grid\n ctx.lineWidth = 1;\n ctx.strokeStyle = toCss(theme.grid);\n ctx.beginPath();\n if (y.grid) {\n for (const v of leftTicks.values) {\n const py = crisp(leftPx(v));\n if (py < plot.y - 1 || py > plot.y + plot.height + 1) continue;\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n }\n }\n if (x.grid) {\n for (const v of bottomTicks.values) {\n const px = crisp(bottomPx(v));\n if (px < plot.x - 1 || px > plot.x + plot.width + 1) continue;\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n }\n }\n ctx.stroke();\n\n const line = Math.ceil(theme.fontSize * 1.4);\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n\n // x axis\n if (x.visible) {\n ctx.strokeStyle = toCss(theme.axis);\n ctx.beginPath();\n const base = crisp(plot.y + plot.height);\n ctx.moveTo(plot.x, base);\n ctx.lineTo(plot.x + plot.width, base);\n ctx.stroke();\n ctx.textBaseline = \"top\";\n ctx.textAlign = \"center\";\n let lastRight = -Infinity;\n // left to right (reversed axes list their ticks right to left)\n const order = bottomTicks.values\n .map((v, i) => ({ px: bottomPx(v), text: bottomTicks.labels[i] }))\n .sort((a, b) => a.px - b.px);\n for (const { px, text } of order) {\n if (px < plot.x - 0.5 || px > plot.x + plot.width + 0.5) continue;\n const w = ctx.measureText(text).width;\n const left = Math.max(0, Math.min(input.width - w, px - w / 2));\n if (left < lastRight + 6) continue;\n lastRight = left + w;\n ctx.fillText(text, left + w / 2, plot.y + plot.height + 7);\n }\n if (x.title) {\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.fillText(\n x.title,\n plot.x + plot.width / 2,\n plot.y + plot.height + line + 10,\n );\n }\n }\n\n // y axis\n if (y.visible) {\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"middle\";\n let lastBottom = -Infinity;\n // top to bottom: category rows of horizontal charts never overlap\n const rows = leftTicks.values\n .map((v, i) => ({ py: leftPx(v), text: leftTicks.labels[i] }))\n .sort((a, b) => a.py - b.py);\n const rowHeight = theme.fontSize + 2;\n for (const { py, text } of rows) {\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) continue;\n if (scales.horizontal) {\n if (py - rowHeight / 2 < lastBottom) continue;\n lastBottom = py + rowHeight / 2;\n }\n ctx.fillText(text, plot.x - 8, py);\n }\n if (y.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(line / 2 + 4, plot.y + plot.height / 2);\n ctx.rotate(-Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y.title, 0, 0);\n ctx.restore();\n }\n }\n\n // right axis\n const y2 = scales.horizontal ? null : input.y2;\n const y2Ticks = input.y2Ticks;\n if (y2 && y2Ticks && y2.visible) {\n const right = plot.x + plot.width;\n ctx.font = font(theme);\n ctx.fillStyle = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n y2Ticks.values.forEach((v, i) => {\n const py = scales.yToPx(v);\n if (py < plot.y - 0.5 || py > plot.y + plot.height + 0.5) return;\n ctx.fillText(y2Ticks.labels[i], right + 8, py);\n });\n if (y2.title) {\n ctx.save();\n ctx.font = font(theme, theme.fontSize + 1, 500);\n ctx.fillStyle = toCss(theme.text, 0.8);\n ctx.translate(input.width - line / 2 - 4, plot.y + plot.height / 2);\n ctx.rotate(Math.PI / 2);\n ctx.textAlign = \"center\";\n ctx.fillText(y2.title, 0, 0);\n ctx.restore();\n }\n }\n};\n\nconst overlaps = (a: Rect, b: Rect) =>\n a.x < b.x + b.width &&\n b.x < a.x + a.width &&\n a.y < b.y + b.height &&\n b.y < a.y + a.height;\n\nconst inside = (r: Rect, plot: Rect) =>\n r.x >= plot.x &&\n r.y >= plot.y &&\n r.x + r.width <= plot.x + plot.width &&\n r.y + r.height <= plot.y + plot.height;\n\n/** Text with a halo in the background color (readable over data) */\nconst haloText = (\n ctx: CanvasRenderingContext2D,\n text: string,\n x: number,\n y: number,\n color: string,\n halo: string,\n) => {\n ctx.lineWidth = 3;\n ctx.lineJoin = \"round\";\n ctx.strokeStyle = halo;\n ctx.strokeText(text, x, y);\n ctx.fillStyle = color;\n ctx.fillText(text, x, y);\n};\n\n/**\n * Box of a label inside its bar (the visible part of it): the text cut with\n * an ellipsis to fit, at the start of horizontal bars and centered in\n * vertical ones; `null` when the bar is too small\n */\nconst insideBox = (\n label: PointLabel,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n): { label: PointLabel; box: Rect } | null => {\n const bar = label.bar;\n if (!bar) return null;\n const x0 = Math.max(bar.x, plot.x);\n const x1 = Math.min(bar.x + bar.width, plot.x + plot.width);\n const y0 = Math.max(bar.y, plot.y);\n const y1 = Math.min(bar.y + bar.height, plot.y + plot.height);\n if (y1 - y0 < height - 2) return null;\n const text = fitText(label.text, x1 - x0 - INSIDE_PAD * 2, measure);\n if (!text) return null;\n const w = measure(text);\n const x = label.align === \"start\" ? x0 + INSIDE_PAD : (x0 + x1) / 2 - w / 2;\n return {\n label: text === label.text ? label : { ...label, text },\n box: { x, y: (y0 + y1) / 2 - height / 2, width: w, height },\n };\n};\n\n/** Room kept between a label and the edges of its cell, CSS pixels */\nconst CELL_PAD = 2;\n/** Room kept between two labels of a cell (they never touch), CSS pixels */\nconst LABEL_GAP = { x: 4, y: 2 };\n\n/** Distance from a point to the nearest point of a box */\nconst distanceTo = (x: number, y: number, r: Rect) =>\n Math.hypot(\n Math.max(r.x - x, 0, x - (r.x + r.width)),\n Math.max(r.y - y, 0, y - (r.y + r.height)),\n );\n\n/** A dot of a cell label: its label is told apart from the others by it */\ntype Dot = Pick<PointLabel, \"x\" | \"y\" | \"r\">;\n\n/**\n * Box of a label kept inside a cell of the plot (`bounds`): beside the dot\n * on the side with more room in the cell (moved up or down into the cell\n * near its edges), else above or below it (moved sideways into the cell),\n * else beside it half a line up or down;\n * cut with an ellipsis to the room left when the whole text fits nowhere;\n * `null` when no free slot is left. A slot is free when it keeps a gap to\n * the other labels and its own dot is the nearest one (it covers no other\n * dot): a crowded cell never pairs a name with the wrong dot\n */\nconst cellBox = (\n label: PointLabel,\n bounds: Rect,\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: readonly Rect[],\n dots: readonly Dot[] = [],\n): { label: PointLabel; box: Rect } | null => {\n const x0 = Math.max(bounds.x, plot.x) + CELL_PAD;\n const x1 = Math.min(bounds.x + bounds.width, plot.x + plot.width) - CELL_PAD;\n const y0 = Math.max(bounds.y, plot.y) + CELL_PAD;\n const y1 =\n Math.min(bounds.y + bounds.height, plot.y + plot.height) - CELL_PAD;\n if (x1 - x0 <= 0 || y1 - y0 < height) return null;\n // a hair of slack: a text cut to the exact room ends on the edge\n const slack = {\n x: x0 - 0.01,\n y: y0 - 0.01,\n width: x1 - x0 + 0.02,\n height: y1 - y0 + 0.02,\n };\n // the other dots: those at the very spot of this one count as its own\n const others = dots.filter(\n (d) => Math.abs(d.x - label.x) >= 0.5 || Math.abs(d.y - label.y) >= 0.5,\n );\n const free = (c: Rect) => {\n if (!inside(c, slack)) return false;\n const spaced = {\n x: c.x - LABEL_GAP.x,\n y: c.y - LABEL_GAP.y,\n width: c.width + LABEL_GAP.x * 2,\n height: c.height + LABEL_GAP.y * 2,\n };\n if (occupied.some((o) => overlaps(o, spaced))) return false;\n const own = distanceTo(label.x, label.y, c);\n return others.every((d) => {\n const far = distanceTo(d.x, d.y, c);\n return far >= d.r + 2 && far > own;\n });\n };\n const gap = label.r + 4;\n // centered on the dot, moved into the cell near its top or bottom edge\n const sideY = Math.min(Math.max(label.y - height / 2, y0), y1 - height);\n const room = { right: x1 - (label.x + gap), left: label.x - gap - x0 };\n const sides: (\"right\" | \"left\")[] =\n room.right >= room.left ? [\"right\", \"left\"] : [\"left\", \"right\"];\n const beside = (side: \"right\" | \"left\", w: number): Rect[] => [\n {\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: sideY,\n width: w,\n height,\n },\n ];\n // beside the dot, raised or lowered by half a line: a crowded cell gets\n // more slots still next to their own dot\n const corners = (side: \"right\" | \"left\", w: number): Rect[] =>\n [label.y - height - 1, label.y + 1].map((y) => ({\n x: side === \"right\" ? label.x + gap : label.x - gap - w,\n y: Math.min(Math.max(y, y0), y1 - height),\n width: w,\n height,\n }));\n const stacked = (w: number): Rect[] => {\n // slid sideways into the cell near its edges (still over the dot)\n const x = Math.min(Math.max(label.x - w / 2, x0), x1 - w);\n return [\n { x, y: label.y - gap - height, width: w, height },\n { x, y: label.y + gap, width: w, height },\n ];\n };\n const w = measure(label.text);\n const whole = [\n ...beside(sides[0]!, w),\n ...beside(sides[1]!, w),\n ...stacked(w),\n ...corners(sides[0]!, w),\n ...corners(sides[1]!, w),\n ];\n const box = whole.find(free);\n if (box) return { label, box };\n // the whole text fits nowhere: cut it to the room beside the dot or above\n // / below it, keeping the longest text (the roomiest side on ties)\n const cuts: [number, (w: number) => Rect[]][] = [\n [\n room[sides[0]!],\n (cw) => [...beside(sides[0]!, cw), ...corners(sides[0]!, cw)],\n ],\n [\n room[sides[1]!],\n (cw) => [...beside(sides[1]!, cw), ...corners(sides[1]!, cw)],\n ],\n [x1 - x0, stacked],\n ];\n let best: { label: PointLabel; box: Rect } | null = null;\n // a cut keeps enough of the name to tell it (else the label is skipped,\n // like an overlapping one: the tooltip still names the point)\n const total = Array.from(label.text).length;\n const keep = Math.min(4, Math.ceil(total * 0.4));\n for (const [max, boxes] of cuts) {\n const text = fitText(label.text, max, measure);\n if (!text || (best && text.length <= best.label.text.length)) continue;\n if (Array.from(text).length - 1 < keep) continue;\n const cut = boxes(measure(text)).find(free);\n if (cut) best = { label: { ...label, text }, box: cut };\n }\n return best;\n};\n\n/** Greedy placement: right, left, above, below the dot; skipped when no slot is free */\nexport const placeLabels = (\n labels: readonly PointLabel[],\n plot: Rect,\n measure: (text: string) => number,\n height: number,\n occupied: Rect[] = [],\n): { label: PointLabel; box: Rect }[] => {\n const placed: { label: PointLabel; box: Rect }[] = [];\n // the dots of the labels kept in cells (labels placed later included)\n const dots = labels.filter((label) => label.bounds);\n for (const label of labels) {\n if (label.placement === \"inside\") {\n const fit = insideBox(label, plot, measure, height);\n if (fit) placed.push(fit);\n continue;\n }\n if (label.bounds) {\n const fit = cellBox(\n label,\n label.bounds,\n plot,\n measure,\n height,\n occupied,\n dots,\n );\n if (!fit) continue;\n occupied.push(fit.box);\n placed.push(fit);\n continue;\n }\n const w = measure(label.text);\n const gap = label.r + 4;\n const above = {\n x: label.x - w / 2,\n y: label.y - gap - height,\n width: w,\n height,\n };\n const below = { x: label.x - w / 2, y: label.y + gap, width: w, height };\n const right = {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const left = {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n };\n const candidates: Rect[] =\n label.placement === \"above\"\n ? [above]\n : label.placement === \"below\"\n ? [below]\n : label.placement === \"right\"\n ? [right, left]\n : label.placement === \"left\"\n ? [left, right]\n : [\n {\n x: label.x + gap,\n y: label.y - height / 2,\n width: w,\n height,\n },\n {\n x: label.x - gap - w,\n y: label.y - height / 2,\n width: w,\n height,\n },\n above,\n below,\n ];\n const box = candidates.find(\n (c) => inside(c, plot) && !occupied.some((o) => overlaps(o, c)),\n );\n if (!box) continue;\n occupied.push(box);\n placed.push({ label, box });\n }\n return placed;\n};\n\nexport interface ForegroundInput {\n width: number;\n height: number;\n scales: Scales;\n theme: ChartTheme;\n annotations: readonly ResolvedAnnotation[];\n pointLabels: readonly PointLabel[];\n /**\n * Clears the canvas first (off when the layers share one canvas)\n * @default true\n */\n clear?: boolean;\n /** Lines between consecutive bars (waterfall connectors), drawn first */\n connectors?: readonly {\n x0: number;\n y0: number;\n x1: number;\n y1: number;\n color: string;\n width: number;\n dash: readonly number[];\n }[];\n /** Dependency arrows (Gantt charts), drawn over the connectors */\n arrows?: readonly ArrowPath[];\n}\n\n/** An elbow arrow in stage pixels (see `dependencyArrows`) */\nexport interface ArrowPath {\n points: readonly { x: number; y: number }[];\n head: readonly { x: number; y: number }[];\n color: string;\n width: number;\n}\n\n/** Elbow arrows: polylines with rounded corners and filled heads */\nexport const drawArrows = (\n ctx: CanvasRenderingContext2D,\n arrows: readonly ArrowPath[],\n) => {\n for (const a of arrows) {\n const pts = a.points;\n const first = pts[0];\n if (!first) continue;\n ctx.strokeStyle = a.color;\n ctx.fillStyle = a.color;\n ctx.lineWidth = a.width;\n ctx.lineJoin = \"round\";\n ctx.setLineDash([]);\n ctx.beginPath();\n ctx.moveTo(first.x, first.y);\n for (let i = 1; i < pts.length; i++) {\n const p = pts[i]!;\n const next = pts[i + 1];\n const prev = pts[i - 1]!;\n if (next && typeof ctx.arcTo === \"function\") {\n // rounded elbow, at most half of the shorter leg\n const r = Math.min(\n 4,\n Math.hypot(p.x - prev.x, p.y - prev.y) / 2,\n Math.hypot(next.x - p.x, next.y - p.y) / 2,\n );\n ctx.arcTo(p.x, p.y, next.x, next.y, r);\n } else {\n ctx.lineTo(p.x, p.y);\n }\n }\n ctx.stroke();\n const [tip, b0, b1] = a.head;\n if (tip && b0 && b1) {\n ctx.beginPath();\n ctx.moveTo(tip.x, tip.y);\n ctx.lineTo(b0.x, b0.y);\n ctx.lineTo(b1.x, b1.y);\n ctx.closePath();\n ctx.fill();\n }\n }\n};\n\nexport const drawForeground = (\n ctx: CanvasRenderingContext2D,\n input: ForegroundInput,\n) => {\n const { scales, theme } = input;\n const { plot } = scales;\n if (input.clear !== false) ctx.clearRect(0, 0, input.width, input.height);\n ctx.save();\n ctx.beginPath();\n ctx.rect(plot.x, plot.y, plot.width, plot.height);\n ctx.clip();\n\n for (const c of input.connectors ?? []) {\n ctx.strokeStyle = c.color;\n ctx.lineWidth = c.width;\n ctx.setLineDash([...c.dash]);\n ctx.beginPath();\n // crisp hairlines along the pixel grid\n const along = c.y0 === c.y1;\n const x0 = along ? c.x0 : crisp(c.x0);\n const y0 = along ? crisp(c.y0) : c.y0;\n ctx.moveTo(x0, y0);\n ctx.lineTo(along ? c.x1 : x0, along ? y0 : c.y1);\n ctx.stroke();\n }\n ctx.setLineDash([]);\n if (input.arrows?.length) drawArrows(ctx, input.arrows);\n\n const halo = toCss(theme.background, 0.9);\n const occupied: Rect[] = [];\n const labelHeight = theme.fontSize + 4;\n\n for (const a of input.annotations) {\n if (a.type !== \"line\") continue;\n const color = toCss(a.color);\n ctx.strokeStyle = color;\n ctx.lineWidth = a.width;\n ctx.setLineDash(a.dash);\n ctx.beginPath();\n const where = lineOf(a, scales);\n if (!where.vertical) {\n const py = crisp(where.at);\n ctx.moveTo(plot.x, py);\n ctx.lineTo(plot.x + plot.width, py);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"right\";\n ctx.textBaseline = \"bottom\";\n haloText(ctx, a.label, plot.x + plot.width - 6, py - 3, color, halo);\n }\n } else {\n const px = crisp(where.at);\n ctx.moveTo(px, plot.y);\n ctx.lineTo(px, plot.y + plot.height);\n ctx.stroke();\n if (a.label) {\n ctx.setLineDash([]);\n ctx.font = font(theme, theme.fontSize, 500);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"top\";\n haloText(ctx, a.label, px + 5, plot.y + 5, color, halo);\n }\n }\n }\n ctx.setLineDash([]);\n\n // labels of areas\n for (const a of input.annotations) {\n if (a.type !== \"rect\" || !hasAreaTitle(a)) continue;\n const title = areaTitleLayout(\n a,\n rectOf(a, scales),\n theme.fontSize,\n (text, size, weight) => {\n ctx.font = font(theme, size, weight);\n return ctx.measureText(text).width;\n },\n );\n if (!title) continue;\n const color = toCss(a.labelColor);\n const muted = toCss(theme.textMuted);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n for (const p of title.parts) {\n const cy = p.y + p.height / 2;\n if (p.kind === \"badge\") {\n const h = p.height - 2;\n pill(ctx, p.x, cy - h / 2, p.width, h);\n ctx.fillStyle = toCss(a.labelColor, 0.16);\n ctx.fill();\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = color;\n ctx.fillText(p.text, p.x + 5, cy);\n continue;\n }\n ctx.font = font(theme, p.size, p.weight);\n ctx.fillStyle = p.kind === \"label\" ? color : muted;\n ctx.fillText(p.text, p.x, cy);\n }\n occupied.push(title.box);\n }\n\n // free texts\n for (const a of input.annotations) {\n if (a.type !== \"text\" || !a.text) continue;\n ctx.font = font(theme, theme.fontSize, a.weight);\n const box = textBox(a, scales, ctx.measureText(a.text).width, labelHeight);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n haloText(ctx, a.text, box.x, box.y + box.height / 2, toCss(a.color), halo);\n occupied.push(box);\n }\n\n // point labels\n let placed: { label: PointLabel; box: Rect }[] = [];\n if (input.pointLabels.length) {\n ctx.font = font(theme);\n ctx.textAlign = \"left\";\n ctx.textBaseline = \"middle\";\n const textColor = toCss(theme.text, 0.85);\n placed = placeLabels(\n input.pointLabels,\n plot,\n (t) => ctx.measureText(t).width,\n labelHeight - 2,\n occupied,\n );\n for (const { label, box } of placed) {\n if (label.hidden) continue;\n const y = box.y + box.height / 2;\n if (label.color) {\n ctx.fillStyle = label.color;\n ctx.fillText(label.text, box.x, y);\n } else haloText(ctx, label.text, box.x, y, textColor, halo);\n }\n }\n ctx.restore();\n return placed;\n};\n"],"mappings":"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"}