@pushwoosh/kit-charts 0.0.1 → 0.0.3

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.
@@ -103,6 +103,25 @@ takes `value`; on a category axis both address a category by name and a band
103
103
  covers the whole slot. Both accept a `label`, and a `zIndex` of 5 or more draws
104
104
  them over the series instead of under it — the value Highcharts users reach for.
105
105
 
106
+ A label's `align` is horizontal and its `verticalAlign` vertical whichever way
107
+ the decoration runs, as in Highcharts: a line on a y axis takes its label to the
108
+ left edge of the plot (`align: 'left'`, the default there) and sits it on the
109
+ rule (`verticalAlign: 'middle'`). `x`/`y` shift it from there — a negative `x`
110
+ hangs it in the axis gutter.
111
+
112
+ `label.backgroundColor` draws the label on a pill instead of leaving it as loose
113
+ text, with `borderRadius` and `padding` to tune it. The text takes whichever of
114
+ white and `BRAND_BLACK` reads better on that fill — the greys a threshold is
115
+ painted in carry white at under 3:1 — and `style.color` overrides the choice.
116
+ That is what a threshold needs: a number sitting on a rule has no
117
+ ground of its own to read against. Highcharts has no such option — it takes
118
+ `useHTML` and a styled span, which this library has no equivalent of — so this is
119
+ an addition rather than a divergence: a Highcharts config still renders.
120
+
121
+ Whether a threshold is breached is the application's decision, not the chart's:
122
+ it passes the colour. Golden cases `area/threshold` and `area/threshold-breached`
123
+ are the same options with one colour changed.
124
+
106
125
  ## Interaction
107
126
 
108
127
  `onPointClick(point, event)` reports the point nearest a click inside the plot,
@@ -4,10 +4,10 @@ import { DEFAULT_FONT_SIZE, measureText } from '../layout/measure-text';
4
4
  import { AXIS_LABEL_GAP, AXIS_TITLE_GAP, crisp, TEXT_BASELINE_SHIFT, X_AXIS_LABEL_DROP, X_AXIS_TITLE_GAP } from '../layout/metrics';
5
5
  import { DEFAULT_AXIS_COLOR, DEFAULT_GRID_COLOR, DEFAULT_MUTED_TEXT_COLOR } from '../model/palette';
6
6
  const textProps = style => ({
7
- fill: (style === null || style === void 0 ? void 0 : style.color) ?? DEFAULT_MUTED_TEXT_COLOR,
8
- fontFamily: style === null || style === void 0 ? void 0 : style.fontFamily,
9
- fontSize: (style === null || style === void 0 ? void 0 : style.fontSize) ?? DEFAULT_FONT_SIZE,
10
- fontWeight: style === null || style === void 0 ? void 0 : style.fontWeight
7
+ fill: style?.color ?? DEFAULT_MUTED_TEXT_COLOR,
8
+ fontFamily: style?.fontFamily,
9
+ fontSize: style?.fontSize ?? DEFAULT_FONT_SIZE,
10
+ fontWeight: style?.fontWeight
11
11
  });
12
12
  const ANCHOR = {
13
13
  left: 'start',
@@ -71,8 +71,7 @@ function AxisTitle({
71
71
  anchor,
72
72
  defaultRotation
73
73
  }) {
74
- var _title$style;
75
- if (!(title !== null && title !== void 0 && title.text) || ((_title$style = title.style) === null || _title$style === void 0 ? void 0 : _title$style.display) === 'none') {
74
+ if (!title?.text || title.style?.display === 'none') {
76
75
  return null;
77
76
  }
78
77
  const rotation = title.rotation ?? defaultRotation;
@@ -90,8 +89,7 @@ function AxisTitle({
90
89
  });
91
90
  }
92
91
  const titleY = (options, plot) => {
93
- var _options$title;
94
- const align = ((_options$title = options.title) === null || _options$title === void 0 ? void 0 : _options$title.align) ?? 'middle';
92
+ const align = options.title?.align ?? 'middle';
95
93
  if (align === 'high') {
96
94
  return plot.y;
97
95
  }
@@ -104,7 +102,6 @@ export function XAxis({
104
102
  plot,
105
103
  axis
106
104
  }) {
107
- var _options$labels, _options$labels2, _options$title2;
108
105
  const {
109
106
  options
110
107
  } = axis;
@@ -118,8 +115,8 @@ export function XAxis({
118
115
  const lineColor = options.lineColor ?? DEFAULT_AXIS_COLOR;
119
116
  const tickLength = options.tickLength ?? 0;
120
117
  const tickWidth = options.tickWidth ?? 1;
121
- const labelsEnabled = ((_options$labels = options.labels) === null || _options$labels === void 0 ? void 0 : _options$labels.enabled) !== false;
122
- const labelY = baseline + direction * (tickLength + (onTop ? AXIS_LABEL_GAP : X_AXIS_LABEL_DROP)) + (((_options$labels2 = options.labels) === null || _options$labels2 === void 0 ? void 0 : _options$labels2.y) ?? 0);
118
+ const labelsEnabled = options.labels?.enabled !== false;
119
+ const labelY = baseline + direction * (tickLength + (onTop ? AXIS_LABEL_GAP : X_AXIS_LABEL_DROP)) + (options.labels?.y ?? 0);
123
120
  return _jsxs("g", {
124
121
  children: [options.lineWidth === 0 ? null : _jsx("line", {
125
122
  x1: plot.x,
@@ -128,29 +125,26 @@ export function XAxis({
128
125
  y2: crisp(baseline, options.lineWidth ?? 1),
129
126
  stroke: lineColor,
130
127
  strokeWidth: options.lineWidth ?? 1
131
- }), axis.ticks.map(tick => {
132
- var _options$labels3, _options$labels4;
133
- return _jsxs("g", {
134
- children: [tickLength > 0 && tickWidth > 0 ? _jsx("line", {
135
- x1: crisp(tick.position, tickWidth),
136
- x2: crisp(tick.position, tickWidth),
137
- y1: crisp(baseline, tickWidth),
138
- y2: crisp(baseline + direction * tickLength, tickWidth),
139
- stroke: options.tickColor ?? lineColor,
140
- strokeWidth: tickWidth
141
- }) : null, labelsEnabled && tick.label ? _jsx(TickLabel, {
142
- hint: tick.hint,
143
- x: tick.position + (((_options$labels3 = options.labels) === null || _options$labels3 === void 0 ? void 0 : _options$labels3.x) ?? 0),
144
- y: labelY,
145
- anchor: tick.anchor,
146
- style: (_options$labels4 = options.labels) === null || _options$labels4 === void 0 ? void 0 : _options$labels4.style,
147
- children: tick.label
148
- }) : null]
149
- }, `x-${tick.value}`);
150
- }), _jsx(AxisTitle, {
128
+ }), axis.ticks.map(tick => _jsxs("g", {
129
+ children: [tickLength > 0 && tickWidth > 0 ? _jsx("line", {
130
+ x1: crisp(tick.position, tickWidth),
131
+ x2: crisp(tick.position, tickWidth),
132
+ y1: crisp(baseline, tickWidth),
133
+ y2: crisp(baseline + direction * tickLength, tickWidth),
134
+ stroke: options.tickColor ?? lineColor,
135
+ strokeWidth: tickWidth
136
+ }) : null, labelsEnabled && tick.label ? _jsx(TickLabel, {
137
+ hint: tick.hint,
138
+ x: tick.position + (options.labels?.x ?? 0),
139
+ y: labelY,
140
+ anchor: tick.anchor,
141
+ style: options.labels?.style,
142
+ children: tick.label
143
+ }) : null]
144
+ }, `x-${tick.value}`)), _jsx(AxisTitle, {
151
145
  title: options.title,
152
146
  x: plot.x + plot.width / 2,
153
- y: labelY + direction * ((((_options$title2 = options.title) === null || _options$title2 === void 0 ? void 0 : _options$title2.offset) ?? 0) + X_AXIS_TITLE_GAP),
147
+ y: labelY + direction * ((options.title?.offset ?? 0) + X_AXIS_TITLE_GAP),
154
148
  anchor: "middle",
155
149
  defaultRotation: 0
156
150
  })]
@@ -160,40 +154,33 @@ export function YAxis({
160
154
  plot,
161
155
  axis
162
156
  }) {
163
- var _options$labels5, _options$labels6, _options$title3, _options$title4;
164
157
  const {
165
158
  options
166
159
  } = axis;
167
160
  if (options.visible === false) {
168
161
  return null;
169
162
  }
170
- const labelsEnabled = ((_options$labels5 = options.labels) === null || _options$labels5 === void 0 ? void 0 : _options$labels5.enabled) !== false;
163
+ const labelsEnabled = options.labels?.enabled !== false;
171
164
  const onRight = options.opposite === true;
172
165
  const offset = options.offset ?? 0;
173
166
  // `offset` pushes the whole axis — labels and title — away from the plot.
174
167
  const edge = onRight ? plot.x + plot.width + AXIS_LABEL_GAP + offset : plot.x - AXIS_LABEL_GAP - offset;
175
- const anchor = (((_options$labels6 = options.labels) === null || _options$labels6 === void 0 ? void 0 : _options$labels6.align) && ANCHOR[options.labels.align]) ?? (onRight ? 'start' : 'end');
176
- const columnWidth = labelsEnabled ? axis.ticks.reduce((widest, tick) => {
177
- var _options$labels7;
178
- return Math.max(widest, measureText(tick.label, (_options$labels7 = options.labels) === null || _options$labels7 === void 0 ? void 0 : _options$labels7.style));
179
- }, 0) : 0;
168
+ const anchor = (options.labels?.align && ANCHOR[options.labels.align]) ?? (onRight ? 'start' : 'end');
169
+ const columnWidth = labelsEnabled ? axis.ticks.reduce((widest, tick) => Math.max(widest, measureText(tick.label, options.labels?.style)), 0) : 0;
180
170
  // Where the labels grow away from the plot, the title has to clear the whole
181
171
  // column of them or it lands on top of the numbers.
182
172
  const outwards = onRight ? anchor !== 'end' : anchor !== 'start';
183
173
  const titleShift = outwards ? Math.ceil(columnWidth * (anchor === 'middle' ? 0.5 : 1)) + AXIS_TITLE_GAP : 0;
184
- const titleX = onRight ? edge + titleShift + (((_options$title3 = options.title) === null || _options$title3 === void 0 ? void 0 : _options$title3.offset) ?? 0) : edge - titleShift - (((_options$title4 = options.title) === null || _options$title4 === void 0 ? void 0 : _options$title4.offset) ?? 0);
174
+ const titleX = onRight ? edge + titleShift + (options.title?.offset ?? 0) : edge - titleShift - (options.title?.offset ?? 0);
185
175
  return _jsxs("g", {
186
- children: [labelsEnabled ? axis.ticks.map(tick => {
187
- var _options$labels8, _options$labels9;
188
- return tick.label ? _jsx(TickLabel, {
189
- x: edge + (((_options$labels8 = options.labels) === null || _options$labels8 === void 0 ? void 0 : _options$labels8.x) ?? 0),
190
- y: tick.position + TEXT_BASELINE_SHIFT,
191
- anchor: anchor,
192
- hint: tick.hint,
193
- style: (_options$labels9 = options.labels) === null || _options$labels9 === void 0 ? void 0 : _options$labels9.style,
194
- children: tick.label
195
- }, `y-${tick.value}`) : null;
196
- }) : null, _jsx(AxisTitle, {
176
+ children: [labelsEnabled ? axis.ticks.map(tick => tick.label ? _jsx(TickLabel, {
177
+ x: edge + (options.labels?.x ?? 0),
178
+ y: tick.position + TEXT_BASELINE_SHIFT,
179
+ anchor: anchor,
180
+ hint: tick.hint,
181
+ style: options.labels?.style,
182
+ children: tick.label
183
+ }, `y-${tick.value}`) : null) : null, _jsx(AxisTitle, {
197
184
  title: options.title,
198
185
  x: titleX,
199
186
  y: titleY(options, plot),
@@ -118,7 +118,6 @@ function ChartBody({
118
118
  onSeriesToggle,
119
119
  onPointClick
120
120
  }) {
121
- var _options$chart, _options$chart2, _options$tooltip4, _options$tooltip7, _options$tooltip8, _options$title2, _options$tooltip1, _options$tooltip10, _options$chart3, _options$chart4, _options$chart5, _options$chart6, _options$chart7, _options$chart8, _options$chart9, _options$title3, _options$chart0, _options$chart1, _options$chart10;
122
121
  const [container, size] = useSize();
123
122
  const [hover, setHover] = useState(null);
124
123
  const [zoom, setZoom] = useState(null);
@@ -143,17 +142,17 @@ function ChartBody({
143
142
  } else {
144
143
  next.add(key);
145
144
  }
146
- onSeriesToggle === null || onSeriesToggle === void 0 || onSeriesToggle(item.seriesIndex, !next.has(key), item.pointIndex);
145
+ onSeriesToggle?.(item.seriesIndex, !next.has(key), item.pointIndex);
147
146
  return next;
148
147
  });
149
148
  }, [onSeriesToggle]);
150
149
  const registry = useMemo(() => resolveRenderers(renderers), [renderers]);
151
150
  // A scrollable plot area draws at its minimum size and scrolls inside the box.
152
- const scrollable = (_options$chart = options.chart) === null || _options$chart === void 0 ? void 0 : _options$chart.scrollablePlotArea;
151
+ const scrollable = options.chart?.scrollablePlotArea;
153
152
  const canvas = useMemo(() => ({
154
- width: Math.max(size.width, (scrollable === null || scrollable === void 0 ? void 0 : scrollable.minWidth) ?? 0),
155
- height: Math.max(size.height, (scrollable === null || scrollable === void 0 ? void 0 : scrollable.minHeight) ?? 0)
156
- }), [size, scrollable === null || scrollable === void 0 ? void 0 : scrollable.minWidth, scrollable === null || scrollable === void 0 ? void 0 : scrollable.minHeight]);
153
+ width: Math.max(size.width, scrollable?.minWidth ?? 0),
154
+ height: Math.max(size.height, scrollable?.minHeight ?? 0)
155
+ }), [size, scrollable?.minWidth, scrollable?.minHeight]);
157
156
  // A zoom is an override on the first x axis, not a second source of truth: the
158
157
  // model is still built from the options, so everything downstream is unaware.
159
158
  const zoomed = useMemo(() => {
@@ -177,7 +176,7 @@ function ChartBody({
177
176
  renderers: registry,
178
177
  hidden
179
178
  }) : null, [zoomed, canvas, registry, hidden]);
180
- const anyShown = (built === null || built === void 0 ? void 0 : built.series.some(series => !series.hidden)) ?? false;
179
+ const anyShown = built?.series.some(series => !series.hidden) ?? false;
181
180
  const lastShown = useRef(null);
182
181
  useEffect(() => {
183
182
  if (built && anyShown) {
@@ -213,7 +212,7 @@ function ChartBody({
213
212
  if (!yModel || yModel.scale.kind === 'color') {
214
213
  return null;
215
214
  }
216
- const hit = hover === null || hover === void 0 ? void 0 : hover.hits.find(candidate => candidate.seriesIndex === series.index);
215
+ const hit = hover?.hits.find(candidate => candidate.seriesIndex === series.index);
217
216
  return {
218
217
  series: series.options,
219
218
  seriesIndex: series.index,
@@ -260,8 +259,7 @@ function ChartBody({
260
259
  };
261
260
  }, [model, contextFor]);
262
261
  const handlePointerMove = useCallback(event => {
263
- var _options$tooltip, _options$tooltip2;
264
- if (!model || ((_options$tooltip = options.tooltip) === null || _options$tooltip === void 0 ? void 0 : _options$tooltip.enabled) === false) {
262
+ if (!model || options.tooltip?.enabled === false) {
265
263
  return;
266
264
  }
267
265
  // While a zoom is being dragged out, a tooltip is in the way of the thing
@@ -282,7 +280,7 @@ function ChartBody({
282
280
  setHover(null);
283
281
  return;
284
282
  }
285
- const shared = ((_options$tooltip2 = options.tooltip) === null || _options$tooltip2 === void 0 ? void 0 : _options$tooltip2.shared) ?? false;
283
+ const shared = options.tooltip?.shared ?? false;
286
284
  const nearest = hits.reduce((best, hit) => hit.distance < best.distance ? hit : best);
287
285
  const selected = shared ? hits.filter(hit => String(hit.x) === String(nearest.x)) : [nearest];
288
286
  const highest = selected.reduce((best, hit) => hit.anchor.y < best.anchor.y ? hit : best, selected[0]);
@@ -299,7 +297,7 @@ function ChartBody({
299
297
  });
300
298
  }, [model, hitsAt, options.tooltip, drag]);
301
299
  const handlePointerLeave = useCallback(() => setHover(null), []);
302
- const zooms = ((_options$chart2 = options.chart) === null || _options$chart2 === void 0 ? void 0 : _options$chart2.zoomType) === 'x' && model !== null && isContinuous(model.xAxis.scale);
300
+ const zooms = options.chart?.zoomType === 'x' && model !== null && isContinuous(model.xAxis.scale);
303
301
  const localX = event => event.clientX - event.currentTarget.getBoundingClientRect().left;
304
302
  const startDrag = useCallback(event => {
305
303
  if (!zooms || !model) {
@@ -352,11 +350,10 @@ function ChartBody({
352
350
  setHover(null);
353
351
  }, []);
354
352
  const handleClick = useCallback(event => {
355
- var _hitsAt, _series$points$neares;
356
353
  if (!onPointClick || !model) {
357
354
  return;
358
355
  }
359
- const hits = ((_hitsAt = hitsAt(event)) === null || _hitsAt === void 0 ? void 0 : _hitsAt.hits) ?? [];
356
+ const hits = hitsAt(event)?.hits ?? [];
360
357
  if (!hits.length) {
361
358
  return;
362
359
  }
@@ -364,33 +361,30 @@ function ChartBody({
364
361
  const series = model.series.find(item => item.index === nearest.seriesIndex);
365
362
  onPointClick({
366
363
  seriesIndex: nearest.seriesIndex,
367
- seriesName: (series === null || series === void 0 ? void 0 : series.options.name) ?? `Series ${nearest.seriesIndex + 1}`,
364
+ seriesName: series?.options.name ?? `Series ${nearest.seriesIndex + 1}`,
368
365
  pointIndex: nearest.pointIndex,
369
366
  x: nearest.x,
370
367
  y: nearest.y,
371
368
  value: nearest.value,
372
- color: (series === null || series === void 0 ? void 0 : series.color) ?? DEFAULT_TEXT_COLOR,
373
- meta: series === null || series === void 0 || (_series$points$neares = series.points[nearest.pointIndex]) === null || _series$points$neares === void 0 ? void 0 : _series$points$neares.meta
369
+ color: series?.color ?? DEFAULT_TEXT_COLOR,
370
+ meta: series?.points[nearest.pointIndex]?.meta
374
371
  }, event);
375
372
  }, [onPointClick, model, hitsAt]);
376
373
  const formatX = useCallback(value => {
377
- var _options$tooltip3;
378
374
  if (typeof value !== 'number') {
379
375
  return String(value);
380
376
  }
381
- const pattern = ((_options$tooltip3 = options.tooltip) === null || _options$tooltip3 === void 0 ? void 0 : _options$tooltip3.dateFormat) ?? (model && isContinuous(model.xAxis.scale) && model.xAxis.scale.kind === 'time' ? '%b %d, %Y' : undefined);
377
+ const pattern = options.tooltip?.dateFormat ?? (model && isContinuous(model.xAxis.scale) && model.xAxis.scale.kind === 'time' ? '%b %d, %Y' : undefined);
382
378
  return pattern ? formatTime(pattern, value) : String(value);
383
- }, [(_options$tooltip4 = options.tooltip) === null || _options$tooltip4 === void 0 ? void 0 : _options$tooltip4.dateFormat, model]);
379
+ }, [options.tooltip?.dateFormat, model]);
384
380
  const formatValue = useCallback(value => {
385
- var _options$tooltip5, _options$tooltip6;
386
381
  if (value === null) {
387
382
  return '—';
388
383
  }
389
384
  const text = model ? model.numberFormat(value) : String(value);
390
- return `${((_options$tooltip5 = options.tooltip) === null || _options$tooltip5 === void 0 ? void 0 : _options$tooltip5.valuePrefix) ?? ''}${text}${((_options$tooltip6 = options.tooltip) === null || _options$tooltip6 === void 0 ? void 0 : _options$tooltip6.valueSuffix) ?? ''}`;
391
- }, [(_options$tooltip7 = options.tooltip) === null || _options$tooltip7 === void 0 ? void 0 : _options$tooltip7.valuePrefix, (_options$tooltip8 = options.tooltip) === null || _options$tooltip8 === void 0 ? void 0 : _options$tooltip8.valueSuffix, model]);
385
+ return `${options.tooltip?.valuePrefix ?? ''}${text}${options.tooltip?.valueSuffix ?? ''}`;
386
+ }, [options.tooltip?.valuePrefix, options.tooltip?.valueSuffix, model]);
392
387
  const tooltipContent = useMemo(() => {
393
- var _points$, _options$title, _options$tooltip9, _options$tooltip0;
394
388
  if (!hover || !model) {
395
389
  return null;
396
390
  }
@@ -403,18 +397,18 @@ function ChartBody({
403
397
  }
404
398
  const points = shown.map(hit => {
405
399
  const series = model.series.find(item => item.index === hit.seriesIndex);
406
- const neighbours = (series === null || series === void 0 ? void 0 : series.points) ?? [];
400
+ const neighbours = series?.points ?? [];
407
401
  const previous = neighbours[hit.pointIndex - 1];
408
402
  const next = neighbours[hit.pointIndex + 1];
409
403
  return {
410
404
  seriesIndex: hit.seriesIndex,
411
- seriesName: (series === null || series === void 0 ? void 0 : series.options.name) ?? `Series ${hit.seriesIndex + 1}`,
412
- color: (series === null || series === void 0 ? void 0 : series.color) ?? DEFAULT_TEXT_COLOR,
405
+ seriesName: series?.options.name ?? `Series ${hit.seriesIndex + 1}`,
406
+ color: series?.color ?? DEFAULT_TEXT_COLOR,
413
407
  x: hit.x,
414
408
  y: hit.y,
415
409
  value: hit.value,
416
410
  index: hit.pointIndex,
417
- meta: series === null || series === void 0 ? void 0 : series.options.meta,
411
+ meta: series?.options.meta,
418
412
  prev: previous ? {
419
413
  x: previous.x,
420
414
  y: previous.y,
@@ -428,34 +422,33 @@ function ChartBody({
428
422
  };
429
423
  });
430
424
  const ctx = {
431
- x: ((_points$ = points[0]) === null || _points$ === void 0 ? void 0 : _points$.x) ?? 0,
425
+ x: points[0]?.x ?? 0,
432
426
  points,
433
427
  chart: {
434
- title: ((_options$title = options.title) === null || _options$title === void 0 ? void 0 : _options$title.text) ?? undefined,
428
+ title: options.title?.text ?? undefined,
435
429
  meta: options.meta
436
430
  }
437
431
  };
438
- const formatter = (_options$tooltip9 = options.tooltip) === null || _options$tooltip9 === void 0 ? void 0 : _options$tooltip9.formatter;
432
+ const formatter = options.tooltip?.formatter;
439
433
  if (formatter) {
440
434
  return formatter(ctx);
441
435
  }
442
- const table = (_options$tooltip0 = options.tooltip) === null || _options$tooltip0 === void 0 ? void 0 : _options$tooltip0.table;
436
+ const table = options.tooltip?.table;
443
437
  return table ? tableTooltip(ctx, table, formatX) : defaultTooltip(ctx, formatX, formatValue);
444
- }, [hover, model, (_options$title2 = options.title) === null || _options$title2 === void 0 ? void 0 : _options$title2.text, options.meta, (_options$tooltip1 = options.tooltip) === null || _options$tooltip1 === void 0 ? void 0 : _options$tooltip1.formatter, (_options$tooltip10 = options.tooltip) === null || _options$tooltip10 === void 0 ? void 0 : _options$tooltip10.table, formatX, formatValue]);
445
- const hasData = (model === null || model === void 0 ? void 0 : model.series.some(series => series.points.some(point => point.y !== null))) ?? false;
446
- const plotBorderWidth = ((_options$chart3 = options.chart) === null || _options$chart3 === void 0 ? void 0 : _options$chart3.plotBorderWidth) ?? 0;
438
+ }, [hover, model, options.title?.text, options.meta, options.tooltip?.formatter, options.tooltip?.table, formatX, formatValue]);
439
+ const hasData = model?.series.some(series => series.points.some(point => point.y !== null)) ?? false;
440
+ const plotBorderWidth = options.chart?.plotBorderWidth ?? 0;
447
441
  const scrolls = canvas.width > size.width || canvas.height > size.height;
448
442
  // Only horizontal scrolling pins anything, and only a left-hand y axis: that is
449
443
  // the one whose labels the plot would otherwise slide out from under. A right-hand
450
444
  // axis and a vertically scrolling chart both stay in the scrolling canvas.
451
- const pinsAxes = canvas.width > size.width && !((model === null || model === void 0 ? void 0 : model.axisless) ?? true);
445
+ const pinsAxes = canvas.width > size.width && !(model?.axisless ?? true);
452
446
  const isPinned = axis => pinsAxes && axis.options.opposite !== true;
453
447
  // Highcharts dims the series a hover is not on. Ours only does it when asked:
454
448
  // switching it on by default would restyle every chart already drawn.
455
449
  const inactiveOpacity = series => {
456
- var _series$options$state;
457
- const opacity = (_series$options$state = series.options.states) === null || _series$options$state === void 0 || (_series$options$state = _series$options$state.inactive) === null || _series$options$state === void 0 ? void 0 : _series$options$state.opacity;
458
- if (opacity === undefined || !(hover !== null && hover !== void 0 && hover.hits.length)) {
450
+ const opacity = series.options.states?.inactive?.opacity;
451
+ if (opacity === undefined || !hover?.hits.length) {
459
452
  return undefined;
460
453
  }
461
454
  return hover.hits.some(hit => hit.seriesIndex === series.index) ? undefined : opacity;
@@ -467,7 +460,7 @@ function ChartBody({
467
460
  if (animation === false) {
468
461
  return 0;
469
462
  }
470
- return (animation === null || animation === void 0 ? void 0 : animation.duration) ?? MOTION_MS;
463
+ return animation?.duration ?? MOTION_MS;
471
464
  };
472
465
  const decorations = layer => {
473
466
  if (!model || model.axisless) {
@@ -491,12 +484,12 @@ function ChartBody({
491
484
  ...containerProps,
492
485
  ref: container,
493
486
  className: className,
494
- "$width": toCssSize((_options$chart4 = options.chart) === null || _options$chart4 === void 0 ? void 0 : _options$chart4.width, '100%'),
495
- "$height": toCssSize((_options$chart5 = options.chart) === null || _options$chart5 === void 0 ? void 0 : _options$chart5.height, '100%'),
496
- "$autoHeight": ((_options$chart6 = options.chart) === null || _options$chart6 === void 0 ? void 0 : _options$chart6.height) === undefined,
497
- "$background": (_options$chart7 = options.chart) === null || _options$chart7 === void 0 ? void 0 : _options$chart7.backgroundColor,
498
- "$fontFamily": ((_options$chart8 = options.chart) === null || _options$chart8 === void 0 || (_options$chart8 = _options$chart8.style) === null || _options$chart8 === void 0 ? void 0 : _options$chart8.fontFamily) ?? DEFAULT_FONT_FAMILY,
499
- "$fontSize": ((_options$chart9 = options.chart) === null || _options$chart9 === void 0 || (_options$chart9 = _options$chart9.style) === null || _options$chart9 === void 0 ? void 0 : _options$chart9.fontSize) ?? DEFAULT_FONT_SIZE,
487
+ "$width": toCssSize(options.chart?.width, '100%'),
488
+ "$height": toCssSize(options.chart?.height, '100%'),
489
+ "$autoHeight": options.chart?.height === undefined,
490
+ "$background": options.chart?.backgroundColor,
491
+ "$fontFamily": options.chart?.style?.fontFamily ?? DEFAULT_FONT_FAMILY,
492
+ "$fontSize": options.chart?.style?.fontSize ?? DEFAULT_FONT_SIZE,
500
493
  children: [isLoading ? _jsx(Centred, {
501
494
  children: loading ?? 'Loading…'
502
495
  }) : null, !isLoading && model && !hasData ? _jsx(Centred, {
@@ -507,7 +500,7 @@ function ChartBody({
507
500
  width: canvas.width,
508
501
  height: canvas.height,
509
502
  role: "img",
510
- "aria-label": ((_options$title3 = options.title) === null || _options$title3 === void 0 ? void 0 : _options$title3.text) ?? 'Chart',
503
+ "aria-label": options.title?.text ?? 'Chart',
511
504
  onPointerMove: event => {
512
505
  extendDrag(event);
513
506
  handlePointerMove(event);
@@ -533,7 +526,7 @@ function ChartBody({
533
526
  width: model.plot.width,
534
527
  height: model.plot.height,
535
528
  fill: "none",
536
- stroke: ((_options$chart0 = options.chart) === null || _options$chart0 === void 0 ? void 0 : _options$chart0.plotBorderColor) ?? DEFAULT_GRID_COLOR,
529
+ stroke: options.chart?.plotBorderColor ?? DEFAULT_GRID_COLOR,
537
530
  strokeWidth: plotBorderWidth
538
531
  }) : null, model.series.map(series => {
539
532
  const ctx = contextFor(series);
@@ -563,8 +556,7 @@ function ChartBody({
563
556
  spacing: model.spacing,
564
557
  onToggle: toggleSeries ? toggle : undefined,
565
558
  renderLabel: item => {
566
- var _options$legend, _model$series$find;
567
- const formatter = (_options$legend = options.legend) === null || _options$legend === void 0 ? void 0 : _options$legend.labelFormatter;
559
+ const formatter = options.legend?.labelFormatter;
568
560
  if (!formatter) {
569
561
  return item.label;
570
562
  }
@@ -573,7 +565,7 @@ function ChartBody({
573
565
  name: item.label,
574
566
  color: item.color,
575
567
  visible: item.visible,
576
- meta: (_model$series$find = model.series.find(s => s.index === item.seriesIndex)) === null || _model$series$find === void 0 ? void 0 : _model$series$find.options.meta
568
+ meta: model.series.find(s => s.index === item.seriesIndex)?.options.meta
577
569
  });
578
570
  }
579
571
  })]
@@ -587,7 +579,7 @@ function ChartBody({
587
579
  y: 0,
588
580
  width: model.plot.x,
589
581
  height: canvas.height,
590
- fill: ((_options$chart1 = options.chart) === null || _options$chart1 === void 0 ? void 0 : _options$chart1.backgroundColor) ?? DEFAULT_SURFACE_COLOR
582
+ fill: options.chart?.backgroundColor ?? DEFAULT_SURFACE_COLOR
591
583
  }), model.yAxes.filter(isPinned).map(axis => _jsx(YAxis, {
592
584
  plot: model.plot,
593
585
  axis: axis
@@ -595,7 +587,7 @@ function ChartBody({
595
587
  }) : null, zoom ? _jsx(ResetZoom, {
596
588
  type: "button",
597
589
  onClick: resetZoom,
598
- children: ((_options$chart10 = options.chart) === null || _options$chart10 === void 0 ? void 0 : _options$chart10.resetZoomText) ?? 'Reset zoom'
590
+ children: options.chart?.resetZoomText ?? 'Reset zoom'
599
591
  }) : null, hover && tooltipContent ? _jsx(Tooltip, {
600
592
  at: hover.anchor,
601
593
  pointer: hover.pointer,
@@ -15,8 +15,7 @@ export function Hinted({
15
15
  const ref = useRef(null);
16
16
  const [at, setAt] = useState(null);
17
17
  const open = useCallback(() => {
18
- var _ref$current;
19
- const box = (_ref$current = ref.current) === null || _ref$current === void 0 ? void 0 : _ref$current.getBoundingClientRect();
18
+ const box = ref.current?.getBoundingClientRect();
20
19
  if (box) {
21
20
  setAt({
22
21
  x: box.left + box.width / 2,
@@ -15,29 +15,28 @@ export function Legend({
15
15
  renderLabel,
16
16
  onToggle
17
17
  }) {
18
- if (!items.length || (options === null || options === void 0 ? void 0 : options.enabled) === false) {
18
+ if (!items.length || options?.enabled === false) {
19
19
  return null;
20
20
  }
21
- const style = options === null || options === void 0 ? void 0 : options.itemStyle;
22
- const symbolSize = (options === null || options === void 0 ? void 0 : options.symbolHeight) ?? 8;
23
- const symbolRadius = (options === null || options === void 0 ? void 0 : options.symbolRadius) ?? 2;
24
- const symbolPadding = (options === null || options === void 0 ? void 0 : options.symbolPadding) ?? 6;
21
+ const style = options?.itemStyle;
22
+ const symbolSize = options?.symbolHeight ?? 8;
23
+ const symbolRadius = options?.symbolRadius ?? 2;
24
+ const symbolPadding = options?.symbolPadding ?? 6;
25
25
  const {
26
26
  positions,
27
27
  metrics
28
28
  } = layoutLegend(items, options, plot, size, spacing);
29
29
  const interactive = Boolean(onToggle);
30
- const activate = item => () => onToggle === null || onToggle === void 0 ? void 0 : onToggle(item);
30
+ const activate = item => () => onToggle?.(item);
31
31
  const onKeyDown = item => event => {
32
32
  if (event.key !== 'Enter' && event.key !== ' ') {
33
33
  return;
34
34
  }
35
35
  event.preventDefault();
36
- onToggle === null || onToggle === void 0 || onToggle(item);
36
+ onToggle?.(item);
37
37
  };
38
38
  return _jsx("g", {
39
39
  children: items.map((item, index) => {
40
- var _options$itemHoverSty, _options$itemHoverSty2;
41
40
  const {
42
41
  x,
43
42
  y
@@ -47,8 +46,8 @@ export function Legend({
47
46
  return _jsxs(LegendItemBox, {
48
47
  "$off": !item.visible,
49
48
  "$interactive": interactive,
50
- "$hoverColor": options === null || options === void 0 || (_options$itemHoverSty = options.itemHoverStyle) === null || _options$itemHoverSty === void 0 ? void 0 : _options$itemHoverSty.color,
51
- "$hoverWeight": options === null || options === void 0 || (_options$itemHoverSty2 = options.itemHoverStyle) === null || _options$itemHoverSty2 === void 0 ? void 0 : _options$itemHoverSty2.fontWeight,
49
+ "$hoverColor": options?.itemHoverStyle?.color,
50
+ "$hoverWeight": options?.itemHoverStyle?.fontWeight,
52
51
  role: interactive ? 'button' : undefined,
53
52
  tabIndex: interactive ? 0 : undefined,
54
53
  "aria-pressed": interactive ? item.visible : undefined,
@@ -72,17 +71,17 @@ export function Legend({
72
71
  }) : _jsx("rect", {
73
72
  x: x,
74
73
  y: y - symbolSize / 2,
75
- width: (options === null || options === void 0 ? void 0 : options.symbolWidth) ?? symbolSize,
74
+ width: options?.symbolWidth ?? symbolSize,
76
75
  height: symbolSize,
77
76
  rx: item.symbol === 'circle' ? symbolSize / 2 : symbolRadius,
78
77
  fill: item.color
79
78
  }), _jsx("text", {
80
79
  x: labelX,
81
80
  y: y + TEXT_BASELINE_SHIFT,
82
- fill: (style === null || style === void 0 ? void 0 : style.color) ?? DEFAULT_TEXT_COLOR,
83
- fontFamily: style === null || style === void 0 ? void 0 : style.fontFamily,
84
- fontSize: (style === null || style === void 0 ? void 0 : style.fontSize) ?? DEFAULT_FONT_SIZE,
85
- fontWeight: style === null || style === void 0 ? void 0 : style.fontWeight,
81
+ fill: style?.color ?? DEFAULT_TEXT_COLOR,
82
+ fontFamily: style?.fontFamily,
83
+ fontSize: style?.fontSize ?? DEFAULT_FONT_SIZE,
84
+ fontWeight: style?.fontWeight,
86
85
  textDecoration: item.visible ? undefined : 'line-through',
87
86
  children: renderLabel(item)
88
87
  })]