minerva-design 1.17.2 → 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 (98) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/custom-elements.json +10 -6
  3. package/dist/angular/fesm2022/minerva-angular.mjs +173 -70
  4. package/dist/angular/fesm2022/minerva-angular.mjs.map +1 -1
  5. package/dist/angular/types/minerva-angular.d.ts +33 -21
  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 +414 -376
  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.d.cts +5 -0
  17. package/dist/charts/engine/overlay.d.ts +5 -0
  18. package/dist/charts/engine/overlay.js +94 -69
  19. package/dist/charts/engine/overlay.js.map +1 -1
  20. package/dist/charts/engine/quadrant-card.cjs +2 -0
  21. package/dist/charts/engine/quadrant-card.cjs.map +1 -0
  22. package/dist/charts/engine/quadrant-card.d.cts +83 -0
  23. package/dist/charts/engine/quadrant-card.d.ts +83 -0
  24. package/dist/charts/engine/quadrant-card.js +154 -0
  25. package/dist/charts/engine/quadrant-card.js.map +1 -0
  26. package/dist/charts/engine/scene.cjs +1 -1
  27. package/dist/charts/engine/scene.cjs.map +1 -1
  28. package/dist/charts/engine/scene.d.cts +5 -0
  29. package/dist/charts/engine/scene.d.ts +5 -0
  30. package/dist/charts/engine/scene.js +32 -32
  31. package/dist/charts/engine/scene.js.map +1 -1
  32. package/dist/charts/engine/types.d.cts +14 -0
  33. package/dist/charts/engine/types.d.ts +14 -0
  34. package/dist/charts/index.cjs +1 -1
  35. package/dist/charts/index.js +28 -27
  36. package/dist/charts/react/Chart.cjs +1 -1
  37. package/dist/charts/react/Chart.cjs.map +1 -1
  38. package/dist/charts/react/Chart.d.cts +4 -2
  39. package/dist/charts/react/Chart.d.ts +4 -2
  40. package/dist/charts/react/Chart.js +42 -42
  41. package/dist/charts/react/Chart.js.map +1 -1
  42. package/dist/charts/react/charts.cjs +1 -1
  43. package/dist/charts/react/charts.cjs.map +1 -1
  44. package/dist/charts/react/charts.js +395 -391
  45. package/dist/charts/react/charts.js.map +1 -1
  46. package/dist/charts/react/types.d.cts +8 -2
  47. package/dist/charts/react/types.d.ts +8 -2
  48. package/dist/core/contracts.cjs +1 -1
  49. package/dist/core/contracts.cjs.map +1 -1
  50. package/dist/core/contracts.js +1 -1
  51. package/dist/core/contracts.js.map +1 -1
  52. package/dist/native/charts/src/engine/overlay.cjs +1 -1
  53. package/dist/native/charts/src/engine/overlay.cjs.map +1 -1
  54. package/dist/native/charts/src/engine/overlay.js +89 -65
  55. package/dist/native/charts/src/engine/overlay.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 +32 -32
  59. package/dist/native/charts/src/engine/scene.js.map +1 -1
  60. package/dist/react/components/QuadrantTaskBoard/QuadrantTaskBoard.cjs +1 -1
  61. package/dist/react/components/QuadrantTaskBoard/QuadrantTaskBoard.cjs.map +1 -1
  62. package/dist/react/components/QuadrantTaskBoard/QuadrantTaskBoard.js +14 -8
  63. package/dist/react/components/QuadrantTaskBoard/QuadrantTaskBoard.js.map +1 -1
  64. package/dist/react/components/QuadrantTaskBoard/quadrantTaskBoard.module.scss.cjs +1 -1
  65. package/dist/react/components/QuadrantTaskBoard/quadrantTaskBoard.module.scss.cjs.map +1 -1
  66. package/dist/react/components/QuadrantTaskBoard/quadrantTaskBoard.module.scss.js +16 -15
  67. package/dist/react/components/QuadrantTaskBoard/quadrantTaskBoard.module.scss.js.map +1 -1
  68. package/dist/react/style.css +1 -1
  69. package/dist/react/styles/quadrant-task-board.css +1 -1
  70. package/dist/taro/index.js +1521 -1496
  71. package/dist/taro/style.css +22 -0
  72. package/dist/uni/manifest.d.ts +34 -34
  73. package/dist/uni/manifest.js +34 -39
  74. package/dist/uni/style.css +22 -0
  75. package/dist/vue/components/Chart/QuadrantChart.vue.d.ts +4 -3
  76. package/dist/vue/components/Chart/QuadrantChart.vue.js.map +1 -1
  77. package/dist/vue/components/Chart/QuadrantChart.vue_vue_type_script_setup_true_lang.js +186 -142
  78. package/dist/vue/components/Chart/QuadrantChart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  79. package/dist/vue/components/Chart/cartesian.d.ts +5 -1
  80. package/dist/vue/components/Chart/cartesian.js +2 -0
  81. package/dist/vue/components/Chart/cartesian.js.map +1 -1
  82. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue.js.map +1 -1
  83. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue_vue_type_script_setup_true_lang.js +18 -12
  84. package/dist/vue/components/QuadrantTaskBoard/QuadrantTaskBoard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  85. package/dist/weapp/charts/canvas.js +48 -11
  86. package/dist/weapp/controls.wxss +22 -0
  87. package/dist/web-components/components/chart/chart.d.ts +4 -1
  88. package/dist/web-components/components/chart/chart.js +3 -1
  89. package/dist/web-components/components/chart/chart.js.map +1 -1
  90. package/dist/web-components/components/chart/charts.d.ts +34 -14
  91. package/dist/web-components/components/chart/charts.js +145 -98
  92. package/dist/web-components/components/chart/charts.js.map +1 -1
  93. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.d.ts +8 -8
  94. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.js +16 -12
  95. package/dist/web-components/components/quadrant-task-board/quadrant-task-board.js.map +1 -1
  96. package/dist/web-components/styles/QuadrantTaskBoard/quadrantTaskBoard.css.js +1 -1
  97. package/dist/web-components/styles/QuadrantTaskBoard/quadrantTaskBoard.css.js.map +1 -1
  98. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"overlay.js","names":["INSIDE_PAD","insideLabelColor","alpha","fill","seen","mix","background","l","relativeLuminance","font","theme","weight","size","textBox","s","at","toScreen","a","free","px","plot","py","x","width","y","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","screenRect","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","r","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","overlaps","b","inside","insideBox","bar","x0","x1","y0","y1","w","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","right","left"],"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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"}
1
+ {"version":3,"file":"overlay.js","names":["INSIDE_PAD","insideLabelColor","alpha","fill","seen","mix","background","l","relativeLuminance","font","theme","weight","size","textBox","s","at","toScreen","a","free","px","plot","py","x","width","y","height","rectOf","xLo","xHi","yLo","yHi","along","lo","hi","screenRect","hasAreaTitle","fitText","text","max","chars","mid","areaTitleLayout","r","lineHeight","fontSize","labelSize","badgeSize","badge","measure","t","badgeWidth","detail","detailWidth","room","label","line","description","lineWidth","sum","p","descriptionWidth","pos","top","startOf","parts","lineOf","overlaps","b","inside","insideBox","bar","x0","x1","y0","y1","w","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","right","left"],"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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"}
@@ -1,2 +1,2 @@
1
- const e=require("./color.cjs"),t=require("./data.cjs"),n=require("./layout.cjs"),r=require("./overlay.cjs"),i=require("./locale.cjs"),a=require("./format.cjs"),o=require("./axis.cjs"),s=require("./model.cjs");var c={top:12,right:16,bottom:4,left:4},l=(e,t)=>t,u=(t,n,r,i)=>{let a=n.resolve??l,o=e=>r&&e!==void 0?r(e):e,s=e=>i&&e!==void 0?i(e):e;return(t??[]).map(t=>{if(t.type===`rect`){let r=t.color?a(t.color,n.primary):n.primary;return{type:`rect`,x0:s(t.x0),x1:s(t.x1),y0:o(t.y0),y1:o(t.y1),color:r,opacity:t.opacity??.08,label:t.label,labelPosition:t.labelPosition??`top-left`,labelColor:t.labelColor?a(t.labelColor,r):e.mix(r,n.text,.2),...t.badge?{badge:t.badge}:{},...t.detail?{detail:t.detail}:{},...t.description?{description:t.description}:{}}}return t.type===`text`?{type:`text`,x:s(t.x),y:o(t.y),text:t.text,anchor:t.anchor??`center`,color:t.color?a(t.color,n.textMuted):n.textMuted,weight:t.weight??500}:{type:`line`,axis:t.axis,value:t.axis===`y`?o(t.value):s(t.value),color:t.color?a(t.color,n.textMuted):n.textMuted,width:t.width??1,dash:[...t.dash??[4,4]],label:t.label}})},d=e=>{let{model:t,view:r,theme:i,width:a,height:s,measure:l}=e;if(t.horizontal)return p(e);let u=t.y.tickCount??(t.y.type===`category`?Math.max(1,Math.floor((s-40)/(i.fontSize+5))):s>=220?5:Math.max(2,Math.round((s-48)/52))),d=o.axisTicks(t.y,r.y,u),m=0;if(t.y.visible)for(let e of d.labels)m=Math.max(m,l(e));let h=f(t,d,r.y,u),g=0;if(h&&t.y2?.visible)for(let e of h.labels)g=Math.max(g,l(e));let _=48;if(t.x.type===`category`){_=0;let e=Math.max(1,Math.floor(t.x.categories.length/200));for(let n=0;n<t.x.categories.length;n+=e)_=Math.max(_,l(t.x.categories[n]))}let v={...c,...e.padding},y=n.computePlot({width:a,height:s,padding:v,yLabelWidth:t.y.visible?Math.ceil(m):0,y2LabelWidth:Math.ceil(g),y2Title:!!t.y2?.title&&!!t.y2.visible,xAxisVisible:t.x.visible,xTitle:!!t.x.title&&t.x.visible,yTitle:!!t.y.title&&t.y.visible,fontSize:i.fontSize});e.top&&(y.y+=e.top);let b=t.x.type===`category`?Math.max(1,Math.floor(y.width/(_+14))):t.x.tickCount??Math.max(3,Math.floor(y.width/88)),x=o.axisTicks(t.x,r.x,b);return{plot:y,scales:n.createScales(y,r,t.x.reverse,t.y.reverse),xTicks:x,yTicks:d,y2Ticks:h}},f=(e,t,n,r)=>{let i=e.y2,s=e.y2Map;if(!i||!s||!s.scale)return null;if(s.log){let e=(n[0]-s.offset)/s.scale,t=(n[1]-s.offset)/s.scale,a=o.axisTicks(i,[Math.min(e,t),Math.max(e,t)],r);return{...a,values:a.values.map(e=>e*s.scale+s.offset)}}let c=t.values.map(e=>(e-s.offset)/s.scale),l=c.length>1?Math.abs(c[1]-c[0]):1,u=0;for(let e of c)u=Math.max(u,Math.abs(e));let d=i.format??a.tickFormatter(l,u,e.locale);return{values:t.values,labels:c.map(d),formatValue:i.format??e.formatValue}},p=e=>{let{model:t,view:r,theme:i,width:a,height:s,measure:l}=e,u=Math.max(1,Math.floor((s-40)/(i.fontSize+5))),d=t.x.tickCount??(t.x.type===`category`?u:s>=220?5:Math.max(2,Math.round((s-48)/52))),f=o.axisTicks(t.x,r.x,d),p=0;if(t.x.visible){if(t.x.type===`category`){let e=t.x.categories,n=Math.max(1,Math.floor(e.length/200));for(let r=0;r<e.length;r+=n){let n=t.x.format?t.x.format(r):e[r];p=Math.max(p,l(n))}}else for(let e of f.labels)p=Math.max(p,l(e))}let m={...c,...e.padding},h=n.computePlot({width:a,height:s,padding:m,yLabelWidth:t.x.visible?Math.ceil(p):0,xAxisVisible:t.y.visible,xTitle:!!t.y.title&&t.y.visible,yTitle:!!t.x.title&&t.x.visible,fontSize:i.fontSize});e.top&&(h.y+=e.top);let g=t.y.tickCount??(t.y.type===`category`?Math.max(1,Math.floor(h.width/60)):Math.max(t.y.type===`time`?4:3,Math.min(8,Math.floor(h.width/88)))),_=o.axisTicks(t.y,r.y,g);return{plot:h,scales:n.createScales(h,r,t.x.reverse,t.y.reverse,!0),xTicks:f,yTicks:_,y2Ticks:null}},m=(e,t,n)=>{let{plot:r}=e,i=r.x,a=r.x+r.width,o=r.y,s=r.y+r.height,c=[],l=[];t.x!==void 0&&Number.isFinite(t.x)&&(e.horizontal?l:c).push(e.xToPx(t.x)),t.y!==void 0&&Number.isFinite(t.y)&&(e.horizontal?c:l).push(e.yToPx(t.y));for(let e of c)e>i&&e<a&&(n.x<e?a=e:i=e);for(let e of l)e>o&&e<s&&(n.y<e?s=e:o=e);return{x:i,y:o,width:a-i,height:s-o}},h=(e,t,i,a,o,c)=>{let l=[],u=e.percent?e.formatValue:a?.formatValue??e.formatValue;for(let a of e.series){if(a.hidden||!a.showLabels)continue;if(a.type===`bar`&&a.barTop){let c=a.format??(a.yAxis===`right`?e.y2?.format??e.formatValue:u),{x:d,count:f}=a.cols,{y:p,y0:m,labels:h}=a.raw,g=a.barTop,[_,v]=t.x[0]<=t.x[1]?t.x:[t.x[1],t.x[0]];for(let t=0;t<f&&l.length<300;t++){let u=d[t]+a.barOffset;if(!Number.isFinite(p[t])||u<_||u>v)continue;let f=g[t]<(a.barBase?.[t]??0)!==e.y.reverse,y=n.toScreen(i,u,g[t]),b=a.floating&&m&&Number.isFinite(m[t]);if(b&&e.y.type===`time`&&!h?.[t])continue;let x=b?p[t]-(m?.[t]??0):0,S=h?.[t]??(b?`${x>0?`+`:``}${c(x)}`:c(p[t]));if(a.labelsInside){let e=a.barBase?.[t]??0,c=a.barHalfWidth,d=a.pointColors?.[t]??a.color,f=[d[0],d[1],d[2],d[3]*s.barOpacity(a,t)],p=o?r.insideLabelColor(f,o):void 0,m=n.toScreen(i,u,(e+g[t])/2);l.push({x:m.x,y:m.y,r:0,text:S,placement:`inside`,align:i.horizontal?`start`:`center`,bar:n.screenRect(i,i.xToPx(u-c),i.xToPx(u+c),i.yToPx(e),i.yToPx(g[t])),...p?{color:p}:{}});continue}l.push({x:y.x,y:y.y,r:0,text:S,placement:i.horizontal?f?`left`:`right`:f?`below`:`above`})}continue}if(a.type!==`scatter`)continue;let{x:d,y:f,count:p,labels:h,size:g}=a.cols;if(h)for(let e=0;e<p&&l.length<300;e++){let r=h[e];if(!r||c&&c.seriesIndex===a.index&&c.index===e)continue;let o=d[e],s=f[e];if(o<t.x[0]||o>t.x[1]||s<t.y[0]||s>t.y[1])continue;let u=g&&g[e]>0?g[e]:a.pointSize,p=n.toScreen(i,o,s);l.push(a.labelCells?{x:p.x,y:p.y,r:u/2,text:r,bounds:m(i,a.labelCells,p)}:{x:p.x,y:p.y,r:u/2,text:r})}}return l},g=e=>e.type===`bar`||e.type===`boxplot`?e.barOffset:0,_=(e,t,r)=>{let i=n.toScreen(r,e.cols.x[t]+g(e),s.plottedY(e,t));return{px:i.x,py:i.y}},v=(e,t,n,r,i,a,o)=>{let s=e.yToPx(r),c=e.yToPx(i);return Math.abs(a-t)<=n&&o>=Math.min(s,c)-2&&o<=Math.max(s,c)+2},y=(e,t,r,i,a)=>{let o=_(e,t,a),s=n.alongX(a,r,i),c=n.alongY(a,r,i),l=a.xToPx(e.cols.x[t]+g(e)),u=!1;if(e.type===`bar`&&e.barBase&&e.barTop)u=v(a,l,e.barHalfWidth/Math.abs(a.xPerPx),e.barBase[t],e.barTop[t],s,c);else if(e.type===`candlestick`||e.type===`boxplot`){let{high:n,low:r,y:i}=e.cols;u=v(a,l,Math.max(e.barHalfWidth/Math.abs(a.xPerPx),3),n?n[t]:i[t],r?r[t]:i[t],s,c)}return{series:e,index:t,px:o.px,py:o.py,dx:Math.abs(a.xToPx(e.cols.x[t])-s),dist:u?0:Math.hypot(o.px-r,o.py-i),inside:u}},b=(e,t,r,i,a,o)=>{let s=e.cols.outliers?.[t];if(!s)return;let c=a.xToPx(e.cols.x[t]+g(e)),l=n.alongX(a,r,i)-c,u=n.alongY(a,r,i),d=e.outlierSize/2+4+o,f,p=d;return s.forEach((n,r)=>{let i=Math.hypot(l,a.yToPx(n)-u);i<=p&&(p=i,f=e.raw.outliers?.[t]?.[r]??n)}),f},x=(e,t)=>e.cols.size&&e.cols.size[t]>0?e.cols.size[t]:e.pointSize,S=new WeakMap,ee=e=>{let t=e.cols.size;if(!t)return e.pointSize;let n=S.get(t);if(n===void 0){n=e.pointSize;for(let e=0;e<t.length;e++)t[e]>n&&(n=t[e]);S.set(t,n)}return n},C=(e,t,r,i,a)=>{let o=Math.max(ee(e)/2+6,10)+a,c=n.toData(i,t,r),l=o*Math.abs(i.xPerPx),u=o*Math.abs(i.yPerPx),d=-1,f=1/0,{x:p,y:m}=e.cols;return s.gridOf(e).query(c.x-l,c.x+l,c.y-u,c.y+u,o=>{let s=n.toScreen(i,p[o],m[o]),c=Math.hypot(s.x-t,s.y-r);c<=Math.max(x(e,o)/2+4,8)+a&&c<=f&&(f=c,d=o)}),d},te=(e,t,n)=>{let{x:r,y:i}=e.cellHalf,{x:a,y:o}=e.cols,c=-1;return s.gridOf(e).query(t-r,t+r,n-i,n+i,s=>{e.cellColors?.[s]&&Math.abs(a[s]-t)<=r&&Math.abs(o[s]-n)<=i&&(c=s)}),c},w=(e,n)=>{let{x:r,y:i,count:a,sorted:o}=e.cols;if(o)return t.nearestIndex(r,i,a,n);let s=-1,c=1/0;for(let e=0;e<a;e++){if(!Number.isFinite(i[e]))continue;let t=Math.abs(r[e]-n);t<c&&(c=t,s=e)}return s},T=(t,n)=>{let r=t.pointColors?.[n],{open:i,high:a,low:o,value:s,y0:c,q1:l,q3:u,outliers:d,labels:f}=t.raw,p=f?.[n],m=r?e.toCss(r):t.colorCss,h={};if(t.type===`candlestick`){let r=i?i[n]:NaN;Number.isFinite(r)&&(h.open=r),a&&Number.isFinite(a[n])&&(h.high=a[n]),o&&Number.isFinite(o[n])&&(h.low=o[n]),m=e.toCss(t.raw.y[n]<r?t.downColor:t.upColor)}else if(t.type===`heatmap`){let r=s?s[n]:t.raw.y[n];Number.isFinite(r)&&(h.value=r);let i=t.cellColors?.[n];i&&(m=e.toCss(e.unpackColor(i)))}else if(t.type===`boxplot`){a&&Number.isFinite(a[n])&&(h.high=a[n]),o&&Number.isFinite(o[n])&&(h.low=o[n]),l&&Number.isFinite(l[n])&&(h.q1=l[n]),u&&Number.isFinite(u[n])&&(h.q3=u[n]);let e=d?.[n];e&&(h.outliers=e.length)}else c&&Number.isFinite(c[n])&&(h.y0=c[n]),t.type===`scatter`&&s&&Number.isFinite(s[n])&&(h.value=s[n]);return{seriesIndex:t.index,seriesId:t.id,seriesName:t.name,index:n,x:t.raw.x[n],y:t.raw.y[n],color:m,...p===void 0?{}:{label:p},...h}},E=(e,t)=>{if(!e.length)return null;e.sort((e,t)=>e.series.index-t.series.index);let n=e.map(e=>{let t=T(e.series,e.index);return e.outlier!==void 0&&(t.outlier=e.outlier),t}),r=n[0].x;return{items:n,x:r,xLabel:t?.formatValue(r)??String(r)}},D=(e,t,r,i,a,o=0)=>{let{plot:s}=t,c=6+o;if(i<s.x-c||i>s.x+s.width+c||a<s.y-c||a>s.y+s.height+c)return null;let l=n.toData(t,i,a),u=[],d=[];for(let n of e.series)if(!n.hidden&&n.tooltip&&n.cols.count!==0){if(n.type===`scatter`){let e=C(n,i,a,t,o);e>=0&&u.push(y(n,e,i,a,t))}else if(n.type===`heatmap`){let e=te(n,l.x,l.y);if(e>=0){let r=y(n,e,i,a,t);r.inside=!0,r.dist=0,u.push(r)}}else{let e=w(n,l.x);if(e<0)continue;let r=y(n,e,i,a,t);n.type===`boxplot`&&(r.outlier=b(n,e,i,a,t,o),r.outlier!==void 0&&(r.inside=!0,r.dist=0)),d.push(r)}}let f=d.filter(e=>(e.series.type===`line`||e.series.type===`area`)&&e.dist<=8+o);if((e.tooltipMode===`item`||e.tooltipMode===`nearest`)&&f.length)return E([f.reduce((e,t)=>t.dist<e.dist?t:e)],r);if(e.tooltipMode===`item`){let e=[...u,...d].filter(e=>e.inside||e.series.type===`scatter`||(e.series.type===`line`||e.series.type===`area`)&&e.dist<=8+o);return e.length?E([e.reduce((e,t)=>t.dist<e.dist||t.dist===e.dist&&t.series.index>e.series.index?t:e)],r):null}if(e.tooltipMode===`nearest`){let e=[...u,...d].filter(e=>e.inside||e.series.type===`scatter`||e.dist<=32+o);return e.length?E([e.reduce((e,t)=>t.dist<=e.dist?t:e)],r):null}if(!d.length)return u.length?E([u.reduce((e,t)=>t.dist<=e.dist?t:e)],r):null;let p=Math.min(...d.map(e=>e.dx)),m=e.x.type===`category`?.5/Math.abs(t.xPerPx):0,h=d.filter(e=>e.dx<=p+Math.max(1,m)),g=h.reduce((e,t)=>t.dx<e.dx?t:e),_=E([g,...h.filter(e=>e!==g),...u],r);return _&&(_.x=T(g.series,g.index).x,_.xLabel=r?.formatValue(_.x)??String(_.x)),_},O=(e,t)=>e===t||!!e&&!!t&&e.items.length===t.items.length&&e.items.every((e,n)=>e.index===t.items[n].index&&e.seriesIndex===t.items[n].seriesIndex),k={style:`percent`,minimumFractionDigits:2,maximumFractionDigits:2},A=(e,t)=>e.raw.details?.[t]?.map(e=>({color:null,name:e.name,value:e.value}))??[],j=(e,t,n,r=null)=>{let o=n?.formatValue??String,s=t=>t.format??(t.yAxis===`right`?r?.formatValue??e.y2?.format??e.formatValue:o),c=e.labels,l=t.items[0],u=l?e.series[l.seriesIndex]:null;if(t.items.length===1&&l&&u?.type===`bar`&&l.y0!==void 0&&e.y.type===`time`){let n=s(u);return{title:l.label??t.xLabel,titleColor:l.color,subtitle:l.label===void 0?u.name:`${t.xLabel} · ${u.name}`,rows:[{color:null,name:c.start,value:n(l.y0)},{color:null,name:c.end,value:n(l.y)},{color:null,name:c.duration,value:a.formatDuration(l.y-l.y0,e.locale)},...A(u,l.index)]}}if(t.items.length===1&&u?.type===`heatmap`){let n=e.y.type===`category`?e.y.categories[Math.round(l.y)]??o(l.y):o(l.y);return{title:`${t.xLabel} · ${n}`,titleColor:null,rows:[{color:l.color,name:l.label??u.name,value:l.value===void 0?`–`:(u.format??e.formatValue)(l.value)},...A(u,l.index)]}}if(t.items.every(t=>e.series[t.seriesIndex].type===`scatter`)&&t.items.length===1){let n=t.items[0],i=e.series[n.seriesIndex],a=n.value===void 0?[]:[{color:null,name:i.valueName??c.value,value:(i.format??e.formatValue)(n.value)}];if(e.x.type===`category`)return{title:n.label??t.xLabel,titleColor:null,rows:[{color:n.color,name:n.seriesName,value:s(i)(n.y)},...a,...A(i,n.index)]};let l=i.yAxis===`right`?r?.formatValue??e.y2?.format??e.formatValue:o,u=[{color:null,name:e.x.title??c.x,value:t.xLabel},{color:null,name:(i.yAxis===`right`?e.y2?.title:e.y.title)??c.y,value:(n.value===void 0?s(i):l)(n.y)},...a,...A(i,n.index)];return{title:n.label??n.seriesName,titleColor:n.color,...n.label!==void 0&&e.series.length>1?{subtitle:n.seriesName}:{},rows:u}}let d=[],f=[],p=t.items.length===1&&u?.type===`bar`&&e.x.type!==`category`&&l?.label!==void 0?l.label:null;for(let n of t.items){let t=e.series[n.seriesIndex],r=s(t);if(f.push(d.length),t.type===`candlestick`){let a=n.open!==void 0&&n.open!==0?(n.y-n.open)/Math.abs(n.open)*100:NaN;d.push({color:n.color,name:t.name,value:Number.isFinite(a)?`${a>=0?`+`:``}${i.numberFormat(e.locale,k).format(a/100)}`:``});let o=[[c.open,n.open],[c.high,n.high],[c.low,n.low],[c.close,n.y]];for(let[e,t]of o)t!==void 0&&Number.isFinite(t)&&d.push({color:null,name:e,value:r(t)});continue}if(t.type===`boxplot`){if(n.outlier!==void 0){d.push({color:n.color,name:n.label?`${n.seriesName} · ${n.label}`:n.seriesName,value:``},{color:null,name:c.outlier,value:r(n.outlier)});continue}d.push({color:n.color,name:n.label?`${n.seriesName} · ${n.label}`:n.seriesName,value:``});let e=[[c.max,n.high],[c.q3,n.q3],[c.median,n.y],[c.q1,n.q1],[c.min,n.low]];for(let[t,n]of e)n!==void 0&&Number.isFinite(n)&&d.push({color:null,name:t,value:r(n)});n.outliers&&d.push({color:null,name:c.outliers,value:String(n.outliers)});continue}let a=r(n.y);if(n.y0!==void 0){let i=n.y-n.y0;a=t.type===`bar`&&e.y.type!==`time`?`${i>0?`+`:``}${r(i)}`:`${r(n.y0)} – ${r(n.y)}`}d.push({color:n.color,name:n.label&&p===null?`${n.seriesName} · ${n.label}`:n.seriesName,value:a}),d.push(...A(t,n.index))}if(e.percent){let n=new Map;for(let r of t.items){let t=M(e,r.seriesIndex);t!==null&&Number.isFinite(r.y)&&n.set(t,(n.get(t)??0)+Math.abs(r.y))}t.items.forEach((t,r)=>{let i=M(e,t.seriesIndex),o=i===null?void 0:n.get(i),s=d[f[r]];o&&s&&Number.isFinite(t.y)&&(s.value=`${(e.series[t.seriesIndex].format??e.formatValue)(t.y)} · ${a.formatPercent(Math.abs(t.y)/o*100,e.locale,!0)}`)})}return{title:p??t.xLabel,titleColor:null,rows:d}},M=(e,t)=>e.series[t].hidden?null:e.stacks[t],ne=(t,r,i)=>{let a=[],{plot:o}=r,s=1/0,c=-1/0;for(let l of i.items){let i=t.series[l.seriesIndex],u=i.cols.x[l.index]??l.x;if(i.type===`boxplot`&&l.outlier!==void 0){let t=n.toScreen(r,u+g(i),V(i,l));a.push({kind:`dot`,x:t.x,y:t.y,size:i.outlierSize+3,color:l.color,halo:e.toCss(i.pointColors?.[l.index]??i.color,.2)});continue}if(i.type===`bar`||i.type===`candlestick`||i.type===`boxplot`){let e=r.xToPx(u+g(i)),n=Math.max(i.barHalfWidth/Math.abs(r.xPerPx),1);s=Math.min(s,e-n),c=Math.max(c,e+n),i.type===`bar`&&a.push(...z(t,r,i,l.index));continue}if(i.type===`heatmap`){let t=r.xToPx(u),s=r.yToPx(l.y),c=Math.abs(i.cellHalf.x/r.xPerPx),d=Math.abs(i.cellHalf.y/r.yPerPx),f=n.screenRect(r,t-c,t+c,s-d,s+d),p=n.heatCellStyle(f.width,f.height,i.radius),m=Math.max(o.y,f.y),h=Math.min(o.y+o.height,f.y+f.height),g=Math.max(o.x,f.x),_=Math.min(o.x+o.width,f.x+f.width);h>m&&a.push({kind:`guide`,x:o.x,y:m,width:o.width,height:h-m}),_>g&&a.push({kind:`guide`,x:g,y:o.y,width:_-g,height:o.height});let v=i.cellColors?.[l.index],y=v?e.unpackColor(v):i.color;a.push({kind:`cell`,x:f.x+p.inset,y:f.y+p.inset,width:Math.max(1,f.width-p.inset*2),height:Math.max(1,f.height-p.inset*2),seriesIndex:i.index,index:l.index,color:l.color,ring:N(y),radius:p.radius});continue}let{px:d,py:f}=_(i,l.index,r);if(d<o.x-1||d>o.x+o.width+1||f<o.y-1||f>o.y+o.height+1)continue;let p=i.type===`scatter`?x(i,l.index)+4:Math.max(9,i.lineWidth*2+5),m=i.pointColors?.[l.index]??i.color;a.push({kind:`dot`,x:d,y:f,size:p,color:l.color,halo:e.toCss(m,.2)})}if(c>s){let e=Math.max(4,(c-s)*.14),t=r.horizontal?o.y:o.x,n=t+(r.horizontal?o.height:o.width),i=Math.max(t,s-e),l=Math.min(n,c+e);l>i&&a.unshift({kind:`band`,...r.horizontal?{x:o.x,y:i,width:o.width,height:l-i}:{x:i,y:o.y,width:l-i,height:o.height}})}return a},N=t=>e.luminance(t)>.45?`rgba(15, 23, 42, 0.78)`:`rgba(255, 255, 255, 0.9)`,P=.6,F=(e,t)=>!t.floating&&e.series.some(e=>e!==t&&!e.hidden&&e.type===`bar`&&!e.floating&&e.barOffset===t.barOffset)?0:t.radius,I=(e,t)=>{let n=1/0;for(let r of e.series){if(r.hidden||r.type!==`bar`&&r.type!==`boxplot`)continue;let e=Math.abs(r.barOffset-t.barOffset);e>0&&e<n&&(n=e)}return Number.isFinite(n)?Math.max(0,n/2-t.barHalfWidth):null},L=(e,t,n,r)=>{let i=Math.min(5,Math.max(1.5,r*.08)),a=I(e,n);return a!==null&&(i=Math.min(i,a/Math.abs(t.xPerPx)*.5)),i>=.75?Math.round(i*4)/4:0},R=(e,t,r,i)=>{let a=r.barBase?.[i],o=r.barTop?.[i],s=r.cols.x[i];if(a===void 0||o===void 0||Number.isNaN(a)||Number.isNaN(o)||!Number.isFinite(s))return null;let{plot:c}=t,l=t.xToPx(s+r.barOffset),u=Math.max(r.barHalfWidth/Math.abs(t.xPerPx),.5),d=t.horizontal?c.x:c.y,f=d+(t.horizontal?c.width:c.height),p=e=>Math.min(f+16,Math.max(d-16,Number.isNaN(e)?d:e)),m=p(t.yToPx(a)),h=p(t.yToPx(o));if(Math.abs(m-h)<.5)return null;let g=n.screenRect(t,l-u,l+u,m,h);return g.x>c.x+c.width||g.x+g.width<c.x||g.y>c.y+c.height||g.y+g.height<c.y?null:{...g,radius:Math.min(F(e,r),g.width/2,g.height/2),base:t.horizontal?m<h?`left`:`right`:m>h?`bottom`:`top`}},z=(t,n,r,i)=>{let a=R(t,n,r,i);if(!a)return[];let o=L(t,n,r,a.base===`top`||a.base===`bottom`?a.width:a.height),c=r.pointColors?.[i]??r.color,l=c[3]*s.barOpacity(r,i),u=l<P,d=[{kind:`bar`,...a,seriesIndex:r.index,index:i,color:e.toCss(c,s.barOpacity(r,i)),backdrop:l<.98,ring:u?e.toCss([c[0],c[1],c[2],1]):N(c),grow:o}],f=Math.min(r.barBase?.[i]??NaN,r.barTop?.[i]??NaN),p=Math.max(r.barBase?.[i]??NaN,r.barTop?.[i]??NaN);if(!r.floating||!(p>=f))return d;let m=(p-f)*1e-9;for(let a of t.series)if(a!==r&&!a.hidden&&!a.tooltip&&a.type===`bar`&&a.floating&&a.barOffset===r.barOffset&&a.barBase&&a.barTop)for(let c=0;c<a.cols.count;c++){if(a.cols.x[c]!==r.cols.x[i])continue;let l=Math.min(a.barBase[c],a.barTop[c]),u=Math.max(a.barBase[c],a.barTop[c]);if(!(l>=f-m&&u<=p+m))continue;let h=R(t,n,a,c);if(!h)continue;let g=a.pointColors?.[c]??a.color;d.push({kind:`bar`,...h,seriesIndex:a.index,index:c,color:e.toCss(g,s.barOpacity(a,c)),backdrop:!1,ring:null,grow:o})}return d},B=e=>e.base===`top`||e.base===`bottom`?{x:e.x-e.grow,y:e.y,width:e.width+e.grow*2,height:e.height}:{x:e.x,y:e.y-e.grow,width:e.width,height:e.height+e.grow*2},V=(e,t)=>{let n=e.raw.outliers?.[t.index],r=n?n.indexOf(t.outlier??NaN):-1;return(r>=0?e.cols.outliers?.[t.index]?.[r]:void 0)??t.outlier??0},H=(t,r)=>{let i=[];for(let a of t.series){let t=a.connector;if(!t||a.hidden||a.type!==`bar`||!a.barTop)continue;let{x:o,count:s}=a.cols,c=a.barTop,l=a.barHalfWidth,[u,d]=r.view.x[0]<=r.view.x[1]?r.view.x:[r.view.x[1],r.view.x[0]],f=e.toCss(t.color,.75),p=-1;for(let e=0;e<s&&i.length<1200;e++)if(Number.isFinite(c[e])&&Number.isFinite(o[e])){if(p>=0&&o[e]+l>=u&&o[p]-l<=d){let s=n.toScreen(r,o[p]+a.barOffset+l,c[p]),u=n.toScreen(r,o[e]+a.barOffset-l,c[p]);i.push({x0:s.x,y0:s.y,x1:u.x,y1:u.y,color:f,width:t.width,dash:t.dash})}p=e}}return i},U=(t,n)=>{let r=n.resolve??l,i=e.toCss(n.textMuted,.85);return(t??[]).map(t=>({from:t.from,to:t.to,color:t.color?e.toCss(r(t.color,n.textMuted)):i}))},W={length:6,half:3.5},G=(e,t,n,r)=>{let i={boxes:[],byId:new Map,byRow:new Map,ids:new Set},a=e.x.type===`category`?e.x.categories:null;for(let o of e.series){if(o.type!==`bar`&&o.type!==`scatter`)continue;let e=o.raw.ids;if(e)for(let t of e)t!==void 0&&i.ids.add(t);if(o.hidden||!o.tooltip)continue;let{x:s,y:c,count:l}=o.cols,u=o.type===`bar`&&o.barBase&&o.barTop,d=g(o);for(let f=0;f<l;f++){let l=u?o.barBase[f]:c[f],p=u?o.barTop[f]:c[f];if(!Number.isFinite(s[f])||!Number.isFinite(l)||!Number.isFinite(p))continue;let m=u?o.barHalfWidth/Math.abs(t.xPerPx):x(o,f)/2,h=n(Math.min(l,p)),g=n(Math.max(l,p)),_=u?0:m,v={c:r(s[f]+d),half:m,start:h,end:g,lo:Math.min(h,g)-_,hi:Math.max(h,g)+_,dot:!u};i.boxes.push(v);let y=e?.[f];y!==void 0&&!i.byId.has(y)&&i.byId.set(y,v);let b=a?a[Math.round(s[f])]:String(o.raw.x[f]);b!==void 0&&!i.byRow.has(b)&&i.byRow.set(b,v)}}return i},K=8,q=4,J=e=>{let t=e.map(e=>[e.lo-q,e.hi+q]).sort((e,t)=>e[0]-t[0]),n=[];for(let e of t){let t=n[n.length-1];t&&e[0]<=t[1]?t[1]=Math.max(t[1],e[1]):n.push(e)}return n},Y=(e,t)=>e.some(([e,n])=>t>e+1e-6&&t<n-1e-6),X=(e,t,n,r)=>{let i=[t];for(let[t,n]of e)i.push(t,n);let a=null;for(let o of i){let i=r*(o-t);i<0||r*(n-o)<0||Y(e,o)||(a===null||i<r*(a-t))&&(a=o)}return a},re=(e,t)=>{let n=e.find(([e,n])=>t>e+1e-6&&t<n-1e-6);if(!n)return t;let[r,i]=n;return t-r<=i-t?r:i},Z=e=>{let t=[],n=(e,t)=>Math.abs(e-t)<1e-6;for(let r of e){let e=t[t.length-1];if(e&&n(e[0],r[0])&&n(e[1],r[1]))continue;let i=t[t.length-2];i&&e&&(n(i[0],e[0])&&n(e[0],r[0])||n(i[1],e[1])&&n(e[1],r[1]))&&t.pop(),t.push(r)}return t},ie=(e,t,n,r,i,a)=>{let o=e.c,s=t.c,c=n+i*K,l=i*(r-c)>=0,u=Math.min(o,s),d=Math.max(o,s),f=d-u<.5?[]:a.filter(n=>n!==e&&n!==t&&n.c+n.half>u&&n.c-n.half<d);if(l){let e=X(J(f),c,r,i);if(e!==null)return Z([[n,o],[e,o],[e,s],[r,s]])}let p=Math.sign(s-o)||1,m=new Map;for(let e of f){if(Math.abs(e.c-o)<.5||Math.abs(e.c-s)<.5)continue;let t=Math.round(e.c*2),n=m.get(t);n?(n.half=Math.max(n.half,e.half),n.of.push(e)):m.set(t,{c:e.c,half:e.half,of:[e]})}let h=[{c:o,half:e.half,lanes:[]},...[...m.values()].sort((e,t)=>p*(e.c-t.c)).map(e=>({c:e.c,half:e.half,lanes:J(e.of)})),{c:s,half:t.half,lanes:[]}],g=r-i*K,_=[[n,o],[c,o]],v=c;for(let e=0;e+1<h.length;e++){let t=h[e],n=h[e+1],a=Math.abs(n.c-t.c)<.5?t.c+p*(Math.max(t.half,n.half)+q):(t.c+p*t.half+n.c-p*n.half)/2,o=e+2===h.length?l&&i*(r-v)>=0?v:g:re(n.lanes,l?v:g);o!==v&&(_.push([v,a],[o,a]),v=o)}return _.push([v,s],[r,s]),Z(_)},ae=(e,t,r)=>{if(!r.length)return[];let i=t.horizontal,a=(e,t)=>i?{x:e,y:t}:{x:t,y:e},o=e=>{let r=n.toScreen(t,0,e);return i?r.x:r.y},s=e=>{let r=n.toScreen(t,e,0);return i?r.y:r.x},c=Math.sign(o(t.view.y[1])-o(t.view.y[0]))||1,l=G(e,t,o,s),u=e=>l.byId.get(e)??(l.ids.has(e)?void 0:l.byRow.get(e)),{length:d,half:f}=W,p=[];for(let e of r){let t=u(e.from),n=u(e.to);if(!t||!n||t===n)continue;let r=t.end+(t.dot?c*t.half:0),i=n.start-c*(n.dot?n.half+1:1),o=i-c*d,s=ie(t,n,r,o,c,l.boxes);p.push({points:s.map(([e,t])=>a(e,t)),head:[a(i,n.c),a(o,n.c-f),a(o,n.c+f)],color:e.color,width:1.25})}return p},oe=12,Q=t=>{if(!t.series.length||t.series.some(e=>e.type!==`heatmap`))return null;let n=t.series.find(e=>!e.hidden&&e.colorLut),r=n?.colorLut;if(!n||!r)return null;let i=[];for(let t=0;t<oe;t++){let n=r[Math.round(t/11*(r.length-1))];i.push(e.toCss(e.unpackColor(n??0)))}let a=n.format??t.formatValue,[o,s]=n.valueRange,c=[{at:0,text:a(o)},{at:1,text:a(s)}],l=n.colorMidpoint;return l!==null&&l>o&&l<s&&c.splice(1,0,{at:.5,text:a(l)}),{seriesIndex:n.index,stops:i,labels:c}},se=(e,t,n)=>e===void 0?n>1||Q(t)!==null:!!e,ce=e=>e===`scatter`?`dot`:e===`line`?`line`:`square`,$=(e,t,n)=>n??(e.tooltipMode===`axis`&&t.items.some(t=>{let n=e.series[t.seriesIndex].type;return n===`line`||n===`area`})&&!t.items.some(t=>{let n=e.series[t.seriesIndex].type;return n===`bar`||n===`candlestick`||n===`boxplot`})),le=(e,t,n,r)=>{if(!$(e,n,r))return null;let i=n.items[0],a=t.xToPx(e.series[i.seriesIndex]?.cols.x[i.index]??s.toPlotX(e,i.x)),o=t.horizontal?t.plot.y:t.plot.x,c=o+(t.horizontal?t.plot.height:t.plot.width);return a>=o&&a<=c?a:null};exports.ARROW_HEAD=W,exports.DEFAULT_PADDING=c,exports.collectPointLabels=h,exports.colorLegend=Q,exports.connectorSegments=H,exports.contrastRing=N,exports.crosshairAt=le,exports.dependencyArrows=ae,exports.dotSize=x,exports.fallbackResolve=l,exports.hitTest=D,exports.hoverItemOf=T,exports.hoverMarks=ne,exports.labelCell=m,exports.layoutChart=d,exports.legendShape=ce,exports.legendShown=se,exports.liftedBarRect=B,exports.pointOf=_,exports.resolveAnnotations=u,exports.resolveDependencies=U,exports.sameHover=O,exports.showsCrosshair=$,exports.tooltipContent=j;
1
+ const e=require("./color.cjs"),t=require("./data.cjs"),n=require("./layout.cjs"),r=require("./overlay.cjs"),i=require("./locale.cjs"),a=require("./format.cjs"),o=require("./axis.cjs"),s=require("./model.cjs");var c={top:12,right:16,bottom:4,left:4},l=(e,t)=>t,u=(t,n,r,i)=>{let a=n.resolve??l,o=e=>r&&e!==void 0?r(e):e,s=e=>i&&e!==void 0?i(e):e;return(t??[]).map(t=>{if(t.type===`rect`){let r=t.color?a(t.color,n.primary):n.primary;return{type:`rect`,x0:s(t.x0),x1:s(t.x1),y0:o(t.y0),y1:o(t.y1),color:r,opacity:t.opacity??.08,label:t.label,labelPosition:t.labelPosition??`top-left`,labelColor:t.labelColor?a(t.labelColor,r):e.mix(r,n.text,.2),...t.badge?{badge:t.badge}:{},...t.detail?{detail:t.detail}:{},...t.description?{description:t.description}:{}}}return t.type===`text`?{type:`text`,x:s(t.x),y:o(t.y),text:t.text,anchor:t.anchor??`center`,color:t.color?a(t.color,n.textMuted):n.textMuted,weight:t.weight??500}:{type:`line`,axis:t.axis,value:t.axis===`y`?o(t.value):s(t.value),color:t.color?a(t.color,n.textMuted):n.textMuted,width:t.width??1,dash:[...t.dash??[4,4]],label:t.label}})},d=e=>{let{model:t,view:r,theme:i,width:a,height:s,measure:l}=e;if(t.horizontal)return p(e);let u=t.y.tickCount??(t.y.type===`category`?Math.max(1,Math.floor((s-40)/(i.fontSize+5))):s>=220?5:Math.max(2,Math.round((s-48)/52))),d=o.axisTicks(t.y,r.y,u),m=0;if(t.y.visible)for(let e of d.labels)m=Math.max(m,l(e));let h=f(t,d,r.y,u),g=0;if(h&&t.y2?.visible)for(let e of h.labels)g=Math.max(g,l(e));let _=48;if(t.x.type===`category`){_=0;let e=Math.max(1,Math.floor(t.x.categories.length/200));for(let n=0;n<t.x.categories.length;n+=e)_=Math.max(_,l(t.x.categories[n]))}let v={...c,...e.padding},y=n.computePlot({width:a,height:s,padding:v,yLabelWidth:t.y.visible?Math.ceil(m):0,y2LabelWidth:Math.ceil(g),y2Title:!!t.y2?.title&&!!t.y2.visible,xAxisVisible:t.x.visible,xTitle:!!t.x.title&&t.x.visible,yTitle:!!t.y.title&&t.y.visible,fontSize:i.fontSize});e.top&&(y.y+=e.top);let b=t.x.type===`category`?Math.max(1,Math.floor(y.width/(_+14))):t.x.tickCount??Math.max(3,Math.floor(y.width/88)),x=o.axisTicks(t.x,r.x,b);return{plot:y,scales:n.createScales(y,r,t.x.reverse,t.y.reverse),xTicks:x,yTicks:d,y2Ticks:h}},f=(e,t,n,r)=>{let i=e.y2,s=e.y2Map;if(!i||!s||!s.scale)return null;if(s.log){let e=(n[0]-s.offset)/s.scale,t=(n[1]-s.offset)/s.scale,a=o.axisTicks(i,[Math.min(e,t),Math.max(e,t)],r);return{...a,values:a.values.map(e=>e*s.scale+s.offset)}}let c=t.values.map(e=>(e-s.offset)/s.scale),l=c.length>1?Math.abs(c[1]-c[0]):1,u=0;for(let e of c)u=Math.max(u,Math.abs(e));let d=i.format??a.tickFormatter(l,u,e.locale);return{values:t.values,labels:c.map(d),formatValue:i.format??e.formatValue}},p=e=>{let{model:t,view:r,theme:i,width:a,height:s,measure:l}=e,u=Math.max(1,Math.floor((s-40)/(i.fontSize+5))),d=t.x.tickCount??(t.x.type===`category`?u:s>=220?5:Math.max(2,Math.round((s-48)/52))),f=o.axisTicks(t.x,r.x,d),p=0;if(t.x.visible){if(t.x.type===`category`){let e=t.x.categories,n=Math.max(1,Math.floor(e.length/200));for(let r=0;r<e.length;r+=n){let n=t.x.format?t.x.format(r):e[r];p=Math.max(p,l(n))}}else for(let e of f.labels)p=Math.max(p,l(e))}let m={...c,...e.padding},h=n.computePlot({width:a,height:s,padding:m,yLabelWidth:t.x.visible?Math.ceil(p):0,xAxisVisible:t.y.visible,xTitle:!!t.y.title&&t.y.visible,yTitle:!!t.x.title&&t.x.visible,fontSize:i.fontSize});e.top&&(h.y+=e.top);let g=t.y.tickCount??(t.y.type===`category`?Math.max(1,Math.floor(h.width/60)):Math.max(t.y.type===`time`?4:3,Math.min(8,Math.floor(h.width/88)))),_=o.axisTicks(t.y,r.y,g);return{plot:h,scales:n.createScales(h,r,t.x.reverse,t.y.reverse,!0),xTicks:f,yTicks:_,y2Ticks:null}},m=(e,t,n)=>{let{plot:r}=e,i=r.x,a=r.x+r.width,o=r.y,s=r.y+r.height,c=[],l=[];t.x!==void 0&&Number.isFinite(t.x)&&(e.horizontal?l:c).push(e.xToPx(t.x)),t.y!==void 0&&Number.isFinite(t.y)&&(e.horizontal?c:l).push(e.yToPx(t.y));for(let e of c)e>i&&e<a&&(n.x<e?a=e:i=e);for(let e of l)e>o&&e<s&&(n.y<e?s=e:o=e);return{x:i,y:o,width:a-i,height:s-o}},h=(e,t,i,a,o,c,l)=>{let u=[],d=e.percent?e.formatValue:a?.formatValue??e.formatValue;for(let a of e.series){if(a.hidden||!a.showLabels)continue;if(a.type===`bar`&&a.barTop){let c=a.format??(a.yAxis===`right`?e.y2?.format??e.formatValue:d),{x:l,count:f}=a.cols,{y:p,y0:m,labels:h}=a.raw,g=a.barTop,[_,v]=t.x[0]<=t.x[1]?t.x:[t.x[1],t.x[0]];for(let t=0;t<f&&u.length<300;t++){let d=l[t]+a.barOffset;if(!Number.isFinite(p[t])||d<_||d>v)continue;let f=g[t]<(a.barBase?.[t]??0)!==e.y.reverse,y=n.toScreen(i,d,g[t]),b=a.floating&&m&&Number.isFinite(m[t]);if(b&&e.y.type===`time`&&!h?.[t])continue;let x=b?p[t]-(m?.[t]??0):0,S=h?.[t]??(b?`${x>0?`+`:``}${c(x)}`:c(p[t]));if(a.labelsInside){let e=a.barBase?.[t]??0,c=a.barHalfWidth,l=a.pointColors?.[t]??a.color,f=[l[0],l[1],l[2],l[3]*s.barOpacity(a,t)],p=o?r.insideLabelColor(f,o):void 0,m=n.toScreen(i,d,(e+g[t])/2);u.push({x:m.x,y:m.y,r:0,text:S,placement:`inside`,align:i.horizontal?`start`:`center`,bar:n.screenRect(i,i.xToPx(d-c),i.xToPx(d+c),i.yToPx(e),i.yToPx(g[t])),...p?{color:p}:{}});continue}u.push({x:y.x,y:y.y,r:0,text:S,placement:i.horizontal?f?`left`:`right`:f?`below`:`above`})}continue}if(a.type!==`scatter`)continue;let{x:f,y:p,count:h,labels:g,size:_}=a.cols;if(g)for(let e=0;e<h&&u.length<300;e++){let r=g[e];if(!r||c&&c.seriesIndex===a.index&&c.index===e)continue;let o=f[e],s=p[e];if(o<t.x[0]||o>t.x[1]||s<t.y[0]||s>t.y[1])continue;let d=_&&_[e]>0?_[e]:a.pointSize,h=n.toScreen(i,o,s),v=a.labelCells?{x:h.x,y:h.y,r:d/2,text:r,bounds:m(i,a.labelCells,h)}:{x:h.x,y:h.y,r:d/2,text:r};l&&l.seriesIndex===a.index&&l.index===e&&(v.hidden=!0),u.push(v)}}return u},g=e=>e.type===`bar`||e.type===`boxplot`?e.barOffset:0,_=(e,t,r)=>{let i=n.toScreen(r,e.cols.x[t]+g(e),s.plottedY(e,t));return{px:i.x,py:i.y}},v=(e,t,n,r,i,a,o)=>{let s=e.yToPx(r),c=e.yToPx(i);return Math.abs(a-t)<=n&&o>=Math.min(s,c)-2&&o<=Math.max(s,c)+2},y=(e,t,r,i,a)=>{let o=_(e,t,a),s=n.alongX(a,r,i),c=n.alongY(a,r,i),l=a.xToPx(e.cols.x[t]+g(e)),u=!1;if(e.type===`bar`&&e.barBase&&e.barTop)u=v(a,l,e.barHalfWidth/Math.abs(a.xPerPx),e.barBase[t],e.barTop[t],s,c);else if(e.type===`candlestick`||e.type===`boxplot`){let{high:n,low:r,y:i}=e.cols;u=v(a,l,Math.max(e.barHalfWidth/Math.abs(a.xPerPx),3),n?n[t]:i[t],r?r[t]:i[t],s,c)}return{series:e,index:t,px:o.px,py:o.py,dx:Math.abs(a.xToPx(e.cols.x[t])-s),dist:u?0:Math.hypot(o.px-r,o.py-i),inside:u}},b=(e,t,r,i,a,o)=>{let s=e.cols.outliers?.[t];if(!s)return;let c=a.xToPx(e.cols.x[t]+g(e)),l=n.alongX(a,r,i)-c,u=n.alongY(a,r,i),d=e.outlierSize/2+4+o,f,p=d;return s.forEach((n,r)=>{let i=Math.hypot(l,a.yToPx(n)-u);i<=p&&(p=i,f=e.raw.outliers?.[t]?.[r]??n)}),f},x=(e,t)=>e.cols.size&&e.cols.size[t]>0?e.cols.size[t]:e.pointSize,S=new WeakMap,ee=e=>{let t=e.cols.size;if(!t)return e.pointSize;let n=S.get(t);if(n===void 0){n=e.pointSize;for(let e=0;e<t.length;e++)t[e]>n&&(n=t[e]);S.set(t,n)}return n},C=(e,t,r,i,a)=>{let o=Math.max(ee(e)/2+6,10)+a,c=n.toData(i,t,r),l=o*Math.abs(i.xPerPx),u=o*Math.abs(i.yPerPx),d=-1,f=1/0,{x:p,y:m}=e.cols;return s.gridOf(e).query(c.x-l,c.x+l,c.y-u,c.y+u,o=>{let s=n.toScreen(i,p[o],m[o]),c=Math.hypot(s.x-t,s.y-r);c<=Math.max(x(e,o)/2+4,8)+a&&c<=f&&(f=c,d=o)}),d},te=(e,t,n)=>{let{x:r,y:i}=e.cellHalf,{x:a,y:o}=e.cols,c=-1;return s.gridOf(e).query(t-r,t+r,n-i,n+i,s=>{e.cellColors?.[s]&&Math.abs(a[s]-t)<=r&&Math.abs(o[s]-n)<=i&&(c=s)}),c},w=(e,n)=>{let{x:r,y:i,count:a,sorted:o}=e.cols;if(o)return t.nearestIndex(r,i,a,n);let s=-1,c=1/0;for(let e=0;e<a;e++){if(!Number.isFinite(i[e]))continue;let t=Math.abs(r[e]-n);t<c&&(c=t,s=e)}return s},T=(t,n)=>{let r=t.pointColors?.[n],{open:i,high:a,low:o,value:s,y0:c,q1:l,q3:u,outliers:d,labels:f}=t.raw,p=f?.[n],m=r?e.toCss(r):t.colorCss,h={};if(t.type===`candlestick`){let r=i?i[n]:NaN;Number.isFinite(r)&&(h.open=r),a&&Number.isFinite(a[n])&&(h.high=a[n]),o&&Number.isFinite(o[n])&&(h.low=o[n]),m=e.toCss(t.raw.y[n]<r?t.downColor:t.upColor)}else if(t.type===`heatmap`){let r=s?s[n]:t.raw.y[n];Number.isFinite(r)&&(h.value=r);let i=t.cellColors?.[n];i&&(m=e.toCss(e.unpackColor(i)))}else if(t.type===`boxplot`){a&&Number.isFinite(a[n])&&(h.high=a[n]),o&&Number.isFinite(o[n])&&(h.low=o[n]),l&&Number.isFinite(l[n])&&(h.q1=l[n]),u&&Number.isFinite(u[n])&&(h.q3=u[n]);let e=d?.[n];e&&(h.outliers=e.length)}else c&&Number.isFinite(c[n])&&(h.y0=c[n]),t.type===`scatter`&&s&&Number.isFinite(s[n])&&(h.value=s[n]);return{seriesIndex:t.index,seriesId:t.id,seriesName:t.name,index:n,x:t.raw.x[n],y:t.raw.y[n],color:m,...p===void 0?{}:{label:p},...h}},E=(e,t)=>{if(!e.length)return null;e.sort((e,t)=>e.series.index-t.series.index);let n=e.map(e=>{let t=T(e.series,e.index);return e.outlier!==void 0&&(t.outlier=e.outlier),t}),r=n[0].x;return{items:n,x:r,xLabel:t?.formatValue(r)??String(r)}},D=(e,t,r,i,a,o=0)=>{let{plot:s}=t,c=6+o;if(i<s.x-c||i>s.x+s.width+c||a<s.y-c||a>s.y+s.height+c)return null;let l=n.toData(t,i,a),u=[],d=[];for(let n of e.series)if(!n.hidden&&n.tooltip&&n.cols.count!==0){if(n.type===`scatter`){let e=C(n,i,a,t,o);e>=0&&u.push(y(n,e,i,a,t))}else if(n.type===`heatmap`){let e=te(n,l.x,l.y);if(e>=0){let r=y(n,e,i,a,t);r.inside=!0,r.dist=0,u.push(r)}}else{let e=w(n,l.x);if(e<0)continue;let r=y(n,e,i,a,t);n.type===`boxplot`&&(r.outlier=b(n,e,i,a,t,o),r.outlier!==void 0&&(r.inside=!0,r.dist=0)),d.push(r)}}let f=d.filter(e=>(e.series.type===`line`||e.series.type===`area`)&&e.dist<=8+o);if((e.tooltipMode===`item`||e.tooltipMode===`nearest`)&&f.length)return E([f.reduce((e,t)=>t.dist<e.dist?t:e)],r);if(e.tooltipMode===`item`){let e=[...u,...d].filter(e=>e.inside||e.series.type===`scatter`||(e.series.type===`line`||e.series.type===`area`)&&e.dist<=8+o);return e.length?E([e.reduce((e,t)=>t.dist<e.dist||t.dist===e.dist&&t.series.index>e.series.index?t:e)],r):null}if(e.tooltipMode===`nearest`){let e=[...u,...d].filter(e=>e.inside||e.series.type===`scatter`||e.dist<=32+o);return e.length?E([e.reduce((e,t)=>t.dist<=e.dist?t:e)],r):null}if(!d.length)return u.length?E([u.reduce((e,t)=>t.dist<=e.dist?t:e)],r):null;let p=Math.min(...d.map(e=>e.dx)),m=e.x.type===`category`?.5/Math.abs(t.xPerPx):0,h=d.filter(e=>e.dx<=p+Math.max(1,m)),g=h.reduce((e,t)=>t.dx<e.dx?t:e),_=E([g,...h.filter(e=>e!==g),...u],r);return _&&(_.x=T(g.series,g.index).x,_.xLabel=r?.formatValue(_.x)??String(_.x)),_},O=(e,t)=>e===t||!!e&&!!t&&e.items.length===t.items.length&&e.items.every((e,n)=>e.index===t.items[n].index&&e.seriesIndex===t.items[n].seriesIndex),k={style:`percent`,minimumFractionDigits:2,maximumFractionDigits:2},A=(e,t)=>e.raw.details?.[t]?.map(e=>({color:null,name:e.name,value:e.value}))??[],j=(e,t,n,r=null)=>{let o=n?.formatValue??String,s=t=>t.format??(t.yAxis===`right`?r?.formatValue??e.y2?.format??e.formatValue:o),c=e.labels,l=t.items[0],u=l?e.series[l.seriesIndex]:null;if(t.items.length===1&&l&&u?.type===`bar`&&l.y0!==void 0&&e.y.type===`time`){let n=s(u);return{title:l.label??t.xLabel,titleColor:l.color,subtitle:l.label===void 0?u.name:`${t.xLabel} · ${u.name}`,rows:[{color:null,name:c.start,value:n(l.y0)},{color:null,name:c.end,value:n(l.y)},{color:null,name:c.duration,value:a.formatDuration(l.y-l.y0,e.locale)},...A(u,l.index)]}}if(t.items.length===1&&u?.type===`heatmap`){let n=e.y.type===`category`?e.y.categories[Math.round(l.y)]??o(l.y):o(l.y);return{title:`${t.xLabel} · ${n}`,titleColor:null,rows:[{color:l.color,name:l.label??u.name,value:l.value===void 0?`–`:(u.format??e.formatValue)(l.value)},...A(u,l.index)]}}if(t.items.every(t=>e.series[t.seriesIndex].type===`scatter`)&&t.items.length===1){let n=t.items[0],i=e.series[n.seriesIndex],a=n.value===void 0?[]:[{color:null,name:i.valueName??c.value,value:(i.format??e.formatValue)(n.value)}];if(e.x.type===`category`)return{title:n.label??t.xLabel,titleColor:null,rows:[{color:n.color,name:n.seriesName,value:s(i)(n.y)},...a,...A(i,n.index)]};let l=i.yAxis===`right`?r?.formatValue??e.y2?.format??e.formatValue:o,u=[{color:null,name:e.x.title??c.x,value:t.xLabel},{color:null,name:(i.yAxis===`right`?e.y2?.title:e.y.title)??c.y,value:(n.value===void 0?s(i):l)(n.y)},...a,...A(i,n.index)];return{title:n.label??n.seriesName,titleColor:n.color,...n.label!==void 0&&e.series.length>1?{subtitle:n.seriesName}:{},rows:u}}let d=[],f=[],p=t.items.length===1&&u?.type===`bar`&&e.x.type!==`category`&&l?.label!==void 0?l.label:null;for(let n of t.items){let t=e.series[n.seriesIndex],r=s(t);if(f.push(d.length),t.type===`candlestick`){let a=n.open!==void 0&&n.open!==0?(n.y-n.open)/Math.abs(n.open)*100:NaN;d.push({color:n.color,name:t.name,value:Number.isFinite(a)?`${a>=0?`+`:``}${i.numberFormat(e.locale,k).format(a/100)}`:``});let o=[[c.open,n.open],[c.high,n.high],[c.low,n.low],[c.close,n.y]];for(let[e,t]of o)t!==void 0&&Number.isFinite(t)&&d.push({color:null,name:e,value:r(t)});continue}if(t.type===`boxplot`){if(n.outlier!==void 0){d.push({color:n.color,name:n.label?`${n.seriesName} · ${n.label}`:n.seriesName,value:``},{color:null,name:c.outlier,value:r(n.outlier)});continue}d.push({color:n.color,name:n.label?`${n.seriesName} · ${n.label}`:n.seriesName,value:``});let e=[[c.max,n.high],[c.q3,n.q3],[c.median,n.y],[c.q1,n.q1],[c.min,n.low]];for(let[t,n]of e)n!==void 0&&Number.isFinite(n)&&d.push({color:null,name:t,value:r(n)});n.outliers&&d.push({color:null,name:c.outliers,value:String(n.outliers)});continue}let a=r(n.y);if(n.y0!==void 0){let i=n.y-n.y0;a=t.type===`bar`&&e.y.type!==`time`?`${i>0?`+`:``}${r(i)}`:`${r(n.y0)} – ${r(n.y)}`}d.push({color:n.color,name:n.label&&p===null?`${n.seriesName} · ${n.label}`:n.seriesName,value:a}),d.push(...A(t,n.index))}if(e.percent){let n=new Map;for(let r of t.items){let t=M(e,r.seriesIndex);t!==null&&Number.isFinite(r.y)&&n.set(t,(n.get(t)??0)+Math.abs(r.y))}t.items.forEach((t,r)=>{let i=M(e,t.seriesIndex),o=i===null?void 0:n.get(i),s=d[f[r]];o&&s&&Number.isFinite(t.y)&&(s.value=`${(e.series[t.seriesIndex].format??e.formatValue)(t.y)} · ${a.formatPercent(Math.abs(t.y)/o*100,e.locale,!0)}`)})}return{title:p??t.xLabel,titleColor:null,rows:d}},M=(e,t)=>e.series[t].hidden?null:e.stacks[t],ne=(t,r,i)=>{let a=[],{plot:o}=r,s=1/0,c=-1/0;for(let l of i.items){let i=t.series[l.seriesIndex],u=i.cols.x[l.index]??l.x;if(i.type===`boxplot`&&l.outlier!==void 0){let t=n.toScreen(r,u+g(i),V(i,l));a.push({kind:`dot`,x:t.x,y:t.y,size:i.outlierSize+3,color:l.color,halo:e.toCss(i.pointColors?.[l.index]??i.color,.2)});continue}if(i.type===`bar`||i.type===`candlestick`||i.type===`boxplot`){let e=r.xToPx(u+g(i)),n=Math.max(i.barHalfWidth/Math.abs(r.xPerPx),1);s=Math.min(s,e-n),c=Math.max(c,e+n),i.type===`bar`&&a.push(...z(t,r,i,l.index));continue}if(i.type===`heatmap`){let t=r.xToPx(u),s=r.yToPx(l.y),c=Math.abs(i.cellHalf.x/r.xPerPx),d=Math.abs(i.cellHalf.y/r.yPerPx),f=n.screenRect(r,t-c,t+c,s-d,s+d),p=n.heatCellStyle(f.width,f.height,i.radius),m=Math.max(o.y,f.y),h=Math.min(o.y+o.height,f.y+f.height),g=Math.max(o.x,f.x),_=Math.min(o.x+o.width,f.x+f.width);h>m&&a.push({kind:`guide`,x:o.x,y:m,width:o.width,height:h-m}),_>g&&a.push({kind:`guide`,x:g,y:o.y,width:_-g,height:o.height});let v=i.cellColors?.[l.index],y=v?e.unpackColor(v):i.color;a.push({kind:`cell`,x:f.x+p.inset,y:f.y+p.inset,width:Math.max(1,f.width-p.inset*2),height:Math.max(1,f.height-p.inset*2),seriesIndex:i.index,index:l.index,color:l.color,ring:N(y),radius:p.radius});continue}let{px:d,py:f}=_(i,l.index,r);if(d<o.x-1||d>o.x+o.width+1||f<o.y-1||f>o.y+o.height+1)continue;let p=i.type===`scatter`?x(i,l.index)+4:Math.max(9,i.lineWidth*2+5),m=i.pointColors?.[l.index]??i.color;a.push({kind:`dot`,x:d,y:f,size:p,color:l.color,halo:e.toCss(m,.2)})}if(c>s){let e=Math.max(4,(c-s)*.14),t=r.horizontal?o.y:o.x,n=t+(r.horizontal?o.height:o.width),i=Math.max(t,s-e),l=Math.min(n,c+e);l>i&&a.unshift({kind:`band`,...r.horizontal?{x:o.x,y:i,width:o.width,height:l-i}:{x:i,y:o.y,width:l-i,height:o.height}})}return a},N=t=>e.luminance(t)>.45?`rgba(15, 23, 42, 0.78)`:`rgba(255, 255, 255, 0.9)`,P=.6,F=(e,t)=>!t.floating&&e.series.some(e=>e!==t&&!e.hidden&&e.type===`bar`&&!e.floating&&e.barOffset===t.barOffset)?0:t.radius,I=(e,t)=>{let n=1/0;for(let r of e.series){if(r.hidden||r.type!==`bar`&&r.type!==`boxplot`)continue;let e=Math.abs(r.barOffset-t.barOffset);e>0&&e<n&&(n=e)}return Number.isFinite(n)?Math.max(0,n/2-t.barHalfWidth):null},L=(e,t,n,r)=>{let i=Math.min(5,Math.max(1.5,r*.08)),a=I(e,n);return a!==null&&(i=Math.min(i,a/Math.abs(t.xPerPx)*.5)),i>=.75?Math.round(i*4)/4:0},R=(e,t,r,i)=>{let a=r.barBase?.[i],o=r.barTop?.[i],s=r.cols.x[i];if(a===void 0||o===void 0||Number.isNaN(a)||Number.isNaN(o)||!Number.isFinite(s))return null;let{plot:c}=t,l=t.xToPx(s+r.barOffset),u=Math.max(r.barHalfWidth/Math.abs(t.xPerPx),.5),d=t.horizontal?c.x:c.y,f=d+(t.horizontal?c.width:c.height),p=e=>Math.min(f+16,Math.max(d-16,Number.isNaN(e)?d:e)),m=p(t.yToPx(a)),h=p(t.yToPx(o));if(Math.abs(m-h)<.5)return null;let g=n.screenRect(t,l-u,l+u,m,h);return g.x>c.x+c.width||g.x+g.width<c.x||g.y>c.y+c.height||g.y+g.height<c.y?null:{...g,radius:Math.min(F(e,r),g.width/2,g.height/2),base:t.horizontal?m<h?`left`:`right`:m>h?`bottom`:`top`}},z=(t,n,r,i)=>{let a=R(t,n,r,i);if(!a)return[];let o=L(t,n,r,a.base===`top`||a.base===`bottom`?a.width:a.height),c=r.pointColors?.[i]??r.color,l=c[3]*s.barOpacity(r,i),u=l<P,d=[{kind:`bar`,...a,seriesIndex:r.index,index:i,color:e.toCss(c,s.barOpacity(r,i)),backdrop:l<.98,ring:u?e.toCss([c[0],c[1],c[2],1]):N(c),grow:o}],f=Math.min(r.barBase?.[i]??NaN,r.barTop?.[i]??NaN),p=Math.max(r.barBase?.[i]??NaN,r.barTop?.[i]??NaN);if(!r.floating||!(p>=f))return d;let m=(p-f)*1e-9;for(let a of t.series)if(a!==r&&!a.hidden&&!a.tooltip&&a.type===`bar`&&a.floating&&a.barOffset===r.barOffset&&a.barBase&&a.barTop)for(let c=0;c<a.cols.count;c++){if(a.cols.x[c]!==r.cols.x[i])continue;let l=Math.min(a.barBase[c],a.barTop[c]),u=Math.max(a.barBase[c],a.barTop[c]);if(!(l>=f-m&&u<=p+m))continue;let h=R(t,n,a,c);if(!h)continue;let g=a.pointColors?.[c]??a.color;d.push({kind:`bar`,...h,seriesIndex:a.index,index:c,color:e.toCss(g,s.barOpacity(a,c)),backdrop:!1,ring:null,grow:o})}return d},B=e=>e.base===`top`||e.base===`bottom`?{x:e.x-e.grow,y:e.y,width:e.width+e.grow*2,height:e.height}:{x:e.x,y:e.y-e.grow,width:e.width,height:e.height+e.grow*2},V=(e,t)=>{let n=e.raw.outliers?.[t.index],r=n?n.indexOf(t.outlier??NaN):-1;return(r>=0?e.cols.outliers?.[t.index]?.[r]:void 0)??t.outlier??0},H=(t,r)=>{let i=[];for(let a of t.series){let t=a.connector;if(!t||a.hidden||a.type!==`bar`||!a.barTop)continue;let{x:o,count:s}=a.cols,c=a.barTop,l=a.barHalfWidth,[u,d]=r.view.x[0]<=r.view.x[1]?r.view.x:[r.view.x[1],r.view.x[0]],f=e.toCss(t.color,.75),p=-1;for(let e=0;e<s&&i.length<1200;e++)if(Number.isFinite(c[e])&&Number.isFinite(o[e])){if(p>=0&&o[e]+l>=u&&o[p]-l<=d){let s=n.toScreen(r,o[p]+a.barOffset+l,c[p]),u=n.toScreen(r,o[e]+a.barOffset-l,c[p]);i.push({x0:s.x,y0:s.y,x1:u.x,y1:u.y,color:f,width:t.width,dash:t.dash})}p=e}}return i},U=(t,n)=>{let r=n.resolve??l,i=e.toCss(n.textMuted,.85);return(t??[]).map(t=>({from:t.from,to:t.to,color:t.color?e.toCss(r(t.color,n.textMuted)):i}))},W={length:6,half:3.5},G=(e,t,n,r)=>{let i={boxes:[],byId:new Map,byRow:new Map,ids:new Set},a=e.x.type===`category`?e.x.categories:null;for(let o of e.series){if(o.type!==`bar`&&o.type!==`scatter`)continue;let e=o.raw.ids;if(e)for(let t of e)t!==void 0&&i.ids.add(t);if(o.hidden||!o.tooltip)continue;let{x:s,y:c,count:l}=o.cols,u=o.type===`bar`&&o.barBase&&o.barTop,d=g(o);for(let f=0;f<l;f++){let l=u?o.barBase[f]:c[f],p=u?o.barTop[f]:c[f];if(!Number.isFinite(s[f])||!Number.isFinite(l)||!Number.isFinite(p))continue;let m=u?o.barHalfWidth/Math.abs(t.xPerPx):x(o,f)/2,h=n(Math.min(l,p)),g=n(Math.max(l,p)),_=u?0:m,v={c:r(s[f]+d),half:m,start:h,end:g,lo:Math.min(h,g)-_,hi:Math.max(h,g)+_,dot:!u};i.boxes.push(v);let y=e?.[f];y!==void 0&&!i.byId.has(y)&&i.byId.set(y,v);let b=a?a[Math.round(s[f])]:String(o.raw.x[f]);b!==void 0&&!i.byRow.has(b)&&i.byRow.set(b,v)}}return i},K=8,q=4,J=e=>{let t=e.map(e=>[e.lo-q,e.hi+q]).sort((e,t)=>e[0]-t[0]),n=[];for(let e of t){let t=n[n.length-1];t&&e[0]<=t[1]?t[1]=Math.max(t[1],e[1]):n.push(e)}return n},Y=(e,t)=>e.some(([e,n])=>t>e+1e-6&&t<n-1e-6),X=(e,t,n,r)=>{let i=[t];for(let[t,n]of e)i.push(t,n);let a=null;for(let o of i){let i=r*(o-t);i<0||r*(n-o)<0||Y(e,o)||(a===null||i<r*(a-t))&&(a=o)}return a},re=(e,t)=>{let n=e.find(([e,n])=>t>e+1e-6&&t<n-1e-6);if(!n)return t;let[r,i]=n;return t-r<=i-t?r:i},Z=e=>{let t=[],n=(e,t)=>Math.abs(e-t)<1e-6;for(let r of e){let e=t[t.length-1];if(e&&n(e[0],r[0])&&n(e[1],r[1]))continue;let i=t[t.length-2];i&&e&&(n(i[0],e[0])&&n(e[0],r[0])||n(i[1],e[1])&&n(e[1],r[1]))&&t.pop(),t.push(r)}return t},ie=(e,t,n,r,i,a)=>{let o=e.c,s=t.c,c=n+i*K,l=i*(r-c)>=0,u=Math.min(o,s),d=Math.max(o,s),f=d-u<.5?[]:a.filter(n=>n!==e&&n!==t&&n.c+n.half>u&&n.c-n.half<d);if(l){let e=X(J(f),c,r,i);if(e!==null)return Z([[n,o],[e,o],[e,s],[r,s]])}let p=Math.sign(s-o)||1,m=new Map;for(let e of f){if(Math.abs(e.c-o)<.5||Math.abs(e.c-s)<.5)continue;let t=Math.round(e.c*2),n=m.get(t);n?(n.half=Math.max(n.half,e.half),n.of.push(e)):m.set(t,{c:e.c,half:e.half,of:[e]})}let h=[{c:o,half:e.half,lanes:[]},...[...m.values()].sort((e,t)=>p*(e.c-t.c)).map(e=>({c:e.c,half:e.half,lanes:J(e.of)})),{c:s,half:t.half,lanes:[]}],g=r-i*K,_=[[n,o],[c,o]],v=c;for(let e=0;e+1<h.length;e++){let t=h[e],n=h[e+1],a=Math.abs(n.c-t.c)<.5?t.c+p*(Math.max(t.half,n.half)+q):(t.c+p*t.half+n.c-p*n.half)/2,o=e+2===h.length?l&&i*(r-v)>=0?v:g:re(n.lanes,l?v:g);o!==v&&(_.push([v,a],[o,a]),v=o)}return _.push([v,s],[r,s]),Z(_)},ae=(e,t,r)=>{if(!r.length)return[];let i=t.horizontal,a=(e,t)=>i?{x:e,y:t}:{x:t,y:e},o=e=>{let r=n.toScreen(t,0,e);return i?r.x:r.y},s=e=>{let r=n.toScreen(t,e,0);return i?r.y:r.x},c=Math.sign(o(t.view.y[1])-o(t.view.y[0]))||1,l=G(e,t,o,s),u=e=>l.byId.get(e)??(l.ids.has(e)?void 0:l.byRow.get(e)),{length:d,half:f}=W,p=[];for(let e of r){let t=u(e.from),n=u(e.to);if(!t||!n||t===n)continue;let r=t.end+(t.dot?c*t.half:0),i=n.start-c*(n.dot?n.half+1:1),o=i-c*d,s=ie(t,n,r,o,c,l.boxes);p.push({points:s.map(([e,t])=>a(e,t)),head:[a(i,n.c),a(o,n.c-f),a(o,n.c+f)],color:e.color,width:1.25})}return p},oe=12,Q=t=>{if(!t.series.length||t.series.some(e=>e.type!==`heatmap`))return null;let n=t.series.find(e=>!e.hidden&&e.colorLut),r=n?.colorLut;if(!n||!r)return null;let i=[];for(let t=0;t<oe;t++){let n=r[Math.round(t/11*(r.length-1))];i.push(e.toCss(e.unpackColor(n??0)))}let a=n.format??t.formatValue,[o,s]=n.valueRange,c=[{at:0,text:a(o)},{at:1,text:a(s)}],l=n.colorMidpoint;return l!==null&&l>o&&l<s&&c.splice(1,0,{at:.5,text:a(l)}),{seriesIndex:n.index,stops:i,labels:c}},se=(e,t,n)=>e===void 0?n>1||Q(t)!==null:!!e,ce=e=>e===`scatter`?`dot`:e===`line`?`line`:`square`,$=(e,t,n)=>n??(e.tooltipMode===`axis`&&t.items.some(t=>{let n=e.series[t.seriesIndex].type;return n===`line`||n===`area`})&&!t.items.some(t=>{let n=e.series[t.seriesIndex].type;return n===`bar`||n===`candlestick`||n===`boxplot`})),le=(e,t,n,r)=>{if(!$(e,n,r))return null;let i=n.items[0],a=t.xToPx(e.series[i.seriesIndex]?.cols.x[i.index]??s.toPlotX(e,i.x)),o=t.horizontal?t.plot.y:t.plot.x,c=o+(t.horizontal?t.plot.height:t.plot.width);return a>=o&&a<=c?a:null};exports.ARROW_HEAD=W,exports.DEFAULT_PADDING=c,exports.collectPointLabels=h,exports.colorLegend=Q,exports.connectorSegments=H,exports.contrastRing=N,exports.crosshairAt=le,exports.dependencyArrows=ae,exports.dotSize=x,exports.fallbackResolve=l,exports.hitTest=D,exports.hoverItemOf=T,exports.hoverMarks=ne,exports.labelCell=m,exports.layoutChart=d,exports.legendShape=ce,exports.legendShown=se,exports.liftedBarRect=B,exports.pointOf=_,exports.resolveAnnotations=u,exports.resolveDependencies=U,exports.sameHover=O,exports.showsCrosshair=$,exports.tooltipContent=j;
2
2
  //# sourceMappingURL=scene.cjs.map