@antadesign/anta 0.3.31 → 0.3.32

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.
@@ -333,14 +333,15 @@ Install the package to use plots in React, Preact, or plain JavaScript.
333
333
  npm install @antadesign/plot # or pnpm / bun
334
334
  ```
335
335
 
336
- Import `Plot` from `/components` and series factories from `@antadesign/plot`.
337
- React 19 is a peer dependency. For Preact, use `preact/compat` aliases.
336
+ Import `Plot` and series factories from `@antadesign/plot`. These root component
337
+ imports require version `0.1.3` or later. Anta `^0.3.30` and React `^19.0.0` are
338
+ peer dependencies. For Preact, use `preact/compat` aliases.
338
339
 
339
340
  ```tsx
340
- import { Plot } from '@antadesign/plot/components'
341
- import { line } from '@antadesign/plot'
341
+ import { Plot, line } from '@antadesign/plot'
342
342
  import '@antadesign/plot/elements/a-plot-surface'
343
343
  import '@antadesign/anta/elements/a-tooltip'
344
+ import '@antadesign/anta/theme-antune.css'
344
345
 
345
346
  const plotArgs = {
346
347
  height: 300,
@@ -353,8 +354,9 @@ function Example() {
353
354
  ```
354
355
 
355
356
  `Plot` is a function component that uses Anta's configured JSX factory and hooks.
356
- It needs no DOM registration. Import the surface and tooltip registration modules
357
- once in your browser entry; their elements install their styles automatically.
357
+ Importing it does not register browser elements. Import the surface and tooltip
358
+ registration modules once in your browser entry; their elements install their
359
+ base styles automatically. Load your application's Anta theme separately.
358
360
  `Plot` handles canvas setup, drawing, interactions, and cleanup.
359
361
 
360
362
  By default, `Plot` fills its parent. Give the parent a height or set `plotArgs.height`,
@@ -364,9 +366,10 @@ With a worker renderer and a DOM bridge that transfers the surface's canvases,
364
366
 
365
367
  For plain JavaScript or TypeScript, import `@antadesign/plot/elements/a-plot`, then use `<a-plot>` and assign its `plotArgs` property.
366
368
 
367
- For custom host integrations, `/components` also exports `PlotSurface`.
368
- Register it with `@antadesign/plot/elements/a-plot-surface`; your host manages
369
- controllers, drawing, and tooltip content.
369
+ `Plot` owns canvas rendering, interactions, and cleanup. The package also exports
370
+ `PlotSurface` as a low-level JSX wrapper, but controllers and drawing lifecycle
371
+ helpers remain internal. Customize marks through `renderer` and
372
+ `highlight_renderer`, and tooltips through the series or root tooltip callbacks.
370
373
 
371
374
  ## Plot arguments
372
375
 
@@ -683,6 +686,7 @@ Scatter arguments
683
686
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
684
687
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
685
688
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
689
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
686
690
 
687
691
  ```ts
688
692
  import { scatter } from '@antadesign/plot'
@@ -810,6 +814,7 @@ Line arguments
810
814
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
811
815
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
812
816
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
817
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
813
818
 
814
819
  ```ts
815
820
  import { line } from '@antadesign/plot'
@@ -1025,6 +1030,7 @@ Bar arguments
1025
1030
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
1026
1031
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
1027
1032
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
1033
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
1028
1034
 
1029
1035
  ```ts
1030
1036
  import { bar } from '@antadesign/plot'
@@ -1460,6 +1466,7 @@ Area arguments
1460
1466
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
1461
1467
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
1462
1468
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
1469
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
1463
1470
 
1464
1471
  ```ts
1465
1472
  import { area } from '@antadesign/plot'
@@ -1720,6 +1727,7 @@ Rect arguments
1720
1727
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
1721
1728
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
1722
1729
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
1730
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
1723
1731
 
1724
1732
  ```ts
1725
1733
  import { rect } from '@antadesign/plot'
@@ -1908,6 +1916,7 @@ Rule arguments
1908
1916
  | [`on_select?`](#selection-callbacks) | `SelectFn` | None | Callback receiving the selected point and its source row. |
1909
1917
  | `hoverable?` | `boolean` | `true` | Allow the series to participate in hit testing. |
1910
1918
  | `highlight?` | `boolean` | `true` | Draw hover feedback for a hit point. |
1919
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
1911
1920
 
1912
1921
  ```ts
1913
1922
  import { rule } from '@antadesign/plot'
@@ -2079,6 +2088,37 @@ plot.plotArgs = {
2079
2088
  return index < 0 ? null : index
2080
2089
  },
2081
2090
  tooltip: ({ row }) => document.createTextNode('Group ' + row?.name + ': ' + row?.total + ' connections'),
2091
+ highlight_renderer: (series, i, { ctx, inner, color_at, highlight_color_at }) => {
2092
+ const rows = series.rows as typeof groups
2093
+ const group = rows[i]
2094
+ const cx = (inner.left + inner.right) / 2
2095
+ const cy = (inner.top + inner.bottom) / 2
2096
+ const radius = Math.min(inner.right - inner.left, inner.bottom - inner.top) / 2 - 32
2097
+ const point = (a: number) => [cx + radius * Math.cos(a), cy + radius * Math.sin(a)]
2098
+ // Match the main renderer: ribbons take the lower-index group's color.
2099
+ ctx.fillStyle = color_at(i)
2100
+ ctx.globalAlpha = 0.45
2101
+ for (let j = i + 1; j < rows.length; j++) {
2102
+ const source = group.segments[j]
2103
+ const target = rows[j].segments[i]
2104
+ const [sx, sy] = point(source.start)
2105
+ const [tx, ty] = point(target.start)
2106
+ ctx.beginPath()
2107
+ ctx.moveTo(sx, sy)
2108
+ ctx.arc(cx, cy, radius, source.start, source.end)
2109
+ ctx.quadraticCurveTo(cx, cy, tx, ty)
2110
+ ctx.arc(cx, cy, radius, target.start, target.end)
2111
+ ctx.quadraticCurveTo(cx, cy, sx, sy)
2112
+ ctx.closePath()
2113
+ ctx.fill()
2114
+ }
2115
+ ctx.globalAlpha = 1
2116
+ ctx.strokeStyle = highlight_color_at(i)
2117
+ ctx.lineWidth = 13
2118
+ ctx.beginPath()
2119
+ ctx.arc(cx, cy, radius + 7, group.start, group.end)
2120
+ ctx.stroke()
2121
+ },
2082
2122
  renderer: (_, { ctx, inner, color_at }) => {
2083
2123
  const cx = (inner.left + inner.right) / 2
2084
2124
  const cy = (inner.top + inner.bottom) / 2
@@ -2195,11 +2235,12 @@ plot.plotArgs = {
2195
2235
  return null
2196
2236
  },
2197
2237
  tooltip: ({ row }) => document.createTextNode(row?.group + ' · 80 samples · mean ' + Number(row?.mean).toFixed(1)),
2198
- renderer: (_, { ctx, x_scale, resolve_y, color_at, inner }) => {
2238
+ renderer: (series, { ctx, x_scale, resolve_y, color_at, inner }) => {
2199
2239
  const step = (inner.bottom - inner.top) / data.length
2200
2240
  ctx.save()
2201
2241
  // Paint from the top row down, so foreground ridges cover the preceding tails.
2202
- data.forEach((row, i) => {
2242
+ const rows = series.rows as typeof data
2243
+ rows.forEach((row, i) => {
2203
2244
  const center = resolve_y(i)
2204
2245
  if (center === undefined) return
2205
2246
  const baseline = center + step * 0.45
@@ -2213,7 +2254,7 @@ plot.plotArgs = {
2213
2254
  })
2214
2255
  ctx.lineTo(Number(x_scale(100)), baseline)
2215
2256
  ctx.closePath()
2216
- ctx.globalAlpha = [1, 0.7, 0.85, 0.65, 0.8, 0.7][i]
2257
+ ctx.globalAlpha = [1, 0.7, 0.85, 0.65, 0.8, 0.7][data.indexOf(row)]
2217
2258
  ctx.fill()
2218
2259
  ctx.globalAlpha = 1
2219
2260
  ctx.stroke()
@@ -2282,9 +2323,9 @@ plot.plotArgs = {
2282
2323
  data,
2283
2324
  x: 'group',
2284
2325
  color: (_, i) => [
2285
- { light: '#0d9488', dark: '#5eead4' },
2286
- { light: '#7c3aed', dark: '#c4b5fd' },
2287
- { light: '#c2410c', dark: '#fdba74' },
2326
+ { light: 'color-mix(in oklch, #0d9488 60%, transparent)', dark: 'color-mix(in oklch, #5eead4 60%, transparent)' },
2327
+ { light: 'color-mix(in oklch, #7c3aed 60%, transparent)', dark: 'color-mix(in oklch, #c4b5fd 60%, transparent)' },
2328
+ { light: 'color-mix(in oklch, #c2410c 60%, transparent)', dark: 'color-mix(in oklch, #fdba74 60%, transparent)' },
2288
2329
  ][i],
2289
2330
  hit_test: (_, { cursor, y_scale, resolve_x, inner }) => {
2290
2331
  const width = Math.min(34, (inner.right - inner.left) / 9)
@@ -2302,10 +2343,11 @@ plot.plotArgs = {
2302
2343
  tooltip: ({ row }) => document.createTextNode('Group ' + row?.group
2303
2344
  + ' · median ' + Number(row?.median).toFixed(1)
2304
2345
  + ' · middle 50%: ' + Number(row?.q1).toFixed(1) + '–' + Number(row?.q3).toFixed(1)),
2305
- renderer: (_, { ctx, y_scale, resolve_x, color_at, inner }) => {
2346
+ renderer: (series, { ctx, y_scale, resolve_x, color_at, inner }) => {
2306
2347
  const width = Math.min(34, (inner.right - inner.left) / 9)
2307
2348
  ctx.save()
2308
- data.forEach((row, i) => {
2349
+ const rows = series.rows as typeof data
2350
+ rows.forEach((row, i) => {
2309
2351
  const x = resolve_x(i)
2310
2352
  if (x === undefined) return
2311
2353
  ctx.fillStyle = color_at(i)
@@ -2348,6 +2390,73 @@ plot.plotArgs = {
2348
2390
  document.body.append(plot)
2349
2391
  ```
2350
2392
 
2393
+ ##### Custom hover highlights
2394
+
2395
+ Hover the points at x = 20 for the default single-point repaint, x = 50 for an explicit halo, and x = 80 for tooltips with highlighting disabled. Only the hovered point is repainted. Translucent fills strengthen when drawn again; an identical opaque fill may look unchanged.
2396
+
2397
+ Without `highlight_renderer`, Anta calls `renderer` on the overlay with a single-point series view. The aligned `x`, `y`, `rows`, `colors`, `highlight_colors`, and `labels` arrays contain only that point at index 0; scales and bounds are unchanged. Render from the supplied series, not captured full-data arrays, to use this fallback. Set `highlight_color` to override the fallback's color without changing its geometry.
2398
+
2399
+ For connected geometry or a different highlight, supply `highlight_renderer(series, point_index, context)`. It receives the full composed series, the original hovered index, and the normal render helpers plus `highlight_color_at(index)`. Anta handles DPR, clearing, clipping, and canvas-state isolation. Set `highlight: false` to disable either path. Both paths require data and hit testing.
2400
+
2401
+ ```ts
2402
+ import { custom, type CustomRendererFn, type CustomHitTestFn, type CustomHighlightRendererFn } from '@antadesign/plot'
2403
+ import type { APlotElement } from '@antadesign/plot/browser'
2404
+ import '@antadesign/plot/elements/a-plot'
2405
+
2406
+ const plot = document.createElement('a-plot') as APlotElement
2407
+ function highlights() {
2408
+ const renderer: CustomRendererFn<Node> = (series, { ctx, resolve_x, resolve_y, color_at }) => {
2409
+ for (let i = 0; i < series.x.length; i++) {
2410
+ const x = resolve_x(i), y = resolve_y(i)
2411
+ if (x === undefined || y === undefined) continue
2412
+ ctx.fillStyle = color_at(i)
2413
+ ctx.beginPath()
2414
+ ctx.arc(x, y, 16, 0, Math.PI * 2)
2415
+ ctx.fill()
2416
+ }
2417
+ }
2418
+ const hit_test: CustomHitTestFn<Node> = (series, { cursor, resolve_x, resolve_y }) => {
2419
+ for (let i = series.x.length - 1; i >= 0; i--) {
2420
+ const x = resolve_x(i), y = resolve_y(i)
2421
+ if (x !== undefined && y !== undefined && Math.hypot(cursor.x - x, cursor.y - y) <= 16) return i
2422
+ }
2423
+ return null
2424
+ }
2425
+ const highlight_renderer: CustomHighlightRendererFn<Node> = (series, i, { ctx, resolve_x, resolve_y, highlight_color_at }) => {
2426
+ const x = resolve_x(i), y = resolve_y(i)
2427
+ if (x === undefined || y === undefined) return
2428
+ ctx.strokeStyle = highlight_color_at(i)
2429
+ ctx.lineWidth = 3
2430
+ ctx.beginPath()
2431
+ ctx.arc(x, y, 22, 0, Math.PI * 2)
2432
+ ctx.stroke()
2433
+ }
2434
+ return {
2435
+ height: 260,
2436
+ axis: { x: { min: 0, max: 100 }, y: { min: 0, max: 100 } },
2437
+ margin: { top: 12, right: 12, bottom: 28, left: 32 },
2438
+ grid: false, zoom_pan: false,
2439
+ series: [
2440
+ custom<Node>({
2441
+ data: [{ x: 20, y: 35 }, { x: 20, y: 65 }], x: 'x', y: 'y', renderer, hit_test,
2442
+ color: 'color-mix(in oklch, teal 40%, transparent)', tooltip: true,
2443
+ }),
2444
+ custom<Node>({
2445
+ data: [{ x: 50, y: 35 }, { x: 50, y: 65 }], x: 'x', y: 'y', renderer, hit_test, highlight_renderer,
2446
+ color: { light: '#7c3aed', dark: '#c4b5fd' }, tooltip: true,
2447
+ }),
2448
+ custom<Node>({
2449
+ data: [{ x: 80, y: 35 }, { x: 80, y: 65 }], x: 'x', y: 'y', renderer, hit_test,
2450
+ color: '#94a3b8', highlight: false, tooltip: true,
2451
+ }),
2452
+ ],
2453
+ }
2454
+ }
2455
+
2456
+ plot.plotArgs = highlights()
2457
+ document.body.append(plot)
2458
+ ```
2459
+
2351
2460
  Custom arguments
2352
2461
 
2353
2462
  | Field | Type | Default | Description |
@@ -2356,6 +2465,9 @@ Custom arguments
2356
2465
  | `x?` | [`FieldArg`](#data-fields) | Unclaimed | Horizontal field or accessor; omitted axes do not contribute data bounds. |
2357
2466
  | `y?` | [`FieldArg`](#data-fields) | Unclaimed | Vertical field or accessor; omitted axes do not contribute data bounds. |
2358
2467
  | [`renderer`](#custom-rendering) | `CustomRendererFn` | Required | Draw the series using its data and the supplied canvas context and pixel resolvers. |
2468
+ | `highlight_renderer?` | `CustomHighlightRendererFn` | Single-point repaint | Draw on the hover overlay using the full series, hovered index, and highlight context. Requires data and hit testing. |
2469
+ | `highlight?` | `boolean` | `true` | Enable the custom callback or default single-point repaint. |
2470
+ | `highlight_color?` | `ColorArg` | Automatic | Exact hover color, including opacity. For custom series, affects only the fallback renderer. Stacked bars also accept a `ThemeColor[]` palette. |
2359
2471
  | [`hit_test?`](#custom-hit-testing) | `CustomHitTestFn` | None | Return a row index for a hit, or `null`. Required for custom tooltips and selection. |
2360
2472
  | `color?` | [`ColorArg`](#series-colors) | Black | Color made available to the renderer, including optional per-row colors. |
2361
2473
  | `axis_range?` | `{ x?: number[]; y?: number[] }` | Data extent | Explicit `[low, high]` bounds for either axis. |
@@ -2421,7 +2533,11 @@ to declare bounds when they cannot be inferred from the data.
2421
2533
 
2422
2534
  ### Hover highlights
2423
2535
 
2424
- Hover bars A through D to see their color intensify. Bar E sets `highlight: false`, so its appearance stays unchanged. Bar F uses `hoverable: false`, so it does not participate in hit testing.
2536
+ Bars A and B use the default highlight. Bar C uses an opaque orange `highlight_color`, and D uses a translucent magenta override. Bar E sets `highlight: false`, so its appearance stays unchanged. Bar F uses `hoverable: false`, so it does not participate in hit testing.
2537
+
2538
+ Set `highlight_color` to a CSS color, a `{ light, dark }` pair, or a per-row accessor. Stacked bars also accept a color array with one entry per segment. Anta uses the resolved color without shading or changing its opacity. Translucent highlights blend over the original mark. Omit the property to keep the default highlight.
2539
+
2540
+ For custom series, this property changes the fallback renderer's `color`, `colors`, and `color_at`. An explicit `highlight_renderer` keeps control of its canvas colors and helpers. A fallback renderer must use the supplied colors to reflect the override; a hard-coded canvas fill will stay unchanged.
2425
2541
 
2426
2542
  Hover feedback is temporary. For custom geometry, supply a [hit-testing callback](#custom-hit-testing).
2427
2543
 
@@ -2440,9 +2556,16 @@ const data = [
2440
2556
  plot.plotArgs = {
2441
2557
  series: [
2442
2558
  bar<Node>({
2443
- data: data.slice(0, 4), inset: 7, border_radius: 4,
2559
+ data: data.slice(0, 2), inset: 7, border_radius: 4,
2444
2560
  color: { light: 'rgba(13, 148, 136, 0.35)', dark: 'rgba(94, 234, 212, 0.35)' },
2445
2561
  }),
2562
+ bar<Node>({
2563
+ data: data.slice(2, 4), inset: 7, border_radius: 4,
2564
+ color: { light: '#0d9488', dark: '#5eead4' },
2565
+ highlight_color: row => row.x === 'C'
2566
+ ? { light: '#f97316', dark: '#fdba74' }
2567
+ : 'color-mix(in oklch, magenta 50%, transparent)',
2568
+ }),
2446
2569
  bar<Node>({
2447
2570
  data: data.slice(4, 5), inset: 7, border_radius: 4,
2448
2571
  color: { light: '#7c3aed', dark: '#c4b5fd' },
@@ -2557,6 +2680,98 @@ With the React component, `TooltipContent` is a `ReactNode`, including strings
2557
2680
  and JSX. With the standalone browser host, return a DOM `Node`. The core
2558
2681
  leaves the content type to the host.
2559
2682
 
2683
+ #### Composing tooltips across series
2684
+
2685
+ Set `tooltip` on the root plot config to compose one tooltip from all hovered series. The callback receives one slot per declared series, in declaration order. Each populated slot contains `{ series, data }`: `series` is the original factory arguments, and `data` contains the hovered point’s `x`, `y`, and optional `row` and `label`. A series with no hit leaves `undefined`. Destructure the array to match your series order. If you need identifiers, include them in your data rows.
2686
+
2687
+ Use `hit.series.color` to read the original color option, including a color defined outside the data. Factory arguments are retained by reference, not copied or resolved; treat them as read-only. Color accessors remain functions, and theme colors remain light/dark pairs. Manually constructed series without factory arguments have `hit.series === undefined`.
2688
+
2689
+ The root callback receives hits even when a series has no tooltip configured. Series with `hoverable: false` retain an empty slot. Per-series tooltip callbacks are not called while a root callback is configured. Returning `null` or `undefined` hides the tooltip without falling back; removing the root callback restores the existing stacked behavior. The callback is not called when there are no hits.
2690
+
2691
+ Hover the overlapping rectangles to compare baseline and current bounds under one window title. The tooltip matches hits by position, places the values side by side, and calculates the change for each bound. Outside the overlap, missing values appear as “—”.
2692
+
2693
+ ```ts
2694
+ import { rect, type APlotElement } from '@antadesign/plot/browser'
2695
+ import '@antadesign/plot/elements/a-plot'
2696
+
2697
+ const plot = document.createElement('a-plot') as APlotElement
2698
+ const data = [
2699
+ { x: 8, x2: 38, y: 15, y2: 48, name: 'Window A' },
2700
+ { x: 55, x2: 86, y: 48, y2: 82, name: 'Window B' },
2701
+ ]
2702
+
2703
+ plot.plotArgs = {
2704
+ series: [
2705
+ rect({
2706
+ data, tooltip: true,
2707
+ color: { light: 'rgba(13, 148, 136, 0.45)', dark: 'rgba(94, 234, 212, 0.45)' },
2708
+ stroke: { color: { light: '#0d9488', dark: '#5eead4' }, width: 2 },
2709
+ }),
2710
+ rect({
2711
+ data: data.map(row => ({
2712
+ ...row, x: row.x + 12, x2: row.x2 + 8, y: row.y + 12, y2: row.y2 + 10,
2713
+ })),
2714
+ color: { light: 'rgba(124, 58, 237, 0.45)', dark: 'rgba(196, 181, 253, 0.45)' },
2715
+ stroke: { color: { light: '#7c3aed', dark: '#c4b5fd' }, width: 2 },
2716
+ tooltip: ({ row }) => {
2717
+ const content = document.createElement('div')
2718
+ const title = document.createElement('strong')
2719
+ title.textContent = String(row.name)
2720
+ const value = document.createElement('div')
2721
+ value.textContent = `Bounds: x ${row.x}–${row.x2}, y ${row.y}–${row.y2}`
2722
+ content.append(title, value)
2723
+ return content
2724
+ },
2725
+ }),
2726
+ ],
2727
+ tooltip: ([baseline_hit, current_hit]) => {
2728
+ const baseline = baseline_hit?.data.row
2729
+ const current = current_hit?.data.row
2730
+ const content = document.createElement('div')
2731
+ const title = document.createElement('strong')
2732
+ title.textContent = String((current ?? baseline)?.name ?? 'Window comparison')
2733
+ const table = document.createElement('table')
2734
+ const header = table.createTHead().insertRow()
2735
+ for (const label of ['Bound', 'Baseline', 'Current', 'Change']) {
2736
+ const cell = document.createElement('th')
2737
+ cell.scope = 'col'
2738
+ cell.textContent = label
2739
+ header.append(cell)
2740
+ }
2741
+ const body = table.createTBody()
2742
+ for (const [field, label] of [['x', 'X start'], ['x2', 'X end'], ['y', 'Y start'], ['y2', 'Y end']]) {
2743
+ const before = baseline?.[field]
2744
+ const after = current?.[field]
2745
+ const delta = typeof before === 'number' && typeof after === 'number' ? after - before : undefined
2746
+ const row = body.insertRow()
2747
+ const heading = document.createElement('th')
2748
+ heading.scope = 'row'
2749
+ heading.textContent = label
2750
+ row.append(heading)
2751
+ for (const value of [before ?? '—', after ?? '—', delta === undefined ? '—' : `${delta > 0 ? '+' : ''}${delta}`]) {
2752
+ row.insertCell().textContent = String(value)
2753
+ }
2754
+ }
2755
+ content.append(title, table)
2756
+ return content
2757
+ },
2758
+ height: 260,
2759
+ margin: { top: 8, right: 12, bottom: 24, left: 32 },
2760
+ axis: { x: { min: 0, max: 100, label: '' }, y: { min: 0, max: 100, label: '' } },
2761
+ background: { light: '#ffffff', dark: '#151b28' },
2762
+ chrome_color: { light: '#e2e8f0', dark: '#334155' },
2763
+ grid: false, border: false, zoom_pan: false,
2764
+ }
2765
+
2766
+ // Remove the root callback for stacked per-series tooltips:
2767
+ // plot.plotArgs = { ...plot.plotArgs, tooltip: undefined }
2768
+ // Suppress tooltips without falling back:
2769
+ // plot.plotArgs = { ...plot.plotArgs, tooltip: () => undefined }
2770
+ document.body.append(plot)
2771
+ ```
2772
+
2773
+ The callback type is `PlotTooltipFn<TooltipContent>`, receiving `PlotTooltipHit[]`. As with series callbacks, return a DOM `Node` for the standalone browser host or a `ReactNode` for React.
2774
+
2560
2775
  ### Selection
2561
2776
 
2562
2777
  Select a point to display its source data in the preview’s text readout. `on_select` receives the selected point and its original row, so you can update a detail panel or application state.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antadesign/anta",
3
- "version": "0.3.31",
3
+ "version": "0.3.32",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",