minerva-design 1.17.1 → 1.17.2

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 (73) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/charts/engine/backing-store.cjs +2 -0
  3. package/dist/charts/engine/backing-store.cjs.map +1 -0
  4. package/dist/charts/engine/backing-store.d.cts +11 -0
  5. package/dist/charts/engine/backing-store.d.ts +11 -0
  6. package/dist/charts/engine/backing-store.js +27 -0
  7. package/dist/charts/engine/backing-store.js.map +1 -0
  8. package/dist/charts/engine/canvas.cjs +1 -1
  9. package/dist/charts/engine/canvas.cjs.map +1 -1
  10. package/dist/charts/engine/canvas.js +89 -86
  11. package/dist/charts/engine/canvas.js.map +1 -1
  12. package/dist/charts/engine/model.cjs +1 -1
  13. package/dist/charts/engine/model.cjs.map +1 -1
  14. package/dist/charts/engine/model.d.cts +5 -0
  15. package/dist/charts/engine/model.d.ts +5 -0
  16. package/dist/charts/engine/model.js +1 -0
  17. package/dist/charts/engine/model.js.map +1 -1
  18. package/dist/charts/engine/overlay.cjs +1 -1
  19. package/dist/charts/engine/overlay.cjs.map +1 -1
  20. package/dist/charts/engine/overlay.d.cts +6 -0
  21. package/dist/charts/engine/overlay.d.ts +6 -0
  22. package/dist/charts/engine/overlay.js +68 -6
  23. package/dist/charts/engine/overlay.js.map +1 -1
  24. package/dist/charts/engine/presets.cjs +1 -1
  25. package/dist/charts/engine/presets.cjs.map +1 -1
  26. package/dist/charts/engine/presets.js +4 -0
  27. package/dist/charts/engine/presets.js.map +1 -1
  28. package/dist/charts/engine/scene.cjs +1 -1
  29. package/dist/charts/engine/scene.cjs.map +1 -1
  30. package/dist/charts/engine/scene.d.cts +11 -0
  31. package/dist/charts/engine/scene.d.ts +11 -0
  32. package/dist/charts/engine/scene.js +107 -90
  33. package/dist/charts/engine/scene.js.map +1 -1
  34. package/dist/charts/engine/shapes/canvas.cjs +1 -1
  35. package/dist/charts/engine/shapes/canvas.cjs.map +1 -1
  36. package/dist/charts/engine/shapes/canvas.js +97 -94
  37. package/dist/charts/engine/shapes/canvas.js.map +1 -1
  38. package/dist/charts/engine/types.d.cts +10 -0
  39. package/dist/charts/engine/types.d.ts +10 -0
  40. package/dist/native/charts/src/engine/backing-store.cjs +2 -0
  41. package/dist/native/charts/src/engine/backing-store.cjs.map +1 -0
  42. package/dist/native/charts/src/engine/backing-store.js +27 -0
  43. package/dist/native/charts/src/engine/backing-store.js.map +1 -0
  44. package/dist/native/charts/src/engine/model.cjs +1 -1
  45. package/dist/native/charts/src/engine/model.cjs.map +1 -1
  46. package/dist/native/charts/src/engine/model.js +1 -0
  47. package/dist/native/charts/src/engine/model.js.map +1 -1
  48. package/dist/native/charts/src/engine/overlay.cjs +1 -1
  49. package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
  50. package/dist/native/charts/src/engine/overlay.js +64 -2
  51. package/dist/native/charts/src/engine/overlay.js.map +1 -1
  52. package/dist/native/charts/src/engine/presets.cjs +1 -1
  53. package/dist/native/charts/src/engine/presets.cjs.map +1 -1
  54. package/dist/native/charts/src/engine/presets.js +4 -0
  55. package/dist/native/charts/src/engine/presets.js.map +1 -1
  56. package/dist/native/charts/src/engine/scene.cjs +1 -1
  57. package/dist/native/charts/src/engine/scene.cjs.map +1 -1
  58. package/dist/native/charts/src/engine/scene.js +107 -90
  59. package/dist/native/charts/src/engine/scene.js.map +1 -1
  60. package/dist/native/charts/src/engine/shapes/canvas.cjs +1 -1
  61. package/dist/native/charts/src/engine/shapes/canvas.cjs.map +1 -1
  62. package/dist/native/charts/src/engine/shapes/canvas.js +107 -104
  63. package/dist/native/charts/src/engine/shapes/canvas.js.map +1 -1
  64. package/dist/taro/chart-pixel-ratio.d.ts +10 -0
  65. package/dist/taro/index.js +1756 -1662
  66. package/dist/taro/style.css +101 -1
  67. package/dist/uni/QuadrantTaskBoard.vue +4 -14
  68. package/dist/uni/style.css +90 -0
  69. package/dist/weapp/charts/canvas.js +201 -18
  70. package/dist/weapp/controls.js +1 -1
  71. package/dist/weapp/controls.wxss +90 -0
  72. package/dist/weapp/quadrant-task-board/index.wxml +1 -1
  73. 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","placeLabels","placed","labels","fit","gap","above","below","box","c","occupied","o","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\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/** 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 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 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 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","cellBox","bounds","slack","c","occupied","o","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\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\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\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): { 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 const free = (c: Rect) =>\n inside(c, slack) && !occupied.some((o) => overlaps(o, c));\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 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(label, label.bounds, plot, measure, height, occupied);\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 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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"}
@@ -58,6 +58,12 @@ export interface PointLabel {
58
58
  * without a halo; the text color of the theme with a halo otherwise
59
59
  */
60
60
  color?: string;
61
+ /**
62
+ * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS
63
+ * pixels: on the side of the dot with more room, cut with an ellipsis
64
+ * when it does not fit
65
+ */
66
+ bounds?: Rect;
61
67
  }
62
68
  /**
63
69
  * Color of a text written on a bar of color `fill` (alpha included) over
@@ -58,6 +58,12 @@ export interface PointLabel {
58
58
  * without a halo; the text color of the theme with a halo otherwise
59
59
  */
60
60
  color?: string;
61
+ /**
62
+ * Cell the label stays in (`labelCells`: the quadrant of the dot), in CSS
63
+ * pixels: on the side of the dot with more room, cut with an ellipsis
64
+ * when it does not fit
65
+ */
66
+ bounds?: Rect;
61
67
  }
62
68
  /**
63
69
  * Color of a text written on a bar of color `fill` (alpha included) over
@@ -176,7 +176,63 @@ var a = 6, o = (n, r) => {
176
176
  height: r
177
177
  }
178
178
  };
179
- }, x = (e, t, n, r, i = []) => {
179
+ }, x = 2, S = (e, t, n, r, i, a) => {
180
+ let o = Math.max(t.x, n.x) + x, s = Math.min(t.x + t.width, n.x + n.width) - x, c = Math.max(t.y, n.y) + x, l = Math.min(t.y + t.height, n.y + n.height) - x;
181
+ if (s - o <= 0 || l - c < i) return null;
182
+ let u = {
183
+ x: o - .01,
184
+ y: c - .01,
185
+ width: s - o + .02,
186
+ height: l - c + .02
187
+ }, d = (e) => v(e, u) && !a.some((t) => _(t, e)), f = e.r + 4, m = Math.min(Math.max(e.y - i / 2, c), l - i), h = {
188
+ right: s - (e.x + f),
189
+ left: e.x - f - o
190
+ }, g = h.right >= h.left ? ["right", "left"] : ["left", "right"], y = (t, n) => [{
191
+ x: t === "right" ? e.x + f : e.x - f - n,
192
+ y: m,
193
+ width: n,
194
+ height: i
195
+ }], b = (t) => {
196
+ let n = Math.min(Math.max(e.x - t / 2, o), s - t);
197
+ return [{
198
+ x: n,
199
+ y: e.y - f - i,
200
+ width: t,
201
+ height: i
202
+ }, {
203
+ x: n,
204
+ y: e.y + f,
205
+ width: t,
206
+ height: i
207
+ }];
208
+ }, S = r(e.text), C = [
209
+ ...y(g[0], S),
210
+ ...y(g[1], S),
211
+ ...b(S)
212
+ ].find(d);
213
+ if (C) return {
214
+ label: e,
215
+ box: C
216
+ };
217
+ let w = [
218
+ [h[g[0]], (e) => y(g[0], e)],
219
+ [h[g[1]], (e) => y(g[1], e)],
220
+ [s - o, b]
221
+ ], T = null, E = Array.from(e.text).length, D = Math.min(4, Math.ceil(E * .4));
222
+ for (let [t, n] of w) {
223
+ let i = p(e.text, t, r);
224
+ if (!i || T && i.length <= T.label.text.length || Array.from(i).length - 1 < D) continue;
225
+ let a = n(r(i)).find(d);
226
+ a && (T = {
227
+ label: {
228
+ ...e,
229
+ text: i
230
+ },
231
+ box: a
232
+ });
233
+ }
234
+ return T;
235
+ }, C = (e, t, n, r, i = []) => {
180
236
  let a = [];
181
237
  for (let o of e) {
182
238
  if (o.placement === "inside") {
@@ -184,6 +240,12 @@ var a = 6, o = (n, r) => {
184
240
  e && a.push(e);
185
241
  continue;
186
242
  }
243
+ if (o.bounds) {
244
+ let e = S(o, o.bounds, t, n, r, i);
245
+ if (!e) continue;
246
+ i.push(e.box), a.push(e);
247
+ continue;
248
+ }
187
249
  let e = n(o.text), s = o.r + 4, c = {
188
250
  x: o.x - e / 2,
189
251
  y: o.y - s - r,
@@ -226,7 +288,7 @@ var a = 6, o = (n, r) => {
226
288
  }));
227
289
  }
228
290
  return a;
229
- }, S = (e, t) => {
291
+ }, w = (e, t) => {
230
292
  for (let n of t) {
231
293
  let t = n.points, r = t[0];
232
294
  if (!r) continue;
@@ -242,7 +304,7 @@ var a = 6, o = (n, r) => {
242
304
  let [i, a, o] = n.head;
243
305
  i && a && o && (e.beginPath(), e.moveTo(i.x, i.y), e.lineTo(a.x, a.y), e.lineTo(o.x, o.y), e.closePath(), e.fill());
244
306
  }
245
- }, C = (e, t) => {
307
+ }, T = (e, t) => {
246
308
  let { scales: r, theme: i } = t, { plot: a } = r;
247
309
  t.clear !== !1 && e.clearRect(0, 0, t.width, t.height), e.save(), e.beginPath(), e.rect(a.x, a.y, a.width, a.height), e.clip();
248
310
  for (let n of t.connectors ?? []) {
@@ -250,7 +312,7 @@ var a = 6, o = (n, r) => {
250
312
  let t = n.y0 === n.y1, r = t ? n.x0 : c(n.x0), i = t ? c(n.y0) : n.y0;
251
313
  e.moveTo(r, i), e.lineTo(t ? n.x1 : r, t ? i : n.y1), e.stroke();
252
314
  }
253
- e.setLineDash([]), t.arrows?.length && S(e, t.arrows);
315
+ e.setLineDash([]), t.arrows?.length && w(e, t.arrows);
254
316
  let o = n(i.background, .9), p = [], g = i.fontSize + 4;
255
317
  for (let l of t.annotations) {
256
318
  if (l.type !== "line") continue;
@@ -293,7 +355,7 @@ var a = 6, o = (n, r) => {
293
355
  if (t.pointLabels.length) {
294
356
  e.font = s(i), e.textAlign = "left", e.textBaseline = "middle";
295
357
  let r = n(i.text, .85);
296
- _ = x(t.pointLabels, a, (t) => e.measureText(t).width, g - 2, p);
358
+ _ = C(t.pointLabels, a, (t) => e.measureText(t).width, g - 2, p);
297
359
  for (let { label: t, box: n } of _) {
298
360
  let i = n.y + n.height / 2;
299
361
  t.color ? (e.fillStyle = t.color, e.fillText(t.text, n.x, i)) : y(e, t.text, n.x, i, r, o);
@@ -302,6 +364,6 @@ var a = 6, o = (n, r) => {
302
364
  return e.restore(), _;
303
365
  };
304
366
  //#endregion
305
- export { m as areaTitleLayout, S as drawArrows, g as drawBackground, C as drawForeground, s as font, f as hasAreaTitle, o as insideLabelColor, h as lineOf, x as placeLabels, d as rectOf, u as textBox };
367
+ export { m as areaTitleLayout, w as drawArrows, g as drawBackground, T as drawForeground, s as font, f as hasAreaTitle, o as insideLabelColor, h as lineOf, C as placeLabels, d as rectOf, u as textBox };
306
368
 
307
369
  //# sourceMappingURL=overlay.js.map