@antadesign/anta 0.3.34 → 0.3.35

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 (184) hide show
  1. package/LICENSE.md +14 -1
  2. package/README.md +9 -0
  3. package/dist/anta_helpers.d.ts +46 -30
  4. package/dist/anta_helpers.js +66 -25
  5. package/dist/bundle.css +1 -1
  6. package/dist/bundle.js +2 -1333
  7. package/dist/components/Banner.d.ts +25 -40
  8. package/dist/components/Banner.js +15 -17
  9. package/dist/components/Button.js +1 -0
  10. package/dist/components/ButtonCopy.js +3 -2
  11. package/dist/components/Calendar.js +13 -13
  12. package/dist/components/Card.d.ts +9 -17
  13. package/dist/components/Card.js +50 -46
  14. package/dist/components/Dialog.d.ts +1 -0
  15. package/dist/components/Dialog.js +16 -10
  16. package/dist/components/Expander.d.ts +6 -21
  17. package/dist/components/Expander.js +24 -23
  18. package/dist/components/Icon.d.ts +8 -14
  19. package/dist/components/Input.d.ts +77 -96
  20. package/dist/components/Input.js +23 -27
  21. package/dist/components/InputAutocomplete.d.ts +29 -10
  22. package/dist/components/InputAutocomplete.js +25 -8
  23. package/dist/components/InputDate.js +2 -2
  24. package/dist/components/InputTime.d.ts +10 -4
  25. package/dist/components/InputTime.js +20 -16
  26. package/dist/components/Loader.d.ts +2 -2
  27. package/dist/components/Menu.d.ts +5 -4
  28. package/dist/components/Menu.js +13 -8
  29. package/dist/components/MenuItem.js +1 -14
  30. package/dist/components/MenuItemCopy.js +2 -2
  31. package/dist/components/Panel.d.ts +3 -1
  32. package/dist/components/Panel.js +17 -11
  33. package/dist/components/Progress.d.ts +21 -23
  34. package/dist/components/Progress.js +13 -9
  35. package/dist/components/RadioGroup.js +6 -8
  36. package/dist/components/{select-parts.css → Select.css} +1 -1
  37. package/dist/components/Select.d.ts +53 -35
  38. package/dist/components/Select.js +53 -97
  39. package/dist/components/SelectFaceted.d.ts +7 -3
  40. package/dist/components/SelectFaceted.js +21 -9
  41. package/dist/components/Slider.d.ts +28 -11
  42. package/dist/components/Slider.js +20 -20
  43. package/dist/components/Steps.css +1 -1
  44. package/dist/components/Steps.js +1 -11
  45. package/dist/components/Tabs.d.ts +17 -20
  46. package/dist/components/Tabs.js +5 -8
  47. package/dist/components/Text.d.ts +55 -36
  48. package/dist/components/Text.js +35 -22
  49. package/dist/components/Title.d.ts +16 -26
  50. package/dist/components/Title.js +2 -1
  51. package/dist/components/Toaster.js +9 -2
  52. package/dist/components/Tooltip.d.ts +10 -15
  53. package/dist/components/copy-props.d.ts +14 -3
  54. package/dist/components/copy-props.js +14 -3
  55. package/dist/components/select-tree.d.ts +24 -0
  56. package/dist/components/select-tree.js +35 -0
  57. package/dist/element-base.d.ts +10 -0
  58. package/dist/element-base.js +15 -0
  59. package/dist/elements/a-banner.css +1 -1
  60. package/dist/elements/a-banner.d.ts +4 -1
  61. package/dist/elements/a-banner.js +22 -112
  62. package/dist/elements/a-button.d.ts +2 -1
  63. package/dist/elements/a-button.js +18 -1
  64. package/dist/elements/a-calendar.d.ts +14 -13
  65. package/dist/elements/a-calendar.js +29 -24
  66. package/dist/elements/a-card.css +1 -1
  67. package/dist/elements/a-card.d.ts +0 -9
  68. package/dist/elements/a-card.js +0 -184
  69. package/dist/elements/a-checkbox.css +1 -1
  70. package/dist/elements/a-copy.css +1 -1
  71. package/dist/elements/a-copy.d.ts +1 -5
  72. package/dist/elements/a-copy.js +129 -108
  73. package/dist/elements/a-dialog.css +1 -1
  74. package/dist/elements/a-dialog.d.ts +1 -1
  75. package/dist/elements/a-dialog.js +66 -194
  76. package/dist/elements/a-expander.css +1 -1
  77. package/dist/elements/a-expander.d.ts +4 -30
  78. package/dist/elements/a-expander.js +85 -344
  79. package/dist/elements/a-icon.d.ts +5 -23
  80. package/dist/elements/a-icon.js +1 -2
  81. package/dist/elements/a-input-time.css +1 -1
  82. package/dist/elements/a-input-time.d.ts +2 -1
  83. package/dist/elements/a-input-time.js +101 -168
  84. package/dist/elements/a-input.css +1 -1
  85. package/dist/elements/a-input.d.ts +10 -8
  86. package/dist/elements/a-input.js +155 -230
  87. package/dist/elements/a-loader.d.ts +5 -8
  88. package/dist/elements/a-loader.js +1 -2
  89. package/dist/elements/a-menu-item.css +1 -1
  90. package/dist/elements/a-menu-item.d.ts +5 -3
  91. package/dist/elements/a-menu-item.js +5 -1
  92. package/dist/elements/a-menu.css +1 -1
  93. package/dist/elements/a-menu.d.ts +5 -7
  94. package/dist/elements/a-menu.js +383 -299
  95. package/dist/elements/a-panel.css +1 -1
  96. package/dist/elements/a-panel.js +19 -37
  97. package/dist/elements/a-progress.css +1 -1
  98. package/dist/elements/a-progress.d.ts +0 -22
  99. package/dist/elements/a-progress.js +0 -100
  100. package/dist/elements/a-radio-group.d.ts +1 -1
  101. package/dist/elements/a-radio-group.js +6 -4
  102. package/dist/elements/a-select-faceted.d.ts +1 -1
  103. package/dist/elements/a-select-faceted.js +1 -1
  104. package/dist/elements/a-select.d.ts +1 -1
  105. package/dist/elements/a-select.js +1 -1
  106. package/dist/elements/a-slider.css +1 -1
  107. package/dist/elements/a-slider.d.ts +11 -3
  108. package/dist/elements/a-slider.js +244 -242
  109. package/dist/elements/a-switch.css +1 -1
  110. package/dist/elements/a-tab.css +1 -1
  111. package/dist/elements/a-tabs.css +1 -1
  112. package/dist/elements/a-tabs.d.ts +1 -1
  113. package/dist/elements/a-tabs.js +6 -4
  114. package/dist/elements/a-tag.css +1 -1
  115. package/dist/elements/a-text.css +1 -1
  116. package/dist/elements/a-text.d.ts +6 -43
  117. package/dist/elements/a-text.js +110 -193
  118. package/dist/elements/a-title.css +1 -1
  119. package/dist/elements/a-toast.css +1 -1
  120. package/dist/elements/a-toast.d.ts +10 -45
  121. package/dist/elements/a-toast.js +80 -66
  122. package/dist/elements/a-toaster.css +1 -1
  123. package/dist/elements/a-toaster.js +9 -44
  124. package/dist/elements/a-tooltip.css +1 -1
  125. package/dist/elements/a-tooltip.d.ts +1 -1
  126. package/dist/elements/a-tooltip.js +142 -136
  127. package/dist/elements/copy-behavior.d.ts +1 -1
  128. package/dist/elements/copy-behavior.js +21 -21
  129. package/dist/elements/index.d.ts +3 -3
  130. package/dist/elements/index.js +3 -7
  131. package/dist/elements/input-focus-modality.d.ts +15 -0
  132. package/dist/elements/input-focus-modality.js +44 -0
  133. package/dist/elements/input-trailing-actions.d.ts +5 -0
  134. package/dist/elements/input-trailing-actions.js +38 -0
  135. package/dist/elements/shadow-aria.d.ts +2 -0
  136. package/dist/elements/shadow-aria.js +2 -1
  137. package/dist/elements/value-input.d.ts +3 -0
  138. package/dist/elements/value-input.js +12 -0
  139. package/dist/general_types.d.ts +103 -96
  140. package/dist/index.d.ts +1 -1
  141. package/dist/input-events.d.ts +4 -0
  142. package/dist/input-events.js +15 -0
  143. package/dist/jsx-runtime.d.ts +70 -23
  144. package/dist/jsx-runtime.js +26 -19
  145. package/dist/native-event-props.d.ts +2 -0
  146. package/dist/native-event-props.js +10 -0
  147. package/dist/reset.css +1 -1
  148. package/dist/theme-antithesis.css +10 -1
  149. package/dist/theme-antune.css +1 -1
  150. package/docs/accessibility.md +17 -3
  151. package/docs/changelog.md +348 -2
  152. package/docs/comparison.md +2 -2
  153. package/docs/components/avatar.md +5 -0
  154. package/docs/components/banner.md +117 -187
  155. package/docs/components/button.md +22 -0
  156. package/docs/components/card.md +74 -28
  157. package/docs/components/checkbox.md +9 -10
  158. package/docs/components/dialog.md +83 -32
  159. package/docs/components/expander.md +198 -435
  160. package/docs/components/icon.md +11 -17
  161. package/docs/components/input-autocomplete.md +152 -52
  162. package/docs/components/input-date.md +175 -148
  163. package/docs/components/input-time.md +81 -38
  164. package/docs/components/input.md +343 -349
  165. package/docs/components/loader.md +2 -1
  166. package/docs/components/menu.md +35 -6
  167. package/docs/components/panel.md +18 -0
  168. package/docs/components/progress.md +83 -49
  169. package/docs/components/radio.md +39 -43
  170. package/docs/components/select-faceted.md +54 -7
  171. package/docs/components/select.md +390 -386
  172. package/docs/components/slider.md +136 -19
  173. package/docs/components/steps.md +2 -1
  174. package/docs/components/switch.md +8 -9
  175. package/docs/components/tabs.md +110 -104
  176. package/docs/components/text.md +110 -86
  177. package/docs/components/title.md +47 -33
  178. package/docs/components/toaster.md +242 -84
  179. package/docs/components/tooltip.md +204 -113
  180. package/docs/install-config.md +183 -26
  181. package/docs/packages/plot.md +170 -148
  182. package/docs/theming.md +7 -0
  183. package/package.json +41 -3
  184. package/theme-antithesis-license.md +66 -0
@@ -24,7 +24,7 @@ Combine multiple series in one plot to compare values, show trends, and add cont
24
24
 
25
25
 
26
26
  ```ts
27
- import { area, line, rule, scatter, type PlotArgs, type Series } from '@antadesign/plot'
27
+ import { area, line, rule, scatter, type PlotArgs } from '@antadesign/plot'
28
28
  import '@antadesign/plot/elements/a-plot'
29
29
  import type { APlotElement } from '@antadesign/plot/browser'
30
30
 
@@ -52,8 +52,8 @@ function overviewExample(): PlotArgs<Node> {
52
52
 
53
53
  const meanExpected = forecast.reduce((sum, point) => sum + point.expected, 0) / forecast.length
54
54
 
55
- const series: Series<Node>[] = [
56
- area<Node>({
55
+ const series: PlotArgs<Node>['series'] = [
56
+ area({
57
57
  data: forecast,
58
58
  x: 'hour',
59
59
  y: 'high',
@@ -61,14 +61,14 @@ function overviewExample(): PlotArgs<Node> {
61
61
  color: { light: '#ede9fe', dark: '#30274e' },
62
62
  hoverable: false,
63
63
  }),
64
- rule<Node>({
64
+ rule({
65
65
  y: meanExpected,
66
66
  color: { light: '#d97706', dark: '#fbbf24' },
67
67
  width: 2,
68
68
  dash: [8, 4],
69
69
  hoverable: false,
70
70
  }),
71
- line<Node>({
71
+ line({
72
72
  data: forecast,
73
73
  x: 'hour',
74
74
  y: 'expected',
@@ -77,7 +77,7 @@ function overviewExample(): PlotArgs<Node> {
77
77
  dash: [5, 5],
78
78
  tooltip: ({ x, y }) => document.createTextNode('Forecast at ' + x + 'h: ' + Math.round(Number(y)) + ' requests/s'),
79
79
  }),
80
- line<Node>({
80
+ line({
81
81
  data: trend,
82
82
  x: 'hour',
83
83
  y: 'average',
@@ -85,7 +85,7 @@ function overviewExample(): PlotArgs<Node> {
85
85
  width: 3,
86
86
  tooltip: ({ x, y }) => document.createTextNode('Trend at ' + x + 'h: ' + Math.round(Number(y)) + ' requests/s'),
87
87
  }),
88
- scatter<Node>({
88
+ scatter({
89
89
  data: observations.filter(point => !point.outside),
90
90
  x: 'hour',
91
91
  y: 'actual',
@@ -93,7 +93,7 @@ function overviewExample(): PlotArgs<Node> {
93
93
  size: 4,
94
94
  tooltip: ({ x, y }) => document.createTextNode('Observed at ' + x + 'h: ' + y + ' requests/s'),
95
95
  }),
96
- scatter<Node>({
96
+ scatter({
97
97
  data: observations.filter(point => point.outside),
98
98
  x: 'hour',
99
99
  y: 'actual',
@@ -126,7 +126,7 @@ function overviewExample(): PlotArgs<Node> {
126
126
 
127
127
  const grid = false
128
128
 
129
- const zoom_pan = { x: true, y: true, modifier: false }
129
+ const zoom_pan = { x: true, y: true }
130
130
 
131
131
  // Replace the object to apply a change; Plot does not observe in-place mutation.
132
132
  const plotArgs: PlotArgs<Node> = { ...options, series, axis, margin, grid, zoom_pan }
@@ -165,11 +165,11 @@ function energyExample(): PlotArgs<Node> {
165
165
  ]
166
166
  return {
167
167
  series: [
168
- bar<Node>({ data, y: ['solar', 'wind'],
168
+ bar({ data, y: ['solar', 'wind'],
169
169
  color: [{ light: '#fbbf24', dark: '#d97706' }, { light: '#2dd4bf', dark: '#0d9488' }],
170
170
  inset: 5, border_radius: 3,
171
171
  tooltip: ({ x, y, label }) => document.createTextNode('Site ' + x + ' · ' + label + ': ' + y + ' kW') }),
172
- scatter<Node>({ data, y: 'demand', mark: 'diamond', size: 7,
172
+ scatter({ data, y: 'demand', mark: 'diamond', size: 7,
173
173
  tooltip: ({ x, y }) => document.createTextNode('Site ' + x + ' · Demand: ' + y + ' kW'),
174
174
  color: { light: '#7c3aed', dark: '#c4b5fd' },
175
175
  stroke: { color: { light: '#ffffff', dark: '#151b28' }, width: 1.5 } }),
@@ -210,12 +210,12 @@ function latencyExample(): PlotArgs<Node> {
210
210
  const curve = Array.from({ length: 121 }, (_, i) => ({ x: i * 2, y: density(i * 2) }))
211
211
  return {
212
212
  series: [
213
- area<Node>({ data: curve, y2: 0, color: { light: '#fce7f3', dark: '#452039' }, hoverable: false }),
214
- rect<Node>({ data: bins, color: { light: '#f472b6', dark: '#be185d' },
213
+ area({ data: curve, y2: 0, color: { light: '#fce7f3', dark: '#452039' }, hoverable: false }),
214
+ rect({ data: bins, color: { light: '#f472b6', dark: '#be185d' },
215
215
  tooltip: ({ row, y }) => document.createTextNode(
216
216
  (Number(row.x) - 1) + '–' + (Number(row.x2) + 1) + ' ms · ' + Math.round(Number(y)) + ' requests',
217
217
  ) }),
218
- line<Node>({ data: curve, color: { light: '#9d174d', dark: '#fbcfe8' }, width: 2.5,
218
+ line({ data: curve, color: { light: '#9d174d', dark: '#fbcfe8' }, width: 2.5,
219
219
  tooltip: ({ x, y }) => document.createTextNode('Distribution at ' + x + ' ms: ' + Number(y).toFixed(1) + ' requests') }),
220
220
 
221
221
  ],
@@ -279,24 +279,24 @@ function mixedExample(): PlotArgs<Node> {
279
279
  ]
280
280
  return {
281
281
  series: [
282
- area<Node>({ data: Array.from({ length: 81 }, (_, i) => {
282
+ area({ data: Array.from({ length: 81 }, (_, i) => {
283
283
  const x = i * 1.25
284
284
  const center = 50 + 7 * Math.sin(i / 9) + 3 * Math.cos(i / 4)
285
285
  const spread = 3 + 1.5 * Math.sin(i / 11) ** 2
286
286
  return { x, y: center + spread, y2: center - spread }
287
287
  }), color: { light: '#99f6e4', dark: '#115e59' },
288
288
  stroke: { color: { light: '#14b8a6', dark: '#5eead4' }, width: 1 } }),
289
- ...points.map((point, i) => scatter<Node>({ data: [point], size: [7, 12, 21, 10, 15, 9, 26, 13, 11, 8, 14][i],
289
+ ...points.map((point, i) => scatter({ data: [point], size: [7, 12, 21, 10, 15, 9, 26, 13, 11, 8, 14][i],
290
290
  mark: 'circle', color: colors[i % colors.length],
291
291
  tooltip: ({ x, y }) => document.createTextNode('Point ' + (i + 1) + ' · (' + x + ', ' + y + ')'),
292
292
  stroke: { color: { light: '#ffffff', dark: '#151b28' }, width: 1.5 } })),
293
- rect<Node>({ data: [{ x: 32, x2: 44, y: 31, y2: 47 }],
293
+ rect({ data: [{ x: 32, x2: 44, y: 31, y2: 47 }],
294
294
  color: { light: '#ddd6fe', dark: '#5b21b6' },
295
295
  stroke: { color: { light: '#8b5cf6', dark: '#c4b5fd' }, width: 1.5 } }),
296
- rect<Node>({ data: [{ x: 76, x2: 97, y: 76, y2: 96 }],
296
+ rect({ data: [{ x: 76, x2: 97, y: 76, y2: 96 }],
297
297
  color: { light: 'rgba(254, 215, 170, 0.55)', dark: 'rgba(154, 52, 18, 0.55)' },
298
298
  stroke: { color: { light: '#f97316', dark: '#fdba74' }, width: 1.5 } }),
299
- ...smoothPaths.map((data, i) => line<Node>({ data, width: 2.5, dash: i === 1 ? [7, 5] : [],
299
+ ...smoothPaths.map((data, i) => line({ data, width: 2.5, dash: i === 1 ? [7, 5] : [],
300
300
  tooltip: ({ x, y }) => document.createTextNode(
301
301
  'Line ' + (i + 1) + ' · (' + Number(x).toFixed(1) + ', ' + Number(y).toFixed(1) + ')',
302
302
  ),
@@ -304,7 +304,7 @@ function mixedExample(): PlotArgs<Node> {
304
304
  : { light: '#f97316', dark: '#fdba74' },
305
305
  })),
306
306
 
307
- rule<Node>({ y: 10, color: { light: '#0284c7', dark: '#7dd3fc' }, width: 1.5, dash: [6, 4] }),
307
+ rule({ y: 10, color: { light: '#0284c7', dark: '#7dd3fc' }, width: 1.5, dash: [6, 4] }),
308
308
  ],
309
309
  axis: { x: { min: 0, max: 100, label: '' }, y: { min: 0, max: 100, label: '' } },
310
310
  background: { light: '#ffffff', dark: '#151b28' },
@@ -394,7 +394,7 @@ const examplePoints = [
394
394
 
395
395
  function presentation(): PlotArgs<Node> {
396
396
  return {
397
- series: [scatter<Node>({ data: examplePoints, size: 3,
397
+ series: [scatter({ data: examplePoints, size: 3,
398
398
  color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
399
399
  title: { text: 'Plot title', font: { size: 16, color: { light: '#374151', dark: '#e5e7eb' } } },
400
400
  height: 260,
@@ -429,7 +429,7 @@ const examplePoints = [
429
429
 
430
430
  function spacing(): PlotArgs<Node> {
431
431
  return {
432
- series: [scatter<Node>({ data: examplePoints, size: 3,
432
+ series: [scatter({ data: examplePoints, size: 3,
433
433
  color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
434
434
  height: 260,
435
435
  margin: { top: 40, right: 40, bottom: 68, left: 88 },
@@ -461,12 +461,15 @@ document.body.append(plot)
461
461
  | [`chrome_color?`](#theme-colors) | `string \| { light, dark }` | Theme defaults | Color for axis lines, tick marks, grid lines, and the plot border. Text colors are configured separately. |
462
462
  | [`background?`](#theme-colors) | `boolean \| string \| { light, dark }` | White | Plot fill. `false` paints none; `true` and an absent value use `#fff`. |
463
463
  | [`theme_invert?`](#theme-colors) | `boolean` | Automatic | Forces dark-mode inversion on or off. Absent means invert unless a series color or the background is a `{ light, dark }` pair. |
464
- | [`zoom_pan?`](#zoom-and-pan) | `boolean \| { x?, y?, modifier? }` | Both axes, Ctrl required | Require Ctrl for zoom and pan by default. Set `modifier: false` to allow gestures without Ctrl. Set both axes to `false` to disable zoom and pan. |
464
+ | [`zoom_pan?`](#zoom-and-pan) | `boolean \| { x?, y?, menu_zoom_step? }` | Both continuous axes | Scroll to zoom and drag to pan. Scroll or drag on an axis to affect only that axis. Set both axes to `false` to disable zoom and pan. |
465
465
  | [`viewport?`](#viewport) | `{ x?, y?, key? }` | Full domain | Requested starting window per axis. Applied at mount and on each `key` change, clamped to the full domain. |
466
466
  | [`on_viewport_change?`](#viewport-changes) | `(change: ViewportChange) => void` | None | Fires with each axis's current window and full extent after a gesture or reset. |
467
467
 
468
- A zoomed plot shows a **Reset zoom** button in the plot area; it
469
- disappears once the view is back to its full extent.
468
+ Right-click the plot for **Reset Zoom**, **Zoom Out**, and **Zoom In**.
469
+ Unavailable actions stay visible and disabled. Reset restores the full viewport;
470
+ double-clicking does not reset. Focus the plot zoom controls and press Shift+F10
471
+ or the Context Menu key to open the menu from the keyboard. Ctrl-primary click
472
+ is reserved for rectangle zoom on macOS too; use a secondary click for the menu.
470
473
 
471
474
  ### Axes
472
475
 
@@ -491,7 +494,7 @@ const examplePoints = [
491
494
  function logarithmic(): PlotArgs<Node> {
492
495
  const data = examplePoints.map(({ x, y }) => ({ x, y: 10 ** (y / 20 - 1) }))
493
496
  return {
494
- series: [scatter<Node>({ data, size: 3,
497
+ series: [scatter({ data, size: 3,
495
498
  color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
496
499
  height: 260,
497
500
  margin: { top: 12, right: 14, bottom: 44, left: 80 },
@@ -531,7 +534,7 @@ function timeAxis(): PlotArgs<Node> {
531
534
  const start = Date.UTC(2026, 0, 12)
532
535
  const data = examplePoints.map(({ x, y }) => ({ x: start + x / 100 * 86400000, y }))
533
536
  return {
534
- series: [scatter<Node>({ data, size: 3,
537
+ series: [scatter({ data, size: 3,
535
538
  color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
536
539
  height: 260,
537
540
  margin: { top: 12, right: 16, bottom: 44, left: 76 },
@@ -731,7 +734,7 @@ const data = Array.from({ length: 97 }, (_, i) => ({
731
734
 
732
735
  plot.plotArgs = {
733
736
  series: [
734
- line<Node>({
737
+ line({
735
738
  data,
736
739
  y: 'expected',
737
740
  color: { light: '#c2410c', dark: '#fdba74' },
@@ -739,7 +742,7 @@ plot.plotArgs = {
739
742
  dash: [7, 5],
740
743
  tooltip: ({ y }) => document.createTextNode('Expected: ' + Math.round(Number(y))),
741
744
  }),
742
- line<Node>({
745
+ line({
743
746
  data,
744
747
  y: 'measured',
745
748
  color: { light: '#0891b2', dark: '#67e8f9' },
@@ -776,7 +779,7 @@ const data = Array.from({ length: 13 }, (_, i) => ({
776
779
  }))
777
780
 
778
781
  plot.plotArgs = {
779
- series: [line<Node>({
782
+ series: [line({
780
783
  data,
781
784
  color: { light: '#7c3aed', dark: '#c4b5fd' },
782
785
  width: 3,
@@ -864,7 +867,7 @@ const data = [
864
867
  ]
865
868
 
866
869
  plot.plotArgs = {
867
- series: [bar<Node>({
870
+ series: [bar({
868
871
  data,
869
872
  x: 'day',
870
873
  y: 'requests',
@@ -908,7 +911,7 @@ const data = [
908
911
  ]
909
912
 
910
913
  plot.plotArgs = {
911
- series: [bar<Node>({
914
+ series: [bar({
912
915
  data,
913
916
  x: 'requests',
914
917
  y: 'service',
@@ -952,7 +955,7 @@ const data = [
952
955
  ]
953
956
 
954
957
  plot.plotArgs = {
955
- series: [bar<Node>({
958
+ series: [bar({
956
959
  data,
957
960
  x: 'month',
958
961
  y: 'change',
@@ -991,7 +994,7 @@ function categoryOrder(): PlotArgs<Node> {
991
994
  { severity: 'Critical', count: 12 }, { severity: 'Medium', count: 35 },
992
995
  ]
993
996
  return {
994
- series: [bar<Node>({ data, x: 'severity', y: 'count', inset: 10, border_radius: 3,
997
+ series: [bar({ data, x: 'severity', y: 'count', inset: 10, border_radius: 3,
995
998
  color: { light: '#64748b', dark: '#94a3b8' },
996
999
  tooltip: ({ x, y }) => document.createTextNode(x + ': ' + y + ' issues'),
997
1000
  })],
@@ -1078,7 +1081,7 @@ const data = [
1078
1081
  ]
1079
1082
 
1080
1083
  plot.plotArgs = {
1081
- series: [bar<Node>({
1084
+ series: [bar({
1082
1085
  data,
1083
1086
  x: 'day',
1084
1087
  y: ['network', 'compute', 'storage'],
@@ -1120,7 +1123,7 @@ function stackedHorizontal(): PlotArgs<Node> {
1120
1123
  { service: 'Export', network: 12, compute: 36, storage: 18 },
1121
1124
  ]
1122
1125
  return {
1123
- series: [bar<Node>({ data, x: ['network', 'compute', 'storage'], y: 'service',
1126
+ series: [bar({ data, x: ['network', 'compute', 'storage'], y: 'service',
1124
1127
  color: [
1125
1128
  { light: '#0d9488', dark: '#5eead4' },
1126
1129
  { light: '#6366f1', dark: '#a5b4fc' },
@@ -1163,7 +1166,7 @@ function stackedDiverging(): PlotArgs<Node> {
1163
1166
  { month: 'May', new: 32, expansion: 10, churn: -12, contraction: -8 },
1164
1167
  ]
1165
1168
  return {
1166
- series: [bar<Node>({ data, x: 'month', y: ['new', 'expansion', 'churn', 'contraction'],
1169
+ series: [bar({ data, x: 'month', y: ['new', 'expansion', 'churn', 'contraction'],
1167
1170
  color: [
1168
1171
  { light: '#0d9488', dark: '#2dd4bf' },
1169
1172
  { light: '#5eead4', dark: '#99f6e4' },
@@ -1208,7 +1211,7 @@ function stackedTooltip(): PlotArgs<Node> {
1208
1211
  ]
1209
1212
 
1210
1213
  return {
1211
- series: [bar<Node>({
1214
+ series: [bar({
1212
1215
  data,
1213
1216
  x: 'day',
1214
1217
  y: ['network', 'compute', 'storage'],
@@ -1222,7 +1225,8 @@ function stackedTooltip(): PlotArgs<Node> {
1222
1225
  hover_span_y: false,
1223
1226
  tooltip: ({ label, row }) => {
1224
1227
  const content = document.createElement('div')
1225
- for (const field of ['network', 'compute', 'storage']) {
1228
+ const fields: (keyof typeof row)[] = ['network', 'compute', 'storage']
1229
+ for (const field of fields) {
1226
1230
  const entry = document.createElement('div')
1227
1231
  const value = document.createElement(field === label ? 'strong' : 'span')
1228
1232
  value.textContent = field + ': ' + row[field] + ' ms'
@@ -1295,7 +1299,7 @@ const data = Array.from({ length: 97 }, (_, i) => ({
1295
1299
 
1296
1300
  plot.plotArgs = {
1297
1301
  series: [
1298
- area<Node>({
1302
+ area({
1299
1303
  data,
1300
1304
  y2: 0,
1301
1305
  color: { light: '#99f6e4', dark: '#134e4a' },
@@ -1334,7 +1338,7 @@ const data = Array.from({ length: 81 }, (_, i) => {
1334
1338
 
1335
1339
  plot.plotArgs = {
1336
1340
  series: [
1337
- area<Node>({
1341
+ area({
1338
1342
  data,
1339
1343
  y: 'high',
1340
1344
  y2: 'low',
@@ -1376,21 +1380,21 @@ const data = Array.from({ length: 97 }, (_, i) => {
1376
1380
 
1377
1381
  plot.plotArgs = {
1378
1382
  series: [
1379
- area<Node>({
1383
+ area({
1380
1384
  data,
1381
1385
  y: 'first',
1382
1386
  y2: 0,
1383
1387
  color: { light: '#2dd4bf', dark: '#0d9488' },
1384
1388
  tooltip: ({ row }) => document.createTextNode('Network: ' + Math.round(Number(row.first))),
1385
1389
  }),
1386
- area<Node>({
1390
+ area({
1387
1391
  data,
1388
1392
  y: 'second',
1389
1393
  y2: 'first',
1390
1394
  color: { light: '#a5b4fc', dark: '#6366f1' },
1391
1395
  tooltip: ({ row }) => document.createTextNode('Compute: ' + Math.round(Number(row.second) - Number(row.first))),
1392
1396
  }),
1393
- area<Node>({
1397
+ area({
1394
1398
  data,
1395
1399
  y: 'total',
1396
1400
  y2: 'second',
@@ -1429,7 +1433,7 @@ const data = Array.from({ length: 81 }, (_, i) => {
1429
1433
 
1430
1434
  plot.plotArgs = {
1431
1435
  series: [
1432
- area<Node>({
1436
+ area({
1433
1437
  data,
1434
1438
  x: 'low',
1435
1439
  x2: 'high',
@@ -1528,7 +1532,7 @@ const data = days.flatMap((day, d) => hours.map((hour, h) => ({
1528
1532
 
1529
1533
  plot.plotArgs = {
1530
1534
  series: [
1531
- rect<Node>({
1535
+ rect({
1532
1536
  data,
1533
1537
  x: 'hour',
1534
1538
  y: 'day',
@@ -1573,7 +1577,7 @@ const data = [
1573
1577
 
1574
1578
  plot.plotArgs = {
1575
1579
  series: [
1576
- rect<Node>({
1580
+ rect({
1577
1581
  data,
1578
1582
  x: 'start',
1579
1583
  x2: 'end',
@@ -1616,7 +1620,7 @@ const data = Array.from({ length: 32 }, (_, i) => ({
1616
1620
 
1617
1621
  plot.plotArgs = {
1618
1622
  series: [
1619
- rect<Node>({
1623
+ rect({
1620
1624
  data,
1621
1625
  size: { width: 16, height: 9 },
1622
1626
  color: row => Number(row.value) > 65
@@ -1658,7 +1662,7 @@ const data = Array.from({ length: 36 }, (_, i) => ({
1658
1662
 
1659
1663
  plot.plotArgs = {
1660
1664
  series: [
1661
- rect<Node>({
1665
+ rect({
1662
1666
  data: data.filter(row => row.lane === 'Passed'),
1663
1667
  x: 'end_ms',
1664
1668
  y: 'lane',
@@ -1669,7 +1673,7 @@ plot.plotArgs = {
1669
1673
  stroke: { color: { light: '#ffffff', dark: '#151b28' }, width: 0.5 },
1670
1674
  tooltip: ({ row }) => document.createTextNode('Run ' + row.run + ': ' + row.lane),
1671
1675
  }),
1672
- rect<Node>({
1676
+ rect({
1673
1677
  data: data.filter(row => row.lane === 'Failed'),
1674
1678
  x: 'end_ms',
1675
1679
  y: 'lane',
@@ -1814,19 +1818,19 @@ const data = Array.from({ length: 97 }, (_, i) => ({
1814
1818
 
1815
1819
  plot.plotArgs = {
1816
1820
  series: [
1817
- line<Node>({
1821
+ line({
1818
1822
  data,
1819
1823
  color: { light: '#0891b2', dark: '#67e8f9' },
1820
1824
  width: 2,
1821
1825
  }),
1822
- rule<Node>({
1826
+ rule({
1823
1827
  y: 60,
1824
1828
  color: { light: '#7c3aed', dark: '#c4b5fd' },
1825
1829
  width: 1,
1826
1830
  dash: [7, 4],
1827
1831
  tooltip: () => document.createTextNode('Target: 60 ms'),
1828
1832
  }),
1829
- rule<Node>({
1833
+ rule({
1830
1834
  y: 90,
1831
1835
  color: { light: '#c2410c', dark: '#fdba74' },
1832
1836
  width: 4,
@@ -1869,19 +1873,19 @@ const events = [
1869
1873
 
1870
1874
  plot.plotArgs = {
1871
1875
  series: [
1872
- line<Node>({
1876
+ line({
1873
1877
  data,
1874
1878
  color: { light: '#6366f1', dark: '#a5b4fc' },
1875
1879
  width: 2,
1876
1880
  }),
1877
- rule<Node>({
1881
+ rule({
1878
1882
  data: events.filter(event => !event.recovery),
1879
1883
  x: 'hour',
1880
1884
  color: { light: '#c2410c', dark: '#fdba74' },
1881
1885
  width: 3,
1882
1886
  tooltip: ({ row }) => document.createTextNode(row?.name + ' at hour ' + row?.hour),
1883
1887
  }),
1884
- rule<Node>({
1888
+ rule({
1885
1889
  data: events.filter(event => event.recovery),
1886
1890
  x: 'hour',
1887
1891
  color: { light: '#0d9488', dark: '#5eead4' },
@@ -1982,7 +1986,7 @@ const points = groups.flatMap((group, g) => Array.from({ length: 80 }, (_, i) =>
1982
1986
 
1983
1987
  plot.plotArgs = {
1984
1988
  series: [
1985
- scatter<Node>({
1989
+ scatter({
1986
1990
  data: points,
1987
1991
  size: 3,
1988
1992
  color: row => Number(row.group) === 0
@@ -1990,7 +1994,7 @@ plot.plotArgs = {
1990
1994
  : { light: '#7c3aed', dark: '#c4b5fd' },
1991
1995
  tooltip: ({ x, y }) => document.createTextNode(Number(x).toFixed(1) + ', ' + Number(y).toFixed(1)),
1992
1996
  }),
1993
- custom<Node>({
1997
+ custom({
1994
1998
  data: groups,
1995
1999
  x: 'x', y: 'y',
1996
2000
  color: (_, i) => i === 0
@@ -2068,7 +2072,7 @@ const groups = matrix.map((row, i) => {
2068
2072
  })
2069
2073
 
2070
2074
  plot.plotArgs = {
2071
- series: [custom<Node>({
2075
+ series: [custom({
2072
2076
  data: groups,
2073
2077
  color: (_, i) => [
2074
2078
  { light: '#0d9488', dark: '#5eead4' },
@@ -2213,7 +2217,7 @@ const data = Array.from({ length: 6 }, (_, i) => {
2213
2217
  const peak = Math.max(...data.flatMap(row => row.density.map(point => point.density)))
2214
2218
 
2215
2219
  plot.plotArgs = {
2216
- series: [custom<Node>({
2220
+ series: [custom({
2217
2221
  data,
2218
2222
  y: 'group',
2219
2223
  color: (_, i) => ({ light: 'hsl(' + (175 + i * 15) + ', 55%, 55%)', dark: 'hsl(' + (175 + i * 15) + ', 50%, 45%)' }),
@@ -2320,7 +2324,7 @@ const data = distributions()
2320
2324
  const peak = Math.max(...data.flatMap(row => row.density.map(point => point.density)))
2321
2325
 
2322
2326
  plot.plotArgs = {
2323
- series: [custom<Node>({
2327
+ series: [custom({
2324
2328
  data,
2325
2329
  x: 'group',
2326
2330
  color: (_, i) => [
@@ -2400,13 +2404,14 @@ Without `highlight_renderer`, Anta calls `renderer` on the overlay with a single
2400
2404
  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.
2401
2405
 
2402
2406
  ```ts
2403
- import { custom, type CustomRendererFn, type CustomHitTestFn, type CustomHighlightRendererFn } from '@antadesign/plot'
2407
+ import { custom, type PlotArgs, type CustomRendererFn, type CustomHitTestFn, type CustomHighlightRendererFn } from '@antadesign/plot'
2404
2408
  import type { APlotElement } from '@antadesign/plot/browser'
2405
2409
  import '@antadesign/plot/elements/a-plot'
2406
2410
 
2407
2411
  const plot = document.createElement('a-plot') as APlotElement
2408
- function highlights() {
2409
- const renderer: CustomRendererFn<Node> = (series, { ctx, resolve_x, resolve_y, color_at }) => {
2412
+ function highlights(): PlotArgs<Node> {
2413
+ type Point = { x: number; y: number }
2414
+ const renderer: CustomRendererFn<Point> = (series, { ctx, resolve_x, resolve_y, color_at }) => {
2410
2415
  for (let i = 0; i < series.x.length; i++) {
2411
2416
  const x = resolve_x(i), y = resolve_y(i)
2412
2417
  if (x === undefined || y === undefined) continue
@@ -2416,14 +2421,14 @@ function highlights() {
2416
2421
  ctx.fill()
2417
2422
  }
2418
2423
  }
2419
- const hit_test: CustomHitTestFn<Node> = (series, { cursor, resolve_x, resolve_y }) => {
2424
+ const hit_test: CustomHitTestFn<Point> = (series, { cursor, resolve_x, resolve_y }) => {
2420
2425
  for (let i = series.x.length - 1; i >= 0; i--) {
2421
2426
  const x = resolve_x(i), y = resolve_y(i)
2422
2427
  if (x !== undefined && y !== undefined && Math.hypot(cursor.x - x, cursor.y - y) <= 16) return i
2423
2428
  }
2424
2429
  return null
2425
2430
  }
2426
- const highlight_renderer: CustomHighlightRendererFn<Node> = (series, i, { ctx, resolve_x, resolve_y, highlight_color_at }) => {
2431
+ const highlight_renderer: CustomHighlightRendererFn<Point> = (series, i, { ctx, resolve_x, resolve_y, highlight_color_at }) => {
2427
2432
  const x = resolve_x(i), y = resolve_y(i)
2428
2433
  if (x === undefined || y === undefined) return
2429
2434
  ctx.strokeStyle = highlight_color_at(i)
@@ -2438,15 +2443,15 @@ function highlights() {
2438
2443
  margin: { top: 12, right: 12, bottom: 28, left: 32 },
2439
2444
  grid: false, zoom_pan: false,
2440
2445
  series: [
2441
- custom<Node>({
2446
+ custom({
2442
2447
  data: [{ x: 20, y: 35 }, { x: 20, y: 65 }], x: 'x', y: 'y', renderer, hit_test,
2443
2448
  color: 'color-mix(in oklch, teal 40%, transparent)', tooltip: true,
2444
2449
  }),
2445
- custom<Node>({
2450
+ custom({
2446
2451
  data: [{ x: 50, y: 35 }, { x: 50, y: 65 }], x: 'x', y: 'y', renderer, hit_test, highlight_renderer,
2447
2452
  color: { light: '#7c3aed', dark: '#c4b5fd' }, tooltip: true,
2448
2453
  }),
2449
- custom<Node>({
2454
+ custom({
2450
2455
  data: [{ x: 80, y: 35 }, { x: 80, y: 65 }], x: 'x', y: 'y', renderer, hit_test,
2451
2456
  color: '#94a3b8', highlight: false, tooltip: true,
2452
2457
  }),
@@ -2556,23 +2561,23 @@ const data = [
2556
2561
 
2557
2562
  plot.plotArgs = {
2558
2563
  series: [
2559
- bar<Node>({
2564
+ bar({
2560
2565
  data: data.slice(0, 2), inset: 7, border_radius: 4,
2561
2566
  color: { light: 'rgba(13, 148, 136, 0.35)', dark: 'rgba(94, 234, 212, 0.35)' },
2562
2567
  }),
2563
- bar<Node>({
2568
+ bar({
2564
2569
  data: data.slice(2, 4), inset: 7, border_radius: 4,
2565
2570
  color: { light: '#0d9488', dark: '#5eead4' },
2566
2571
  highlight_color: row => row.x === 'C'
2567
2572
  ? { light: '#f97316', dark: '#fdba74' }
2568
2573
  : 'color-mix(in oklch, magenta 50%, transparent)',
2569
2574
  }),
2570
- bar<Node>({
2575
+ bar({
2571
2576
  data: data.slice(4, 5), inset: 7, border_radius: 4,
2572
2577
  color: { light: '#7c3aed', dark: '#c4b5fd' },
2573
2578
  highlight: false,
2574
2579
  }),
2575
- bar<Node>({
2580
+ bar({
2576
2581
  data: data.slice(5), inset: 7, border_radius: 4,
2577
2582
  color: { light: '#94a3b8', dark: '#64748b' },
2578
2583
  hoverable: false,
@@ -2593,14 +2598,14 @@ document.body.append(plot)
2593
2598
 
2594
2599
  #### Custom hit testing
2595
2600
 
2596
- `CustomHitTestFn<TooltipContent>` receives the composed custom series and a
2601
+ `CustomHitTestFn<Row>` receives a `CustomSeriesView<Row>` and a
2597
2602
  `HitContext`. Return the matching row index or `null` when there is no hit.
2598
2603
  Custom series need this callback for tooltips and selection.
2599
2604
 
2600
2605
  ```ts
2601
- import type { ComposedCustom, HitContext } from '@antadesign/plot'
2606
+ import type { CustomSeriesView, HitContext } from '@antadesign/plot'
2602
2607
 
2603
- type HitTest = (series: ComposedCustom, context: HitContext) => number | null
2608
+ type HitTest<Row> = (series: CustomSeriesView<Row>, context: HitContext) => number | null
2604
2609
  ```
2605
2610
 
2606
2611
  | Context field | Type | Description |
@@ -2631,13 +2636,13 @@ const data = [
2631
2636
 
2632
2637
  plot.plotArgs = {
2633
2638
  series: [
2634
- rect<Node>({
2639
+ rect({
2635
2640
  data,
2636
2641
  color: { light: 'rgba(13, 148, 136, 0.45)', dark: 'rgba(94, 234, 212, 0.45)' },
2637
2642
  stroke: { color: { light: '#0d9488', dark: '#5eead4' }, width: 2 },
2638
2643
  tooltip: true,
2639
2644
  }),
2640
- rect<Node>({
2645
+ rect({
2641
2646
  data: data.map(row => ({
2642
2647
  ...row, x: row.x + 12, x2: row.x2 + 8, y: row.y + 12, y2: row.y2 + 10,
2643
2648
  })),
@@ -2695,6 +2700,16 @@ Hover the overlapping rectangles to compare baseline and current bounds under on
2695
2700
  import { rect, type APlotElement } from '@antadesign/plot/browser'
2696
2701
  import '@antadesign/plot/elements/a-plot'
2697
2702
 
2703
+ function windowRow(row: unknown) {
2704
+ if (typeof row !== 'object' || row === null) return undefined
2705
+ if (!('name' in row) || typeof row.name !== 'string'
2706
+ || !('x' in row) || typeof row.x !== 'number'
2707
+ || !('x2' in row) || typeof row.x2 !== 'number'
2708
+ || !('y' in row) || typeof row.y !== 'number'
2709
+ || !('y2' in row) || typeof row.y2 !== 'number') return undefined
2710
+ return row
2711
+ }
2712
+
2698
2713
  const plot = document.createElement('a-plot') as APlotElement
2699
2714
  const data = [
2700
2715
  { x: 8, x2: 38, y: 15, y2: 48, name: 'Window A' },
@@ -2726,8 +2741,8 @@ plot.plotArgs = {
2726
2741
  }),
2727
2742
  ],
2728
2743
  tooltip: ([baseline_hit, current_hit]) => {
2729
- const baseline = baseline_hit?.data.row
2730
- const current = current_hit?.data.row
2744
+ const baseline = windowRow(baseline_hit?.data.row)
2745
+ const current = windowRow(current_hit?.data.row)
2731
2746
  const content = document.createElement('div')
2732
2747
  const title = document.createElement('strong')
2733
2748
  title.textContent = String((current ?? baseline)?.name ?? 'Window comparison')
@@ -2740,7 +2755,10 @@ plot.plotArgs = {
2740
2755
  header.append(cell)
2741
2756
  }
2742
2757
  const body = table.createTBody()
2743
- for (const [field, label] of [['x', 'X start'], ['x2', 'X end'], ['y', 'Y start'], ['y2', 'Y end']]) {
2758
+ const bounds: ['x' | 'x2' | 'y' | 'y2', string][] = [
2759
+ ['x', 'X start'], ['x2', 'X end'], ['y', 'Y start'], ['y2', 'Y end'],
2760
+ ]
2761
+ for (const [field, label] of bounds) {
2744
2762
  const before = baseline?.[field]
2745
2763
  const after = current?.[field]
2746
2764
  const delta = typeof before === 'number' && typeof after === 'number' ? after - before : undefined
@@ -2797,7 +2815,7 @@ const data = Array.from({ length: 24 }, (_, i) => ({
2797
2815
 
2798
2816
  plot.plotArgs = {
2799
2817
  series: [
2800
- scatter<Node>({
2818
+ scatter({
2801
2819
  data, size: 13,
2802
2820
  color: { light: '#0891b2', dark: '#67e8f9' },
2803
2821
  tooltip: true,
@@ -2848,11 +2866,15 @@ the same fields with an optional `row`.
2848
2866
 
2849
2867
  ### Zoom and pan
2850
2868
 
2851
- Zoom continuous axes with the scroll wheel and pan by dragging. The reset control restores the full extent after the view changes. Categorical axes do not zoom. See [Zoom and pan options](#zoom-and-pan-options).
2869
+ Zoom continuous axes with the scroll wheel and pan by dragging. Reset Zoom in the context menu restores the full extent after the view changes. Categorical axes do not zoom. See [Zoom and pan options](#zoom-and-pan-options).
2870
+
2871
+ Zoom and pan in the plot
2852
2872
 
2853
- Zoom with a modifier
2873
+ Scroll to zoom around the pointer, or drag to pan. Plain wheel zoom activates after the pointer settles over the plot; Ctrl-wheel and pinch activate immediately. Horizontal scrolling does not change the viewport. Hold Ctrl and drag inside the plot to draw a zoom rectangle. Releasing fits the viewport to the rectangle, subject to each enabled axis's limits.
2854
2874
 
2855
- Hold Ctrl and scroll to zoom around the pointer, or hold Ctrl and drag to pan. The modifier leaves ordinary scrolling available for navigating the page.
2875
+ Ctrl-wheel and pinch share the same browser signal. Small samples use higher sensitivity, while each sample is capped at a 1.2× change to keep physical mouse-wheel notches manageable. Switching between pinch and ordinary scrolling preserves the existing pointer dwell.
2876
+
2877
+ Right-click for **Reset Zoom**, **Zoom Out**, and **Zoom In**. Menu zoom anchors at the context-click position and applies the same factor to both enabled axes, with independent limits. Set `zoom_pan: { menu_zoom_step: 1.5 }` to change that factor from its default of `2`. Zoom In divides each span by the factor; Zoom Out multiplies it. The value must be finite and greater than 1. It affects only menu actions; wheel and drag sensitivity stay fixed.
2856
2878
 
2857
2879
  ```ts
2858
2880
  import { line, type APlotElement } from '@antadesign/plot/browser'
@@ -2862,7 +2884,7 @@ const plot = document.createElement('a-plot') as APlotElement
2862
2884
  const output = document.createElement('output')
2863
2885
  output.setAttribute('aria-live', 'polite')
2864
2886
  output.style.display = 'block'
2865
- output.textContent = 'Hold Ctrl and scroll to zoom, or Ctrl-drag to pan.'
2887
+ output.textContent = 'Scroll to zoom, drag to pan, or Ctrl-drag to zoom to a rectangle.'
2866
2888
 
2867
2889
  const data = Array.from({ length: 201 }, (_, i) => ({
2868
2890
  x: i / 2,
@@ -2871,20 +2893,20 @@ const data = Array.from({ length: 201 }, (_, i) => ({
2871
2893
 
2872
2894
  plot.plotArgs = {
2873
2895
  series: [
2874
- line<Node>({
2896
+ line({
2875
2897
  data, width: 2,
2876
2898
  color: { light: '#6366f1', dark: '#a5b4fc' },
2877
2899
  tooltip: true,
2878
2900
  }),
2879
2901
  ],
2880
- height: 260,
2902
+ height: 420,
2881
2903
  margin: { top: 8, right: 12, bottom: 24, left: 32 },
2882
2904
  axis: { x: { min: 0, max: 100, label: '' }, y: { min: 0, max: 100, label: '' } },
2883
2905
  background: { light: '#ffffff', dark: '#151b28' },
2884
2906
  chrome_color: { light: '#e2e8f0', dark: '#334155' },
2885
2907
  grid: false,
2886
2908
  border: false,
2887
- zoom_pan: { x: true, y: true, modifier: true },
2909
+ zoom_pan: { x: true, y: true },
2888
2910
  on_viewport_change: ({ x, y }) => {
2889
2911
  const format = (axis: { window: number[] } | null) => axis
2890
2912
  ? axis.window.map(value => value.toFixed(1)).join('–') : 'full extent'
@@ -2895,9 +2917,9 @@ plot.plotArgs = {
2895
2917
  document.body.append(plot, output)
2896
2918
  ```
2897
2919
 
2898
- Zoom without a modifier
2920
+ Navigate an axis
2899
2921
 
2900
- Scroll over the plot to zoom, or drag to pan. Set `modifier: false` when the plot should own these gestures without requiring Ctrl.
2922
+ Scroll over an axis to zoom around the pointer, or drag on the axis to zoom around the value where the drag started. No modifier is needed. Enabled continuous axes show directional arrows on hover. Drag inside the plot to pan. Drag right on x or up on y to zoom in; drag the other way to zoom out. Moving a quarter of the full axis length halves or doubles the starting span, subject to zoom limits. The other axis keeps its viewport.
2901
2923
 
2902
2924
  ```ts
2903
2925
  import { line, type APlotElement } from '@antadesign/plot/browser'
@@ -2907,7 +2929,7 @@ const plot = document.createElement('a-plot') as APlotElement
2907
2929
  const output = document.createElement('output')
2908
2930
  output.setAttribute('aria-live', 'polite')
2909
2931
  output.style.display = 'block'
2910
- output.textContent = 'Scroll to zoom, or drag to pan.'
2932
+ output.textContent = 'Scroll to zoom, drag to pan, or Ctrl-drag to zoom to a rectangle.'
2911
2933
 
2912
2934
  const data = Array.from({ length: 201 }, (_, i) => ({
2913
2935
  x: i / 2,
@@ -2916,7 +2938,7 @@ const data = Array.from({ length: 201 }, (_, i) => ({
2916
2938
 
2917
2939
  plot.plotArgs = {
2918
2940
  series: [
2919
- line<Node>({
2941
+ line({
2920
2942
  data, width: 2,
2921
2943
  color: { light: '#6366f1', dark: '#a5b4fc' },
2922
2944
  tooltip: true,
@@ -2929,7 +2951,7 @@ plot.plotArgs = {
2929
2951
  chrome_color: { light: '#e2e8f0', dark: '#334155' },
2930
2952
  grid: false,
2931
2953
  border: false,
2932
- zoom_pan: { x: true, y: true, modifier: false },
2954
+ zoom_pan: { x: true, y: true },
2933
2955
  on_viewport_change: ({ x, y }) => {
2934
2956
  const format = (axis: { window: number[] } | null) => axis
2935
2957
  ? axis.window.map(value => value.toFixed(1)).join('–') : 'full extent'
@@ -2942,7 +2964,7 @@ document.body.append(plot, output)
2942
2964
 
2943
2965
  Zoom on one axis
2944
2966
 
2945
- Hold Ctrl and scroll or drag. Only the horizontal window changes; the vertical range stays fixed. Set `x: false, y: true` for vertical-only navigation.
2967
+ Scroll to zoom or drag to pan. Only the horizontal window changes; the vertical range stays fixed. Set `x: false, y: true` for vertical-only navigation.
2946
2968
 
2947
2969
  ```ts
2948
2970
  import { line, type APlotElement } from '@antadesign/plot/browser'
@@ -2952,7 +2974,7 @@ const plot = document.createElement('a-plot') as APlotElement
2952
2974
  const output = document.createElement('output')
2953
2975
  output.setAttribute('aria-live', 'polite')
2954
2976
  output.style.display = 'block'
2955
- output.textContent = 'Hold Ctrl and scroll to zoom, or Ctrl-drag to pan.'
2977
+ output.textContent = 'Scroll to zoom, drag to pan, or Ctrl-drag to zoom to a rectangle.'
2956
2978
 
2957
2979
  const data = Array.from({ length: 201 }, (_, i) => ({
2958
2980
  x: i / 2,
@@ -2961,7 +2983,7 @@ const data = Array.from({ length: 201 }, (_, i) => ({
2961
2983
 
2962
2984
  plot.plotArgs = {
2963
2985
  series: [
2964
- line<Node>({
2986
+ line({
2965
2987
  data, width: 2,
2966
2988
  color: { light: '#6366f1', dark: '#a5b4fc' },
2967
2989
  tooltip: true,
@@ -2974,7 +2996,7 @@ plot.plotArgs = {
2974
2996
  chrome_color: { light: '#e2e8f0', dark: '#334155' },
2975
2997
  grid: false,
2976
2998
  border: false,
2977
- zoom_pan: { x: true, y: false, modifier: true },
2999
+ zoom_pan: { x: true, y: false },
2978
3000
  on_viewport_change: ({ x, y }) => {
2979
3001
  const format = (axis: { window: number[] } | null) => axis
2980
3002
  ? axis.window.map(value => value.toFixed(1)).join('–') : 'full extent'
@@ -2993,13 +3015,13 @@ document.body.append(plot, output)
2993
3015
  |---|---|---|---|
2994
3016
  | `x?` | `boolean` | `true` | Enable horizontal zoom and pan on a continuous axis. |
2995
3017
  | `y?` | `boolean` | `true` | Enable vertical zoom and pan on a continuous axis. |
2996
- | `modifier?` | `boolean` | `true` | Require Ctrl for gestures. Set `false` to allow gestures without a modifier. |
3018
+ | `menu_zoom_step?` | `number` | `2` | Multiplicative menu zoom factor. Must be finite and greater than 1; does not affect wheel or drag sensitivity. |
2997
3019
 
2998
3020
  Setting both axes to `false` disables zoom and pan. Categorical axes do not zoom.
2999
3021
 
3000
3022
  ### Controlling the viewport
3001
3023
 
3002
- Use the buttons to focus on a range or restore the full extent. You can still zoom and pan horizontally with Ctrl after a button sets the view.
3024
+ Use the buttons to focus on a range or restore the full extent. You can still zoom and pan horizontally after a button sets the view.
3003
3025
 
3004
3026
  Set `viewport` to control the visible range. Increment its `key` to apply a new request after the user zooms or pans. See [Viewport](#viewport) for initialization and reset behavior.
3005
3027
 
@@ -3014,7 +3036,7 @@ const plot = document.createElement('a-plot') as APlotElement
3014
3036
  const output = document.createElement('output')
3015
3037
  output.setAttribute('aria-live', 'polite')
3016
3038
  output.style.display = 'block'
3017
- output.textContent = 'Hold Ctrl and scroll to zoom, or Ctrl-drag to pan.'
3039
+ output.textContent = 'Scroll to zoom, drag to pan, or Ctrl-drag to zoom to a rectangle.'
3018
3040
 
3019
3041
  const data = Array.from({ length: 201 }, (_, i) => ({
3020
3042
  x: i / 2,
@@ -3023,7 +3045,7 @@ const data = Array.from({ length: 201 }, (_, i) => ({
3023
3045
 
3024
3046
  plot.plotArgs = {
3025
3047
  series: [
3026
- line<Node>({
3048
+ line({
3027
3049
  data, width: 2,
3028
3050
  color: { light: '#6366f1', dark: '#a5b4fc' },
3029
3051
  tooltip: true,
@@ -3036,7 +3058,7 @@ plot.plotArgs = {
3036
3058
  chrome_color: { light: '#e2e8f0', dark: '#334155' },
3037
3059
  grid: false,
3038
3060
  border: false,
3039
- zoom_pan: { x: true, y: false, modifier: true },
3061
+ zoom_pan: { x: true, y: false },
3040
3062
  viewport: { x: [20, 45], y: null, key: 0 },
3041
3063
  on_viewport_change: ({ x, y }) => {
3042
3064
  const format = (axis: { window: number[] } | null) => axis
@@ -3103,9 +3125,9 @@ Scatter `size` accepts a fixed pixel diameter or a pure accessor returning a num
3103
3125
  The accessor receives `(row, index, viewport)`, so you can combine data and viewport
3104
3126
  without storing zoom in application state.
3105
3127
 
3106
- Hold **Ctrl** and scroll near **50**. The first series stays at 4px. The other series
3128
+ Scroll near **50**. The first series stays at 4px. The other series
3107
3129
  alternate between 2px and 4px based on their data, then grow with horizontal zoom,
3108
- at different rates, up to 16px. Hold **Ctrl** and drag to pan; **Reset zoom** restores
3130
+ at different rates, up to 16px. Drag to pan; **Reset Zoom** in the context menu restores
3109
3131
  the starting sizes.
3110
3132
 
3111
3133
  ```ts
@@ -3124,14 +3146,14 @@ export function viewportSizes(): PlotArgs<Node> {
3124
3146
  background: { light: '#ffffff', dark: '#202124' },
3125
3147
  chrome_color: { light: '#64748b', dark: '#cbd5e1' },
3126
3148
  grid: false,
3127
- zoom_pan: { x: true, y: false, modifier: true },
3149
+ zoom_pan: { x: true, y: false },
3128
3150
  series: [
3129
- scatter<Node>({ data: rows(labels[0]), size: 4,
3151
+ scatter({ data: rows(labels[0]), size: 4,
3130
3152
  color: { light: '#64748b', dark: '#cbd5e1' }, tooltip: true }),
3131
- scatter<Node>({ data: rows(labels[1]),
3153
+ scatter({ data: rows(labels[1]),
3132
3154
  size: (row, index, viewport) => Math.min(16, Number(row.weight) * viewport.zoom_factor.x ** 0.25),
3133
3155
  color: { light: '#7c3aed', dark: '#c4b5fd' }, tooltip: true }),
3134
- scatter<Node>({ data: rows(labels[2]),
3156
+ scatter({ data: rows(labels[2]),
3135
3157
  size: (row, index, viewport) => Math.min(16, Number(row.weight) * viewport.zoom_factor.x ** 0.5),
3136
3158
  color: { light: '#c2410c', dark: '#fdba74' }, tooltip: true }),
3137
3159
  ],
@@ -3203,7 +3225,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3203
3225
 
3204
3226
  function base(): PlotArgs<Node> {
3205
3227
  return {
3206
- series: [scatter<Node>({ data: [
3228
+ series: [scatter({ data: [
3207
3229
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3208
3230
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3209
3231
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3255,7 +3277,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3255
3277
 
3256
3278
  function base(): PlotArgs<Node> {
3257
3279
  return {
3258
- series: [scatter<Node>({ data: [
3280
+ series: [scatter({ data: [
3259
3281
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3260
3282
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3261
3283
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3311,7 +3333,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3311
3333
 
3312
3334
  function base(): PlotArgs<Node> {
3313
3335
  return {
3314
- series: [scatter<Node>({ data: [
3336
+ series: [scatter({ data: [
3315
3337
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3316
3338
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3317
3339
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3354,7 +3376,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3354
3376
 
3355
3377
  function base(): PlotArgs<Node> {
3356
3378
  return {
3357
- series: [scatter<Node>({ data: [
3379
+ series: [scatter({ data: [
3358
3380
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3359
3381
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3360
3382
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3407,7 +3429,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3407
3429
 
3408
3430
  function base(): PlotArgs<Node> {
3409
3431
  return {
3410
- series: [scatter<Node>({ data: [
3432
+ series: [scatter({ data: [
3411
3433
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3412
3434
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3413
3435
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3425,7 +3447,7 @@ function base(): PlotArgs<Node> {
3425
3447
  function grid(): PlotArgs<Node> {
3426
3448
  const categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
3427
3449
  return { ...base(), height: 160, margin: { top: 10, right: 10, bottom: 10, left: 10 },
3428
- series: [scatter<Node>({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3450
+ series: [scatter({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3429
3451
  size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
3430
3452
  axis: { x: { categories, label: '', tick_mark: false, tick_label: { format: () => '' } },
3431
3453
  y: { min: 0, max: 100, label: '', tick_mark: false, tick_label: { format: () => '' } } },
@@ -3446,7 +3468,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3446
3468
 
3447
3469
  function base(): PlotArgs<Node> {
3448
3470
  return {
3449
- series: [scatter<Node>({ data: [
3471
+ series: [scatter({ data: [
3450
3472
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3451
3473
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3452
3474
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3464,7 +3486,7 @@ function base(): PlotArgs<Node> {
3464
3486
  function grid(): PlotArgs<Node> {
3465
3487
  const categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
3466
3488
  return { ...base(), height: 160, margin: { top: 10, right: 10, bottom: 10, left: 10 },
3467
- series: [scatter<Node>({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3489
+ series: [scatter({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3468
3490
  size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
3469
3491
  axis: { x: { categories, label: '', tick_mark: false, tick_label: { format: () => '' } },
3470
3492
  y: { min: 0, max: 100, label: '', tick_mark: false, tick_label: { format: () => '' } } },
@@ -3489,7 +3511,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3489
3511
 
3490
3512
  function base(): PlotArgs<Node> {
3491
3513
  return {
3492
- series: [scatter<Node>({ data: [
3514
+ series: [scatter({ data: [
3493
3515
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3494
3516
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3495
3517
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3507,7 +3529,7 @@ function base(): PlotArgs<Node> {
3507
3529
  function grid(): PlotArgs<Node> {
3508
3530
  const categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
3509
3531
  return { ...base(), height: 160, margin: { top: 10, right: 10, bottom: 10, left: 10 },
3510
- series: [scatter<Node>({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3532
+ series: [scatter({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3511
3533
  size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
3512
3534
  axis: { x: { categories, label: '', tick_mark: false, tick_label: { format: () => '' } },
3513
3535
  y: { min: 0, max: 100, label: '', tick_mark: false, tick_label: { format: () => '' } } },
@@ -3532,7 +3554,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3532
3554
 
3533
3555
  function base(): PlotArgs<Node> {
3534
3556
  return {
3535
- series: [scatter<Node>({ data: [
3557
+ series: [scatter({ data: [
3536
3558
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3537
3559
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3538
3560
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3550,7 +3572,7 @@ function base(): PlotArgs<Node> {
3550
3572
  function grid(): PlotArgs<Node> {
3551
3573
  const categories = ['A', 'B', 'C', 'D', 'E', 'F', 'G']
3552
3574
  return { ...base(), height: 160, margin: { top: 10, right: 10, bottom: 10, left: 10 },
3553
- series: [scatter<Node>({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3575
+ series: [scatter({ data: categories.map((x, i) => ({ x, y: 20 + i * 9 })),
3554
3576
  size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
3555
3577
  axis: { x: { categories, label: '', tick_mark: false, tick_label: { format: () => '' } },
3556
3578
  y: { min: 0, max: 100, label: '', tick_mark: false, tick_label: { format: () => '' } } },
@@ -3584,7 +3606,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3584
3606
 
3585
3607
  function base(): PlotArgs<Node> {
3586
3608
  return {
3587
- series: [scatter<Node>({ data: [
3609
+ series: [scatter({ data: [
3588
3610
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3589
3611
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3590
3612
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3600,7 +3622,7 @@ function base(): PlotArgs<Node> {
3600
3622
  }
3601
3623
 
3602
3624
  function themeColors(): PlotArgs<Node> {
3603
- return { ...base(), series: [scatter<Node>({
3625
+ return { ...base(), series: [scatter({
3604
3626
  data: [{ x: 20, y: 30 }, { x: 50, y: 65 }, { x: 80, y: 45 }],
3605
3627
  size: 18, color: { light: 'tomato', dark: 'lightskyblue' }, hoverable: false,
3606
3628
  })] }
@@ -3635,7 +3657,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3635
3657
 
3636
3658
  function base(): PlotArgs<Node> {
3637
3659
  return {
3638
- series: [scatter<Node>({ data: [
3660
+ series: [scatter({ data: [
3639
3661
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3640
3662
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3641
3663
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3652,7 +3674,7 @@ function base(): PlotArgs<Node> {
3652
3674
 
3653
3675
  function scales(): PlotArgs<Node> {
3654
3676
  return { ...base(),
3655
- series: [scatter<Node>({ data: [1, 10, 100, 1000, 10000].map((y, i) => ({ x: 10 + i * 20, y })),
3677
+ series: [scatter({ data: [1, 10, 100, 1000, 10000].map((y, i) => ({ x: 10 + i * 20, y })),
3656
3678
  size: 4, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
3657
3679
  axis: { x: { scale: 'linear', min: 0, max: 100, label: 'Linear' },
3658
3680
  y: { scale: 'log', min: 1, max: 10000, label: 'Logarithmic',
@@ -3675,7 +3697,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3675
3697
 
3676
3698
  function base(): PlotArgs<Node> {
3677
3699
  return {
3678
- series: [scatter<Node>({ data: [
3700
+ series: [scatter({ data: [
3679
3701
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3680
3702
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3681
3703
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3693,7 +3715,7 @@ function base(): PlotArgs<Node> {
3693
3715
  function timeCategory(): PlotArgs<Node> {
3694
3716
  const start = new Date(2026, 0, 12).getTime()
3695
3717
  return { ...base(),
3696
- series: [scatter<Node>({ data: [
3718
+ series: [scatter({ data: [
3697
3719
  { x: start, y: 'Alpha' }, { x: start + 3600000, y: 'Beta' },
3698
3720
  { x: start + 7200000, y: 'Alpha' }, { x: start + 10800000, y: 'Gamma' },
3699
3721
  { x: start + 14400000, y: 'Beta' },
@@ -3737,7 +3759,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3737
3759
 
3738
3760
  function base(): PlotArgs<Node> {
3739
3761
  return {
3740
- series: [scatter<Node>({ data: [
3762
+ series: [scatter({ data: [
3741
3763
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3742
3764
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3743
3765
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3773,7 +3795,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3773
3795
 
3774
3796
  function base(): PlotArgs<Node> {
3775
3797
  return {
3776
- series: [scatter<Node>({ data: [
3798
+ series: [scatter({ data: [
3777
3799
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3778
3800
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3779
3801
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3821,7 +3843,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3821
3843
 
3822
3844
  function base(): PlotArgs<Node> {
3823
3845
  return {
3824
- series: [scatter<Node>({ data: [
3846
+ series: [scatter({ data: [
3825
3847
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3826
3848
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3827
3849
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3866,7 +3888,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3866
3888
 
3867
3889
  function base(): PlotArgs<Node> {
3868
3890
  return {
3869
- series: [scatter<Node>({ data: [
3891
+ series: [scatter({ data: [
3870
3892
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3871
3893
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3872
3894
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3882,7 +3904,7 @@ function base(): PlotArgs<Node> {
3882
3904
  }
3883
3905
 
3884
3906
  function seriesColors(): PlotArgs<Node> {
3885
- return { ...base(), series: [scatter<Node>({
3907
+ return { ...base(), series: [scatter({
3886
3908
  data: [{ x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 }, { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 }],
3887
3909
  size: 8, color: row => Number(row.y) >= 60
3888
3910
  ? { light: '#c2410c', dark: '#fdba74' } : { light: '#64748b', dark: '#94a3b8' },
@@ -3901,12 +3923,12 @@ and custom series accept it; line and area use one `ThemeColor` per series.
3901
3923
  | Form | Type | Description |
3902
3924
  |---|---|---|
3903
3925
  | Shared color | [`ThemeColor`](#theme-colors) | Apply one color or theme pair to the series. |
3904
- | Accessor | [`(row: Record<string, unknown>, index: number) => ThemeColor`](#theme-colors) | Choose a color or theme pair for each row. |
3926
+ | Accessor | [`(row: Row, index: number) => ThemeColor`](#theme-colors) | Choose a color or theme pair for each row. |
3905
3927
 
3906
3928
  ```ts
3907
3929
  import type { ColorArg } from '@antadesign/plot'
3908
3930
 
3909
- const color: ColorArg = (row) => Number(row.value) >= 10 ? 'coral' : 'steelblue'
3931
+ const color: ColorArg<{ value: number }> = (row) => row.value >= 10 ? 'coral' : 'steelblue'
3910
3932
  ```
3911
3933
 
3912
3934
  For these series, a valid `color` on a data row takes precedence over the
@@ -3924,7 +3946,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3924
3946
 
3925
3947
  function base(): PlotArgs<Node> {
3926
3948
  return {
3927
- series: [scatter<Node>({ data: [
3949
+ series: [scatter({ data: [
3928
3950
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3929
3951
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3930
3952
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3941,7 +3963,7 @@ function base(): PlotArgs<Node> {
3941
3963
 
3942
3964
  function markShapes(): PlotArgs<Node> {
3943
3965
  const marks = ['circle', 'square', 'diamond', 'triangle'] as const
3944
- return { ...base(), series: marks.map((mark, i) => scatter<Node>({
3966
+ return { ...base(), series: marks.map((mark, i) => scatter({
3945
3967
  data: [{ x: mark, y: 40 + i * 10 }], mark, size: 12,
3946
3968
  color: [
3947
3969
  { light: '#7c3aed', dark: '#c4b5fd' }, { light: '#db2777', dark: '#f9a8d4' },
@@ -3979,7 +4001,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
3979
4001
 
3980
4002
  function base(): PlotArgs<Node> {
3981
4003
  return {
3982
- series: [scatter<Node>({ data: [
4004
+ series: [scatter({ data: [
3983
4005
  { x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
3984
4006
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 },
3985
4007
  ], size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false })],
@@ -3995,7 +4017,7 @@ function base(): PlotArgs<Node> {
3995
4017
  }
3996
4018
 
3997
4019
  function strokes(): PlotArgs<Node> {
3998
- return { ...base(), series: [1, 3, 5].map((width, i) => scatter<Node>({
4020
+ return { ...base(), series: [1, 3, 5].map((width, i) => scatter({
3999
4021
  data: [{ x: 25 + i * 25, y: 50 }], size: 18,
4000
4022
  color: { light: '#f0abfc', dark: '#c026d3' },
4001
4023
  stroke: { color: { light: '#7e22ce', dark: '#f5d0fe' }, width }, hoverable: false,
@@ -4031,25 +4053,26 @@ such as `x` and `y`, or for a second boundary where the series supports one.
4031
4053
 
4032
4054
  | Form | Type | Description |
4033
4055
  |---|---|---|
4034
- | Field name | `string` | Read the named property from each row. |
4035
- | Accessor | `(row: Record<string, unknown>, index: number) => number \| string` | Compute a value from the row and its zero-based index. Return numbers for continuous axes or strings for categories. |
4056
+ | Field name | `keyof Row & string` | Read the named property from each row. |
4057
+ | Accessor | `(row: Row, index: number) => number \| string` | Compute a value from the row and its zero-based index. Return numbers for continuous axes or strings for categories. |
4036
4058
 
4037
4059
  ```ts
4038
4060
  import type { FieldArg } from '@antadesign/plot'
4039
4061
 
4040
- const x: FieldArg = 'elapsed_ms'
4041
- const y: FieldArg = (row) => Number(row.duration_ms) / 1000
4062
+ type Timing = { elapsed_ms: number; duration_ms: number }
4063
+ const x: FieldArg<Timing> = 'elapsed_ms'
4064
+ const y: FieldArg<Timing> = (row) => row.duration_ms / 1000
4042
4065
  ```
4043
4066
 
4044
4067
  ### Custom rendering
4045
4068
 
4046
- `CustomRendererFn<TooltipContent>` receives the composed custom series and
4069
+ `CustomRendererFn<Row>` receives a `CustomSeriesView<Row>` and
4047
4070
  its drawing context:
4048
4071
 
4049
4072
  ```ts
4050
- import type { ComposedCustom, CustomRenderContext } from '@antadesign/plot'
4073
+ import type { CustomSeriesView, CustomRenderContext } from '@antadesign/plot'
4051
4074
 
4052
- type Renderer = (series: ComposedCustom, context: CustomRenderContext) => void
4075
+ type Renderer<Row> = (series: CustomSeriesView<Row>, context: CustomRenderContext) => void
4053
4076
  ```
4054
4077
 
4055
4078
  The composed series contains resolved `x` and `y` columns, source `rows` when
@@ -4115,7 +4138,7 @@ import type { APlotElement } from '@antadesign/plot/browser'
4115
4138
 
4116
4139
  function stylingExample(): PlotArgs<Node> {
4117
4140
  return {
4118
- series: [scatter<Node>({
4141
+ series: [scatter({
4119
4142
  data: [{ x: 12, y: 18 }, { x: 30, y: 42 }, { x: 48, y: 35 },
4120
4143
  { x: 58, y: 64 }, { x: 76, y: 58 }, { x: 88, y: 82 }],
4121
4144
  size: 3, color: { light: '#9ca3af', dark: '#6b7280' }, hoverable: false,
@@ -4184,5 +4207,4 @@ Set text colors separately with `title.font.color`, `axis.x.label.font.color`,
4184
4207
 
4185
4208
  With the JSX `Plot` component, return content supported by your renderer from a
4186
4209
  series’ [`tooltip`](#tooltips) callback and style it like other markup. Anta’s
4187
- `Tooltip` renders that content in the component tree. The reset control is an Anta `Button` and
4188
- follows the application’s theme.
4210
+ `Tooltip` renders that content in the component tree. The zoom context menu uses Anta `Menu` and follows the application’s theme.