@cfasim-ui/docs 0.4.6 → 0.4.8

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.
@@ -160,6 +160,40 @@ Use `value-tick-format` to format the value-axis labels. `tooltip-value-format`
160
160
  </template>
161
161
  </ComponentDemo>
162
162
 
163
+ ### Logarithmic value axis
164
+
165
+ Set `value-scale-type="log"` to switch the value axis to base-10 log
166
+ scaling. Non-positive values collapse to the axis floor, and
167
+ `valueMin <= 0` is ignored. With `layout="stacked"`, individual segment
168
+ sizes are no longer proportional to their raw values, but the cumulative
169
+ top still represents the sum.
170
+
171
+ <ComponentDemo>
172
+ <BarChart
173
+ :data="[3, 24, 180, 1450, 9800]"
174
+ :categories="['Wk1', 'Wk2', 'Wk3', 'Wk4', 'Wk5']"
175
+ value-scale-type="log"
176
+ :height="220"
177
+ x-label="Week"
178
+ y-label="Cases"
179
+ />
180
+
181
+ <template #code>
182
+
183
+ ```vue
184
+ <BarChart
185
+ :data="[3, 24, 180, 1450, 9800]"
186
+ :categories="['Wk1', 'Wk2', 'Wk3', 'Wk4', 'Wk5']"
187
+ value-scale-type="log"
188
+ :height="220"
189
+ x-label="Week"
190
+ y-label="Cases"
191
+ />
192
+ ```
193
+
194
+ </template>
195
+ </ComponentDemo>
196
+
163
197
  ### Annotations
164
198
 
165
199
  Pin callouts to specific bars with `annotations`. `x` is the category
@@ -286,7 +320,7 @@ anchor. `lineColor`, `lineWidth`, and `lineDash` style the line.
286
320
  | `tooltipData` | `ArrayLike&lt;unknown&gt;` | No | — |
287
321
  | `tooltipTrigger` | `"hover" \| "click"` | No | — |
288
322
  | `tooltipClamp` | `"none" \| "chart" \| "window"` | No | `"chart"` |
289
- | `tooltipValueFormat` | `(value: number) =&gt; string` | No | — |
323
+ | `tooltipValueFormat` | `NumberFormat` | No | — |
290
324
  | `csv` | `string \| (() =&gt; string)` | No | — |
291
325
  | `filename` | `string` | No | — |
292
326
  | `downloadLink` | `boolean \| string` | No | — |
@@ -299,8 +333,9 @@ anchor. `lineColor`, `lineWidth`, and `lineDash` style the line.
299
333
  | `orientation` | `"vertical" \| "horizontal"` | No | `"vertical"` |
300
334
  | `layout` | `"grouped" \| "stacked"` | No | `"grouped"` |
301
335
  | `valueMin` | `number` | No | `0` |
336
+ | `valueScaleType` | `"linear" \| "log"` | No | `"linear"` |
302
337
  | `valueTicks` | `number \| number[]` | No | — |
303
- | `valueTickFormat` | `(value: number) =&gt; string` | No | — |
338
+ | `valueTickFormat` | `NumberFormat` | No | — |
304
339
  | `categoryFormat` | `(label: string, index: number) =&gt; string` | No | — |
305
340
  | `barPadding` | `number` | No | `0.2` |
306
341
  | `groupGap` | `number` | No | `1` |
@@ -1,10 +1,14 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from "vue";
3
+ import { formatNumber, type NumberFormat } from "@cfasim-ui/shared";
3
4
  import ChartMenu from "../ChartMenu/ChartMenu.vue";
4
5
  import {
5
6
  snap,
6
7
  formatTick,
7
8
  computeTickValues,
9
+ computeLogTickValues,
10
+ scaleFraction,
11
+ clampExtentForScale,
8
12
  categoricalToCsv,
9
13
  useChartFoundation,
10
14
  makeTooltipValueFormatter,
@@ -45,13 +49,26 @@ interface BarChartProps extends ChartCommonProps {
45
49
  layout?: "grouped" | "stacked";
46
50
  /** Force the value axis to start at this value or lower (default 0). */
47
51
  valueMin?: number;
52
+ /**
53
+ * Scale type for the value axis. `"linear"` (default) maps values
54
+ * directly to pixels; `"log"` uses a base-10 log mapping. On a log
55
+ * axis, non-positive values collapse to the visible minimum, and
56
+ * `valueMin <= 0` is ignored. Stacked layout + log produces a
57
+ * cumulative axis but individual segment sizes are no longer
58
+ * proportional to their values.
59
+ */
60
+ valueScaleType?: "linear" | "log";
48
61
  /**
49
62
  * Tick placement on the value axis (numeric). Number = interval,
50
63
  * array = explicit values. When omitted, ticks are chosen automatically.
51
64
  */
52
65
  valueTicks?: number | number[];
53
- /** Formatter for value-axis tick labels. */
54
- valueTickFormat?: (value: number) => string;
66
+ /**
67
+ * Formatter for value-axis tick labels. Accepts a preset name, a
68
+ * printf-style format string, or a function. See `formatNumber` in
69
+ * `@cfasim-ui/shared`.
70
+ */
71
+ valueTickFormat?: NumberFormat;
55
72
  /** Formatter for category-axis labels. Receives the resolved category string. */
56
73
  categoryFormat?: (label: string, index: number) => string;
57
74
  /**
@@ -76,6 +93,7 @@ const props = withDefaults(defineProps<BarChartProps>(), {
76
93
  menu: true,
77
94
  tooltipClamp: "chart",
78
95
  valueGrid: true,
96
+ valueScaleType: "linear",
79
97
  });
80
98
 
81
99
  const emit = defineEmits<{
@@ -137,6 +155,10 @@ const isVertical = computed(() => props.orientation === "vertical");
137
155
  const valueExtent = computed(() => {
138
156
  let min = Infinity;
139
157
  let max = -Infinity;
158
+ let smallestPositive = Infinity;
159
+ const visitPositive = (v: number) => {
160
+ if (v > 0 && v < smallestPositive) smallestPositive = v;
161
+ };
140
162
  if (props.layout === "stacked") {
141
163
  const n = categoryCount.value;
142
164
  for (let i = 0; i < n; i++) {
@@ -146,6 +168,7 @@ const valueExtent = computed(() => {
146
168
  if (i >= s.data.length) continue;
147
169
  const v = Number(s.data[i]);
148
170
  if (!isFinite(v)) continue;
171
+ visitPositive(v);
149
172
  if (v >= 0) pos += v;
150
173
  else neg += v;
151
174
  }
@@ -157,6 +180,7 @@ const valueExtent = computed(() => {
157
180
  for (const v of s.data) {
158
181
  const n = Number(v);
159
182
  if (!isFinite(n)) continue;
183
+ visitPositive(n);
160
184
  if (n < min) min = n;
161
185
  if (n > max) max = n;
162
186
  }
@@ -165,11 +189,25 @@ const valueExtent = computed(() => {
165
189
  if (!isFinite(min)) min = 0;
166
190
  if (!isFinite(max)) max = 0;
167
191
  // Extend the value axis down to valueMin (default 0) when data sits
168
- // above it, so bars share a common baseline.
192
+ // above it, so bars share a common baseline. On log scales, only
193
+ // positive valueMin values are honored.
169
194
  const floor = props.valueMin ?? 0;
170
- if (floor < min) min = floor;
171
- const range = max - min || 1;
172
- return { min, max, range };
195
+ if (props.valueScaleType === "log") {
196
+ if (floor > 0 && floor < min) min = floor;
197
+ } else if (floor < min) {
198
+ min = floor;
199
+ }
200
+ const clamped = clampExtentForScale(
201
+ min,
202
+ max,
203
+ props.valueScaleType,
204
+ smallestPositive,
205
+ );
206
+ return {
207
+ min: clamped.min,
208
+ max: clamped.max,
209
+ range: clamped.max - clamped.min || 1,
210
+ };
173
211
  });
174
212
 
175
213
  /** Size (in pixels) of the categorical axis. */
@@ -218,12 +256,12 @@ const groupedBaselinePixel = computed(() => {
218
256
 
219
257
  /** Convert a data value to its pixel position along the value axis. */
220
258
  function valuePixel(v: number): number {
221
- const { min, range } = valueExtent.value;
222
- const scale = valueSize.value / range;
259
+ const { min, max } = valueExtent.value;
260
+ const frac = scaleFraction(v, min, max, props.valueScaleType);
223
261
  if (isVertical.value) {
224
- return padding.value.top + innerH.value - (v - min) * scale;
262
+ return padding.value.top + innerH.value - frac * innerH.value;
225
263
  }
226
- return padding.value.left + (v - min) * scale;
264
+ return padding.value.left + frac * innerW.value;
227
265
  }
228
266
 
229
267
  interface BarRect {
@@ -367,7 +405,9 @@ const formatTooltipValue = makeTooltipValueFormatter(
367
405
  const valueTickItems = computed(() => {
368
406
  const { min, max } = valueExtent.value;
369
407
  const fmt = (v: number) =>
370
- props.valueTickFormat ? props.valueTickFormat(v) : formatTick(v);
408
+ props.valueTickFormat !== undefined
409
+ ? formatNumber(v, props.valueTickFormat)
410
+ : formatTick(v);
371
411
  if (min === max) {
372
412
  return [
373
413
  {
@@ -377,12 +417,15 @@ const valueTickItems = computed(() => {
377
417
  ];
378
418
  }
379
419
  const targetTickPixels = isVertical.value ? 50 : 80;
380
- const values = computeTickValues({
381
- min,
382
- max,
383
- ticks: props.valueTicks,
384
- targetTickCount: valueSize.value / targetTickPixels,
385
- });
420
+ const values =
421
+ props.valueScaleType === "log"
422
+ ? computeLogTickValues({ min, max, ticks: props.valueTicks })
423
+ : computeTickValues({
424
+ min,
425
+ max,
426
+ ticks: props.valueTicks,
427
+ targetTickCount: valueSize.value / targetTickPixels,
428
+ });
386
429
  return values.map((v) => ({
387
430
  value: fmt(v),
388
431
  pos: snap(valuePixel(v)),
@@ -7,16 +7,81 @@ export function downloadBlob(blob: Blob, name: string) {
7
7
  URL.revokeObjectURL(url);
8
8
  }
9
9
 
10
- export function saveSvg(svg: SVGSVGElement, filename: string) {
10
+ /** Inherited CSS properties propagated onto the cloned SVG root so text and
11
+ * `currentColor` strokes render with the same color/typography as the
12
+ * live chart when the SVG is opened standalone or rasterized to PNG. */
13
+ const ROOT_INHERITED_PROPS = [
14
+ "color",
15
+ "font-family",
16
+ "font-size",
17
+ "font-weight",
18
+ ] as const;
19
+
20
+ /** Presentation attributes that may contain `var(--…)` references. The
21
+ * fallback inside `var(--name, #fff)` is the only thing that renders when
22
+ * the custom property is undefined outside the page context — so we
23
+ * resolve them against the document's CSS custom properties before
24
+ * serializing. */
25
+ const VAR_RESOLVABLE_ATTRS = ["fill", "stroke"] as const;
26
+
27
+ /** Resolve a single `var(--name)` or `var(--name, fallback)` expression.
28
+ * Looks the name up on `document.documentElement` (where theme tokens are
29
+ * declared); falls back to the in-expression fallback, then the original
30
+ * expression if neither resolves. */
31
+ function resolveVarExpression(expr: string): string {
32
+ const match = expr.match(
33
+ /^\s*var\(\s*(--[\w-]+)\s*(?:,\s*([^)]*?)\s*)?\)\s*$/,
34
+ );
35
+ if (!match) return expr;
36
+ const [, name, fallback] = match;
37
+ const value = window
38
+ .getComputedStyle(document.documentElement)
39
+ .getPropertyValue(name)
40
+ .trim();
41
+ if (value) return value;
42
+ if (fallback) return fallback.trim();
43
+ return expr;
44
+ }
45
+
46
+ /** Clone `svg` and inline the styles that don't survive a standalone render:
47
+ * inherited `color`/`font-*` on the root (so `currentColor` and unset
48
+ * font-family resolve), and any `var(--…)` references in fill/stroke
49
+ * attributes resolved against the document. */
50
+ export function prepareSvgForExport(svg: SVGSVGElement): SVGSVGElement {
11
51
  const clone = svg.cloneNode(true) as SVGSVGElement;
12
52
  clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
53
+
54
+ const rootComputed = window.getComputedStyle(svg);
55
+ const rootStyleParts: string[] = [];
56
+ for (const prop of ROOT_INHERITED_PROPS) {
57
+ const value = rootComputed.getPropertyValue(prop);
58
+ if (value) rootStyleParts.push(`${prop}: ${value}`);
59
+ }
60
+ const existingRootStyle = clone.getAttribute("style") ?? "";
61
+ clone.setAttribute(
62
+ "style",
63
+ [existingRootStyle, ...rootStyleParts].filter(Boolean).join("; "),
64
+ );
65
+
66
+ for (const target of clone.querySelectorAll<SVGElement>("*")) {
67
+ for (const attr of VAR_RESOLVABLE_ATTRS) {
68
+ const raw = target.getAttribute(attr);
69
+ if (!raw || !raw.includes("var(")) continue;
70
+ target.setAttribute(attr, resolveVarExpression(raw));
71
+ }
72
+ }
73
+
74
+ return clone;
75
+ }
76
+
77
+ export function saveSvg(svg: SVGSVGElement, filename: string) {
78
+ const clone = prepareSvgForExport(svg);
13
79
  const xml = new XMLSerializer().serializeToString(clone);
14
80
  downloadBlob(new Blob([xml], { type: "image/svg+xml" }), `${filename}.svg`);
15
81
  }
16
82
 
17
83
  export function savePng(svg: SVGSVGElement, filename: string) {
18
- const clone = svg.cloneNode(true) as SVGSVGElement;
19
- clone.setAttribute("xmlns", "http://www.w3.org/2000/svg");
84
+ const clone = prepareSvgForExport(svg);
20
85
  const xml = new XMLSerializer().serializeToString(clone);
21
86
  const svgBlob = new Blob([xml], { type: "image/svg+xml;charset=utf-8" });
22
87
  const url = URL.createObjectURL(svgBlob);
@@ -704,7 +704,7 @@ set `tooltip-trigger`.
704
704
  id: string` | No | — |
705
705
  | `name` | `string` | Yes | — |
706
706
  | `value` | `number \| string` | No | — |
707
- | `tooltipValueFormat` | `(value: number) =&gt; string` | No | — |
707
+ | `tooltipValueFormat` | `NumberFormat` | No | — |
708
708
  | `tooltipClamp` | `"none" \| "chart" \| "window"` | No | `"chart"` |
709
709
  | `focus` | `FocusValue` | No | — |
710
710
  | `focusZoomLevel` | `number` | No | `4` |
@@ -16,6 +16,7 @@ import { select } from "d3-selection";
16
16
  import "d3-transition";
17
17
  import { feature, mesh, merge } from "topojson-client";
18
18
  import type { Topology, GeometryCollection } from "topojson-specification";
19
+ import { formatNumber, type NumberFormat } from "@cfasim-ui/shared";
19
20
  import { fipsToHsa, hsaNames } from "./hsaMapping.js";
20
21
  import ChartMenu from "../ChartMenu/ChartMenu.vue";
21
22
  import type { ChartMenuItem } from "../ChartMenu/ChartMenu.vue";
@@ -129,11 +130,12 @@ const props = withDefaults(
129
130
  value?: number | string;
130
131
  }) => string;
131
132
  /**
132
- * Formatter for numeric values shown in the default tooltip. Receives
133
- * the raw value. Ignored when `tooltipFormat` is provided (the caller
134
- * controls the entire tooltip in that case).
133
+ * Formatter for numeric values shown in the default tooltip. Accepts a
134
+ * preset name, a printf-style format string, or a function. Ignored when
135
+ * `tooltipFormat` is provided (the caller controls the entire tooltip in
136
+ * that case). See `formatNumber` in `@cfasim-ui/shared`.
135
137
  */
136
- tooltipValueFormat?: (value: number) => string;
138
+ tooltipValueFormat?: NumberFormat;
137
139
  /**
138
140
  * Boundary for tooltip flip/clamp. `"none"` always places to the right of
139
141
  * the pointer with no clamping. `"chart"` (default) uses the map
@@ -889,8 +891,8 @@ const featureName = (
889
891
 
890
892
  function formatTooltipValue(value: number | string | undefined): string {
891
893
  if (value == null) return "";
892
- if (typeof value === "number" && props.tooltipValueFormat) {
893
- return props.tooltipValueFormat(value);
894
+ if (typeof value === "number" && props.tooltipValueFormat !== undefined) {
895
+ return formatNumber(value, props.tooltipValueFormat);
894
896
  }
895
897
  return String(value);
896
898
  }
@@ -56,6 +56,43 @@ A table for displaying columnar data. Accepts a plain record of arrays or a `Mod
56
56
  </template>
57
57
  </ComponentDemo>
58
58
 
59
+ ### Formatting cell values
60
+
61
+ Use `format` on a column to override the default rendering. Accepts a
62
+ {@link NumberFormat} value — a preset name (optionally with `:N` digits,
63
+ e.g. `"percent:1"`), a printf-style format string, or a function
64
+ `(value, row) => string`. Formatted values are also used in CSV exports.
65
+
66
+ <ComponentDemo>
67
+ <DataTable
68
+ :data="{ day: [0, 1, 2, 3, 4], rate: [0.012, 0.234, 0.467, 0.512, 0.601], cases: [1, 21, 56, 101, 141] }"
69
+ :column-config="{
70
+ day: { label: 'Day', width: 'small' },
71
+ rate: { label: 'Attack rate', format: 'percent:1' },
72
+ cases: { label: 'Cases', format: '%05d' },
73
+ }"
74
+ />
75
+
76
+ <template #code>
77
+
78
+ ```vue
79
+ <DataTable
80
+ :data="{
81
+ day: [0, 1, 2, 3, 4],
82
+ rate: [0.012, 0.234, 0.467, 0.512, 0.601],
83
+ cases: [1, 21, 56, 101, 141],
84
+ }"
85
+ :column-config="{
86
+ day: { label: 'Day', width: 'small' },
87
+ rate: { label: 'Attack rate', format: 'percent:1' },
88
+ cases: { label: 'Cases', format: '%05d' },
89
+ }"
90
+ />
91
+ ```
92
+
93
+ </template>
94
+ </ComponentDemo>
95
+
59
96
  ### Cell class and max rows
60
97
 
61
98
  <ComponentDemo>
@@ -169,5 +206,16 @@ interface ColumnConfig {
169
206
  width?: "small" | "medium" | "large" | number;
170
207
  align?: "left" | "center" | "right";
171
208
  cellClass?: string;
209
+ format?: NumberFormat | ((value: CellValue, row: number) => string);
172
210
  }
211
+
212
+ type CellValue = number | string | boolean;
213
+
214
+ type NumberFormat =
215
+ | NumberFormatPreset // "plain" | "localized" | "percent" | "compact" | "scientific" | "engineering" (optionally with ":N" digits, e.g. "percent:1")
216
+ | string // printf-style format, e.g. "%.2f", "%05d"
217
+ | ((value: number) => string);
173
218
  ```
219
+
220
+ See `formatNumber` in `@cfasim-ui/shared` for the underlying utility — you
221
+ can also call it directly in your own code.
@@ -1,7 +1,11 @@
1
1
  <script setup lang="ts">
2
2
  import { computed } from "vue";
3
3
  import type { CSSProperties } from "vue";
4
- import type { ModelOutput } from "@cfasim-ui/shared";
4
+ import {
5
+ formatNumber,
6
+ type ModelOutput,
7
+ type NumberFormat,
8
+ } from "@cfasim-ui/shared";
5
9
  import ChartMenu from "../ChartMenu/ChartMenu.vue";
6
10
  import type { ChartMenuItem } from "../ChartMenu/ChartMenu.vue";
7
11
  import { downloadCsv } from "../ChartMenu/download.js";
@@ -10,12 +14,23 @@ export type TableRecord = Record<string, ArrayLike<number | string | boolean>>;
10
14
  export type TableData = TableRecord | ModelOutput;
11
15
  export type ColumnWidth = "small" | "medium" | "large";
12
16
  export type ColumnAlign = "left" | "center" | "right";
17
+ export type CellValue = number | string | boolean;
18
+ export type ColumnFormatter = (value: CellValue, row: number) => string;
13
19
 
14
20
  export interface ColumnConfig {
15
21
  label?: string;
16
22
  width?: ColumnWidth | number;
17
23
  align?: ColumnAlign;
18
24
  cellClass?: string;
25
+ /**
26
+ * Custom formatter for cell values in this column. Accepts a
27
+ * {@link NumberFormat} (preset name, printf-style string, or
28
+ * `(value) => string` function — see `formatNumber` in
29
+ * `@cfasim-ui/shared`) or a `(value, row) => string` function for full
30
+ * control. Number presets/sprintf only apply to numeric cells; other
31
+ * types fall back to default rendering. Used in CSV exports.
32
+ */
33
+ format?: NumberFormat | ColumnFormatter;
19
34
  }
20
35
 
21
36
  const COLUMN_WIDTHS: Record<ColumnWidth, string> = {
@@ -102,6 +117,18 @@ const rowCount = computed(() => {
102
117
  function cellValue(col: Column, row: number): string {
103
118
  const v = col.values[row];
104
119
  if (v === undefined || v === null) return "";
120
+ const format = props.columnConfig?.[col.name]?.format;
121
+ if (format !== undefined) {
122
+ // Function variant — either `(value: number) => string` (NumberFormat
123
+ // function) or `(value, row) => string` (ColumnFormatter). Both call
124
+ // sites are compatible; the narrower variant ignores `row`.
125
+ if (typeof format === "function") {
126
+ return (format as ColumnFormatter)(v, row);
127
+ }
128
+ // String preset/sprintf — only applies to numeric cells; other types
129
+ // fall through to default rendering.
130
+ if (typeof v === "number") return formatNumber(v, format);
131
+ }
105
132
  if (col.enumLabels && typeof v === "number")
106
133
  return col.enumLabels[v] ?? String(v);
107
134
  if (typeof v === "number") {
@@ -180,6 +180,39 @@ Control tick placement with `x-ticks` and `y-ticks`. Pass a **number** for a fix
180
180
  </template>
181
181
  </ComponentDemo>
182
182
 
183
+ ### Logarithmic y-axis
184
+
185
+ Set `y-scale-type="log"` to switch the y axis to base-10 log scaling. Useful
186
+ when data spans several orders of magnitude (e.g. epidemic case counts in
187
+ early exponential growth). Non-positive values collapse to the axis
188
+ floor, and `yMin <= 0` is ignored.
189
+
190
+ <ComponentDemo>
191
+ <LineChart
192
+ :data="[1, 3, 8, 22, 60, 165, 450, 1230, 3350]"
193
+ y-scale-type="log"
194
+ :height="220"
195
+ x-label="Day"
196
+ y-label="Cases"
197
+ y-grid
198
+ />
199
+
200
+ <template #code>
201
+
202
+ ```vue
203
+ <LineChart
204
+ :data="[1, 3, 8, 22, 60, 165, 450, 1230, 3350]"
205
+ y-scale-type="log"
206
+ :height="220"
207
+ x-label="Day"
208
+ y-label="Cases"
209
+ y-grid
210
+ />
211
+ ```
212
+
213
+ </template>
214
+ </ComponentDemo>
215
+
183
216
  ### Dashed baseline
184
217
 
185
218
  <ComponentDemo>
@@ -647,7 +680,7 @@ until the user clicks Download:
647
680
  | `tooltipData` | `ArrayLike&lt;unknown&gt;` | No | — |
648
681
  | `tooltipTrigger` | `"hover" \| "click"` | No | — |
649
682
  | `tooltipClamp` | `"none" \| "chart" \| "window"` | No | `"chart"` |
650
- | `tooltipValueFormat` | `(value: number) =&gt; string` | No | — |
683
+ | `tooltipValueFormat` | `NumberFormat` | No | — |
651
684
  | `csv` | `string \| (() =&gt; string)` | No | — |
652
685
  | `filename` | `string` | No | — |
653
686
  | `downloadLink` | `boolean \| string` | No | — |
@@ -661,11 +694,12 @@ until the user clicks Download:
661
694
  | `areaSections` | `AreaSection[]` | No | — |
662
695
  | `lineOpacity` | `number` | No | `1` |
663
696
  | `yMin` | `number` | No | — |
697
+ | `yScaleType` | `"linear" \| "log"` | No | `"linear"` |
664
698
  | `xMin` | `number` | No | — |
665
699
  | `xTicks` | `number \| number[]` | No | — |
666
700
  | `yTicks` | `number \| number[]` | No | — |
667
- | `xTickFormat` | `(value: number, index: number) =&gt; string` | No | — |
668
- | `yTickFormat` | `(value: number) =&gt; string` | No | — |
701
+ | `xTickFormat` | `NumberFormat \| ((value: number, index: number) =&gt; string)` | No | — |
702
+ | `yTickFormat` | `NumberFormat` | No | — |
669
703
  | `xLabels` | `string[]` | No | — |
670
704
  | `xGrid` | `boolean` | No | — |
671
705
  | `yGrid` | `boolean` | No | — |