tinybase 8.5.0-beta.1 → 8.5.0-beta.2

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 (35) hide show
  1. package/@types/ui-react-dom-charts/index.d.ts +151 -6
  2. package/@types/ui-react-dom-charts/with-schemas/index.d.ts +188 -8
  3. package/min/ui-react/index.js +1 -1
  4. package/min/ui-react/index.js.gz +0 -0
  5. package/min/ui-react/with-schemas/index.js +1 -1
  6. package/min/ui-react/with-schemas/index.js.gz +0 -0
  7. package/min/ui-react-dom/index.js +1 -1
  8. package/min/ui-react-dom/index.js.gz +0 -0
  9. package/min/ui-react-dom/with-schemas/index.js +1 -1
  10. package/min/ui-react-dom/with-schemas/index.js.gz +0 -0
  11. package/min/ui-react-dom-charts/index.js +1 -1
  12. package/min/ui-react-dom-charts/index.js.gz +0 -0
  13. package/min/ui-react-dom-charts/with-schemas/index.js +1 -1
  14. package/min/ui-react-dom-charts/with-schemas/index.js.gz +0 -0
  15. package/min/ui-react-inspector/index.js +1 -1
  16. package/min/ui-react-inspector/index.js.gz +0 -0
  17. package/min/ui-react-inspector/with-schemas/index.js +1 -1
  18. package/min/ui-react-inspector/with-schemas/index.js.gz +0 -0
  19. package/package.json +8 -8
  20. package/readme.md +13 -17
  21. package/releases.md +111 -81
  22. package/ui-react/index.js +3 -0
  23. package/ui-react/with-schemas/index.js +3 -0
  24. package/ui-react-dom/index.js +8 -5
  25. package/ui-react-dom/with-schemas/index.js +8 -5
  26. package/ui-react-dom-charts/index.js +1274 -720
  27. package/ui-react-dom-charts/with-schemas/index.js +1274 -720
  28. package/ui-react-inspector/index.js +13 -10
  29. package/ui-react-inspector/with-schemas/index.js +13 -10
  30. package/ui-svelte/index.js +1 -1
  31. package/ui-svelte/with-schemas/index.js +1 -1
  32. package/ui-svelte-dom/index.js +2 -2
  33. package/ui-svelte-dom/with-schemas/index.js +2 -2
  34. package/ui-svelte-inspector/index.js +2 -2
  35. package/ui-svelte-inspector/with-schemas/index.js +2 -2
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import {Fragment, jsx, jsxs} from 'react/jsx-runtime';
2
+ import {Fragment as Fragment$1, jsx, jsxs} from 'react/jsx-runtime';
3
3
 
4
4
  const getTypeOf = (thing) => typeof thing;
5
5
  const TINYBASE = 'tinybase';
@@ -23,6 +23,7 @@ const getIfNotFunction = (predicate) => (value, then, otherwise) =>
23
23
  : then(value);
24
24
  const GLOBAL = globalThis;
25
25
  const number = Number;
26
+ const string = String;
26
27
  const mathMax = math.max;
27
28
  const mathMin = math.min;
28
29
  const mathCeil = math.ceil;
@@ -38,15 +39,53 @@ const isInteger = number.isInteger;
38
39
  const isNullish = (thing) => thing == null;
39
40
  const isUndefined = (thing) => thing === void 0;
40
41
  const isNull = (thing) => thing === null;
42
+ const isTrue = (thing) => thing === true;
43
+ const isFalse = (thing) => thing === false;
41
44
  const ifNotNullish = getIfNotFunction(isNullish);
42
45
  const ifNotUndefined = getIfNotFunction(isUndefined);
43
46
  const isString = (thing) => getTypeOf(thing) == STRING;
44
47
  const isNumber = (thing) => getTypeOf(thing) == NUMBER;
45
48
  const isArray = (thing) => Array.isArray(thing);
46
49
  const size = (arrayOrString) => arrayOrString.length;
50
+ const test = (regex, subject) => regex.test(subject);
51
+
52
+ const {
53
+ Children,
54
+ Fragment,
55
+ PureComponent,
56
+ createContext,
57
+ isValidElement,
58
+ useCallback,
59
+ useContext,
60
+ useEffect,
61
+ useLayoutEffect,
62
+ useMemo,
63
+ useRef,
64
+ useState,
65
+ useSyncExternalStore,
66
+ } = React;
67
+
68
+ var SourceType = /* @__PURE__ */ ((SourceType2) => {
69
+ SourceType2[(SourceType2['None'] = 0)] = 'None';
70
+ SourceType2[(SourceType2['Query'] = 1)] = 'Query';
71
+ SourceType2[(SourceType2['Table'] = 2)] = 'Table';
72
+ return SourceType2;
73
+ })(SourceType || {});
74
+ const CHART_SERIES = '_tinybaseChartSeries';
75
+ const isChartSeriesComponent = (component) =>
76
+ typeof component == 'function' && component[CHART_SERIES] === true;
77
+ const CartesianChartContext = createContext(null);
78
+ const useCartesianChartContext = () => {
79
+ const context = useContext(CartesianChartContext);
80
+ if (context == null) {
81
+ throw new Error('Series components must be used inside a CartesianChart');
82
+ }
83
+ return context;
84
+ };
47
85
 
48
86
  const arrayNew = (size2, cb) =>
49
87
  arrayMap(new Array(size2).fill(0), (_, index) => cb(index));
88
+ const arrayHas = (array, value) => array.includes(value);
50
89
  const arrayIndexOf = (array, value) => array.indexOf(value);
51
90
  const arrayEvery = (array, cb) => array.every(cb);
52
91
  const arrayIsEqual = (array1, array2) =>
@@ -61,85 +100,8 @@ const arrayJoin = (array, sep = EMPTY_STRING) => array.join(sep);
61
100
  const arrayMap = (array, cb) => array.map(cb);
62
101
  const arrayIsEmpty = (array) => size(array) == 0;
63
102
  const arrayFilter = (array, cb) => array.filter(cb);
64
-
65
- const {
66
- PureComponent,
67
- createContext,
68
- useCallback,
69
- useContext,
70
- useEffect,
71
- useLayoutEffect,
72
- useMemo,
73
- useRef,
74
- useState,
75
- useSyncExternalStore,
76
- } = React;
77
-
78
- const DEFAULT_SIZE = [1e3, 1e3];
79
- const DEFAULT_FONT_SIZE = 12;
80
- const DEFAULT_STYLE = [0.5, 0.5, 0.25, 3.5, 4, 1, 1];
81
- const useLayout = () => {
82
- const svgRef = useRef(null);
83
- const [chartLayout, setChartLayout] = useState([
84
- DEFAULT_SIZE,
85
- getDefaultStyle(DEFAULT_FONT_SIZE),
86
- ]);
87
- useLayoutEffect(() => {
88
- const svg = svgRef.current;
89
- if (isNull(svg)) {
90
- return;
91
- }
92
- const updateLayout = ({contentRect}) => {
93
- const style = svg.ownerDocument.defaultView?.getComputedStyle(svg);
94
- const nextLayout = [getSvgSize(contentRect), getStyle(style)];
95
- setChartLayout((chartLayout2) =>
96
- isLayoutEqual(chartLayout2, nextLayout) ? chartLayout2 : nextLayout,
97
- );
98
- };
99
- const observer = new ResizeObserver(([entry]) => updateLayout(entry));
100
- observer.observe(svg);
101
- return () => observer.disconnect();
102
- }, []);
103
- return [svgRef, ...chartLayout];
104
- };
105
- const getPlotSize = ([, chartSize, chartStyle]) => {
106
- const [, , width, height] = getPlotFrame(chartSize, chartStyle);
107
- return [width, height];
108
- };
109
- const getLabelSize = ([, , chartStyle]) => chartStyle[6];
110
- const getPlotFrame = (
111
- [width, height],
112
- [, , , xAxisHeight, yAxisWidth, inset, fontSize],
113
- ) => {
114
- const plotX = inset + mathMax(mathMin(yAxisWidth, width / 2 - 2 * inset), 0);
115
- const plotY = inset + fontSize / 2;
116
- const plotRight = inset + fontSize / 2;
117
- const plotHeight = mathMax(
118
- height -
119
- plotY -
120
- mathMax(mathMin(xAxisHeight, height / 2 - plotY - inset), 0) -
121
- inset,
122
- 0,
123
- );
124
- return [plotX, plotY, mathMax(width - plotX - plotRight, 0), plotHeight];
125
- };
126
- const getDefaultStyle = (fontSize) =>
127
- arrayMap(DEFAULT_STYLE, (value) => value * fontSize);
128
- const getStyle = (style) => {
129
- const fontSize = parseFloat(style?.fontSize ?? '');
130
- return getDefaultStyle(
131
- isFiniteNumber(fontSize) ? fontSize : DEFAULT_FONT_SIZE,
132
- );
133
- };
134
- const getSvgSize = ({width, height}) => [
135
- mathRound(width) || DEFAULT_SIZE[0],
136
- mathRound(height) || DEFAULT_SIZE[1],
137
- ];
138
- const isLayoutEqual = ([chartSize1, chartStyle1], [chartSize2, chartStyle2]) =>
139
- arrayIsEqual(chartSize1, chartSize2) &&
140
- arrayIsEqual(chartStyle1, chartStyle2);
141
-
142
- const CURRENT_COLOR = 'currentColor';
103
+ const arrayPush = (array, ...values) => array.push(...values);
104
+ const arrayShift = (array) => array.shift();
143
105
 
144
106
  const collSize = (coll) => coll?.size ?? 0;
145
107
 
@@ -282,6 +244,9 @@ const getScaledPoints = (
282
244
  points,
283
245
  [xMin, xMax, yMin, yMax],
284
246
  [width, height],
247
+ xValues,
248
+ xTitle,
249
+ yTitle,
285
250
  ) => {
286
251
  const numericX =
287
252
  kind == 'line' &&
@@ -289,17 +254,24 @@ const getScaledPoints = (
289
254
  const xDomain = numericX ? [xMin, xMax] : [0, 0];
290
255
  const yDomain = [yMin ?? 0, yMax ?? 0];
291
256
  const xCategories = /* @__PURE__ */ new Map();
292
- arrayForEach(points, ([, xValue]) => {
293
- if (!xCategories.has(xValue)) {
294
- xCategories.set(xValue, collSize(xCategories));
295
- }
296
- });
257
+ arrayForEach(
258
+ xValues == null || arrayIsEmpty(xValues)
259
+ ? arrayMap(points, ([, xValue]) => xValue)
260
+ : xValues,
261
+ (xValue) => {
262
+ if (!xCategories.has(xValue)) {
263
+ xCategories.set(xValue, collSize(xCategories));
264
+ }
265
+ },
266
+ );
297
267
  return arrayMap(points, ([rowId, xValue, yValue]) => [
298
268
  rowId,
299
269
  xValue,
300
270
  yValue,
301
271
  getX(xValue, numericX, xDomain, xCategories, width, kind),
302
272
  getY(yValue, yDomain, height),
273
+ xTitle,
274
+ yTitle,
303
275
  ]);
304
276
  };
305
277
  const getX = (xValue, numericX, [xMin, xMax], xCategories, width, kind) =>
@@ -363,6 +335,70 @@ const getTickBounds = ([xMin, xMax, yMin, yMax], xTicks, yTicks) => [
363
335
  ? yMax
364
336
  : mathMax(yMax ?? -infinity, yTicks[size(yTicks) - 1]),
365
337
  ];
338
+ const getSeriesSummary = (kind, points, xCellId, yCellId, yLabel) => {
339
+ const [xMin, xMax, yMin, yMax] = getBounds(kind, points);
340
+ const xValues = [];
341
+ const continuousX =
342
+ kind == 'line' &&
343
+ arrayIsEmpty(arrayFilter(points, ([, xValue]) => !isNumber(xValue)));
344
+ arrayForEach(points, ([, xValue]) => {
345
+ if (!arrayHas(xValues, xValue)) {
346
+ arrayPush(xValues, xValue);
347
+ }
348
+ });
349
+ return {
350
+ continuousX,
351
+ xCellId,
352
+ xMin,
353
+ xMax,
354
+ yMin,
355
+ yMax,
356
+ yCellId,
357
+ yLabel,
358
+ xValues,
359
+ };
360
+ };
361
+ const getDomainState = (summaries) => {
362
+ const xValues = [];
363
+ const xMins = [];
364
+ const xMaxes = [];
365
+ const yMins = [];
366
+ const yMaxes = [];
367
+ let continuousX = true;
368
+ let xMin;
369
+ let xMax;
370
+ arrayForEach(summaries, (summary) => {
371
+ continuousX &&= summary.continuousX;
372
+ arrayForEach(summary.xValues, (xValue) => {
373
+ if (!arrayHas(xValues, xValue)) {
374
+ arrayPush(xValues, xValue);
375
+ }
376
+ });
377
+ if (isNumber(summary.xMin) && isNumber(summary.xMax)) {
378
+ xMins.push(summary.xMin);
379
+ xMaxes.push(summary.xMax);
380
+ } else {
381
+ xMin ??= summary.xMin;
382
+ xMax = summary.xMax ?? xMax;
383
+ }
384
+ if (!isUndefined(summary.yMin)) {
385
+ yMins.push(summary.yMin);
386
+ }
387
+ if (!isUndefined(summary.yMax)) {
388
+ yMaxes.push(summary.yMax);
389
+ }
390
+ });
391
+ return {
392
+ bounds: [
393
+ arrayIsEmpty(xMins) ? xMin : mathMin(...xMins),
394
+ arrayIsEmpty(xMaxes) ? xMax : mathMax(...xMaxes),
395
+ arrayIsEmpty(yMins) ? void 0 : mathMin(...yMins),
396
+ arrayIsEmpty(yMaxes) ? void 0 : mathMax(...yMaxes),
397
+ ],
398
+ continuousX: !arrayIsEmpty(summaries) && continuousX,
399
+ xValues,
400
+ };
401
+ };
366
402
  const getYDomain = (points, kind = 'bar') =>
367
403
  getDomain([
368
404
  ...(kind == 'bar' ? [0] : []),
@@ -380,527 +416,117 @@ const getXValue = (cell) =>
380
416
  : void 0
381
417
  : isString(cell)
382
418
  ? cell
383
- : void 0;
419
+ : isTrue(cell) || isFalse(cell)
420
+ ? cell
421
+ : void 0;
384
422
  const getYValue = (cell) =>
385
423
  isNumber(cell) && isFiniteNumber(cell) ? cell : void 0;
386
424
 
387
- const XAxis = ({
425
+ const CURRENT_COLOR = 'currentColor';
426
+
427
+ const Bars = ({
388
428
  points,
389
- xTicks,
390
- xMin,
391
- xMax,
392
- xTitle,
393
429
  plotFrame,
394
- tickSize,
395
- tickGap,
396
- axisHeight,
397
- fontSize,
430
+ barGap,
431
+ barSeriesCount,
432
+ barSeriesIndex,
433
+ setTooltipPoint,
434
+ yMin = 0,
435
+ yMax = 0,
398
436
  }) => {
399
- const [plotX, plotY, plotWidth, plotHeight] = plotFrame;
400
- const titleGap = mathMax(axisHeight - tickSize - tickGap - 2 * fontSize, 0);
401
- return /* @__PURE__ */ jsxs('g', {
402
- className: 'x',
403
- dominantBaseline: 'hanging',
404
- textAnchor: 'middle',
405
- children: [
406
- /* @__PURE__ */ jsx('path', {
407
- className: 'line',
408
- d: `M${plotX},${plotY + plotHeight}h${plotWidth}`,
409
- fill: 'none',
410
- stroke: CURRENT_COLOR,
411
- strokeOpacity: 0.5,
412
- strokeWidth: 1,
413
- }),
414
- /* @__PURE__ */ jsx('g', {
415
- className: 'ticks',
416
- children:
417
- arrayIsEmpty(xTicks) || !isNumber(xMin) || !isNumber(xMax)
418
- ? arrayMap(points, ([rowId, xValue, , x]) =>
419
- /* @__PURE__ */ jsx(
420
- 'text',
421
- {
422
- x: plotX + x,
423
- y: plotY + plotHeight + tickSize + tickGap,
424
- children: xValue,
425
- },
426
- rowId,
427
- ),
428
- )
429
- : arrayMap(xTicks, (tick) => {
430
- const x = getScale(tick, xMin, xMax, plotWidth);
431
- return /* @__PURE__ */ jsx(
432
- 'text',
433
- {
434
- x: plotX + x,
435
- y: plotY + plotHeight + tickSize + tickGap,
436
- children: tick,
437
- },
438
- tick,
439
- );
440
- }),
441
- }),
442
- /* @__PURE__ */ jsx('text', {
443
- className: 'title',
444
- x: plotX + plotWidth / 2,
445
- y: plotY + plotHeight + tickSize + tickGap + fontSize + titleGap,
446
- children: xTitle,
447
- }),
448
- ],
437
+ const [plotX, plotY, width, height] = plotFrame;
438
+ const baselineY = height - getScale(0, yMin, yMax, height);
439
+ const pointsSize = size(points);
440
+ const fullBarWidth = arrayIsEmpty(points) ? 0 : width / pointsSize;
441
+ const barCount = mathMax(barSeriesCount, 1);
442
+ const barIndex = mathMax(barSeriesIndex, 0);
443
+ const barGroupWidth = mathMax(fullBarWidth - barGap, 0);
444
+ const barWidth = mathMax(
445
+ (barGroupWidth - barGap * (barCount - 1)) / barCount,
446
+ 0,
447
+ );
448
+ return arrayMap(points, (point) => {
449
+ const [rowId, , , x, pointY] = point;
450
+ const y = mathMin(pointY, baselineY);
451
+ return /* @__PURE__ */ jsx(
452
+ 'rect',
453
+ {
454
+ className: 'bar',
455
+ height: mathAbs(baselineY - pointY),
456
+ onPointerEnter: () => setTooltipPoint(point),
457
+ onPointerLeave: () => setTooltipPoint(void 0),
458
+ width: barWidth,
459
+ x: plotX + x - barGroupWidth / 2 + (barWidth + barGap) * barIndex,
460
+ y: plotY + y,
461
+ },
462
+ rowId,
463
+ );
449
464
  });
450
465
  };
451
466
 
452
- const YAxis = ({
453
- yTicks,
454
- yMin,
455
- yMax,
456
- yTitle,
457
- plotFrame,
458
- tickSize,
459
- tickGap,
460
- axisWidth,
461
- }) => {
462
- const [plotX, plotY, , plotHeight] = plotFrame;
463
- return isNullish(yMin) || isNullish(yMax)
464
- ? null
465
- : /* @__PURE__ */ jsxs('g', {
466
- className: 'y',
467
- children: [
468
- /* @__PURE__ */ jsx('path', {
469
- className: 'line',
470
- d: `M${plotX},${plotY}v${plotHeight}`,
471
- fill: 'none',
472
- stroke: CURRENT_COLOR,
473
- strokeOpacity: 0.5,
474
- strokeWidth: 1,
475
- }),
476
- /* @__PURE__ */ jsx('g', {
477
- className: 'ticks',
478
- dominantBaseline: 'middle',
479
- textAnchor: 'end',
480
- children: arrayMap(yTicks, (tick) => {
481
- const y = plotHeight - getScale(tick, yMin, yMax, plotHeight);
482
- return /* @__PURE__ */ jsx(
483
- 'text',
484
- {x: plotX - tickSize - tickGap, y: plotY + y, children: tick},
485
- tick,
486
- );
487
- }),
488
- }),
489
- /* @__PURE__ */ jsx('text', {
490
- className: 'title',
491
- dominantBaseline: 'text-before-edge',
492
- textAnchor: 'middle',
493
- transform: `translate(${plotX - axisWidth} ${plotFrame[1] + plotFrame[3] / 2}) rotate(-90)`,
494
- children: yTitle,
495
- }),
496
- ],
497
- });
498
- };
499
-
500
- const Axes = ({
501
- points,
502
- xTicks,
503
- yTicks,
504
- bounds: [xMin, xMax, yMin, yMax],
505
- titles: [xTitle, yTitle],
506
- xAxisHeight,
507
- yAxisWidth,
508
- fontSize,
509
- ...sharedProps
510
- }) => {
511
- return /* @__PURE__ */ jsxs('g', {
512
- className: 'axes',
513
- fill: CURRENT_COLOR,
514
- fillOpacity: 0.75,
515
- children: [
516
- /* @__PURE__ */ jsx(YAxis, {
517
- ...sharedProps,
518
- yTicks,
519
- yMin,
520
- yMax,
521
- yTitle,
522
- axisWidth: yAxisWidth,
523
- }),
524
- /* @__PURE__ */ jsx(XAxis, {
525
- ...sharedProps,
526
- points,
527
- xTicks,
528
- xMin,
529
- xMax,
530
- xTitle,
531
- axisHeight: xAxisHeight,
532
- fontSize,
533
- }),
534
- ],
535
- });
536
- };
467
+ const object = Object;
468
+ const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
469
+ const objEntries = object.entries;
470
+ const isObject = (obj) =>
471
+ !isNullish(obj) &&
472
+ ifNotNullish(
473
+ getPrototypeOf(obj),
474
+ (objPrototype) =>
475
+ objPrototype == object.prototype ||
476
+ isNullish(getPrototypeOf(objPrototype)),
537
477
 
538
- const Grid = ({
539
- points,
540
- xTicks,
541
- yTicks,
542
- bounds: [xMin, xMax, yMin, yMax],
543
- plotFrame,
544
- tickSize,
545
- }) => {
546
- const [plotX, plotY, width, height] = plotFrame;
547
- return /* @__PURE__ */ jsxs('g', {
548
- className: 'grid',
549
- stroke: CURRENT_COLOR,
550
- strokeOpacity: 0.75,
551
- strokeWidth: 0.5,
552
- children: [
553
- isNullish(yMin) || isNullish(yMax)
554
- ? null
555
- : /* @__PURE__ */ jsx('path', {
556
- className: 'y',
557
- d: arrayJoin(
558
- arrayMap(
559
- arrayFilter(
560
- yTicks,
561
- (tick) => getScale(tick, yMin, yMax, height) != 0,
562
- ),
563
- (tick) =>
564
- `M${plotX - tickSize},${plotY + height - getScale(tick, yMin, yMax, height)}h${width + tickSize}`,
565
- ),
566
- ' ',
567
- ),
568
- }),
569
- arrayIsEmpty(xTicks) || !isNumber(xMin) || !isNumber(xMax)
570
- ? /* @__PURE__ */ jsx('path', {
571
- className: 'x',
572
- d: arrayJoin(
573
- arrayMap(
574
- arrayFilter(points, ([, , , x]) => x != 0),
575
- ([, , , x]) => `M${plotX + x},${plotY}v${height + tickSize}`,
576
- ),
577
- ' ',
578
- ),
579
- })
580
- : /* @__PURE__ */ jsx('path', {
581
- className: 'x',
582
- d: arrayJoin(
583
- arrayMap(
584
- arrayFilter(
585
- xTicks,
586
- (tick) => getScale(tick, xMin, xMax, width) != 0,
587
- ),
588
- (tick) =>
589
- `M${plotX + getScale(tick, xMin, xMax, width)},${plotY}v${height + tickSize}`,
590
- ),
591
- ' ',
592
- ),
593
- }),
594
- ],
595
- });
478
+ /* istanbul ignore next */
479
+ () => true,
480
+ );
481
+ const objIds = object.keys;
482
+ const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
483
+ const objValues = (obj) => object.values(obj);
484
+ const objSize = (obj) => size(objIds(obj));
485
+
486
+ /* istanbul ignore next */
487
+ const objIsEqual = (
488
+ obj1,
489
+ obj2,
490
+ isEqual = (value1, value2) => value1 === value2,
491
+ ) => {
492
+ const entries1 = objEntries(obj1);
493
+ return (
494
+ size(entries1) === objSize(obj2) &&
495
+ arrayEvery(entries1, ([index, value1]) =>
496
+ isObject(value1)
497
+ ? /* istanbul ignore next */
498
+ isObject(obj2[index])
499
+ ? objIsEqual(obj2[index], value1, isEqual)
500
+ : false
501
+ : isEqual(value1, obj2[index]),
502
+ )
503
+ );
596
504
  };
597
505
 
598
- const Marks = ({getMark, points, setTooltipPoint}) =>
599
- arrayMap(points, (point, index) => {
600
- const [rowId] = point;
601
- return /* @__PURE__ */ jsx(
602
- 'g',
603
- {
604
- onPointerEnter: () => setTooltipPoint(point),
605
- onPointerLeave: () => setTooltipPoint(void 0),
606
- children: getMark(point, index),
607
- },
608
- rowId,
609
- );
610
- });
506
+ const jsonString = JSON.stringify;
611
507
 
612
- const Bars = ({
613
- points,
614
- plotFrame,
615
- barGap,
616
- setTooltipPoint,
617
- yMin = 0,
618
- yMax = 0,
619
- }) => {
620
- const [plotX, plotY, width, height] = plotFrame;
621
- const baselineY = height - getScale(0, yMin, yMax, height);
622
- const pointsSize = size(points);
623
- const fullBarWidth = arrayIsEmpty(points) ? 0 : width / pointsSize;
624
- const barWidth = arrayIsEmpty(points) ? 0 : mathMax(fullBarWidth - barGap, 0);
625
- return /* @__PURE__ */ jsx(Marks, {
626
- points,
627
- getMark: ([, , , x, pointY]) => {
628
- const y = mathMin(pointY, baselineY);
629
- return /* @__PURE__ */ jsx('rect', {
630
- className: 'bar',
631
- fill: CURRENT_COLOR,
632
- x: plotX + x - barWidth / 2,
633
- y: plotY + y,
634
- width: barWidth,
635
- height: mathAbs(baselineY - pointY),
636
- });
637
- },
638
- setTooltipPoint,
639
- });
508
+ const TINYBASE_CONTEXT = TINYBASE + '_uirc';
509
+ const Context = GLOBAL[TINYBASE_CONTEXT]
510
+ ? /* istanbul ignore next */
511
+ GLOBAL[TINYBASE_CONTEXT]
512
+ : (GLOBAL[TINYBASE_CONTEXT] = createContext([]));
513
+ const useThing = (id, offset) => {
514
+ const contextValue = useContext(Context);
515
+ return isUndefined(id)
516
+ ? contextValue[offset * 2]
517
+ : isString(id)
518
+ ? objGet(contextValue[offset * 2 + 1], id)
519
+ : id;
640
520
  };
641
-
642
- const Line = ({plotFrame, points, setTooltipPoint}) => {
643
- const [plotX, plotY, , height] = plotFrame;
644
- return /* @__PURE__ */ jsxs(Fragment, {
645
- children: [
646
- /* @__PURE__ */ jsx('path', {
647
- className: 'area',
648
- d: getAreaPath(points, plotX, plotY, height),
649
- fill: CURRENT_COLOR,
650
- fillOpacity: 0.25,
651
- stroke: 'none',
652
- }),
653
- /* @__PURE__ */ jsx('path', {
654
- className: 'line',
655
- d: getLinePath(points, plotX, plotY),
656
- fill: 'none',
657
- stroke: CURRENT_COLOR,
658
- strokeOpacity: 0.75,
659
- strokeWidth: 2,
660
- }),
661
- /* @__PURE__ */ jsx('g', {
662
- className: 'points',
663
- fill: CURRENT_COLOR,
664
- children: arrayMap(points, (point) => {
665
- const [rowId, , , x, y] = point;
666
- return /* @__PURE__ */ jsx(
667
- 'circle',
668
- {
669
- cx: plotX + x,
670
- cy: plotY + y,
671
- onPointerEnter: () => setTooltipPoint(point),
672
- onPointerLeave: () => setTooltipPoint(void 0),
673
- r: 5,
674
- },
675
- rowId,
676
- );
677
- }),
678
- }),
679
- ],
680
- });
521
+ const useThingOrThingById = (thingOrThingId, offset) => {
522
+ const thing = useThing(thingOrThingId, offset);
523
+ return isUndefined(thingOrThingId) || isString(thingOrThingId)
524
+ ? thing
525
+ : thingOrThingId;
681
526
  };
682
- const getLinePath = (points, plotX, plotY) =>
683
- arrayJoin(
684
- arrayMap(
685
- points,
686
- ([, , , x, y], index) =>
687
- `${index == 0 ? 'M' : 'L'}${plotX + x},${plotY + y}`,
688
- ),
689
- ' ',
690
- );
691
- const getAreaPath = (points, plotX, plotY, height) =>
692
- arrayIsEmpty(points)
693
- ? ''
694
- : `${getLinePath(points, plotX, plotY)} L${plotX + points[size(points) - 1][3]},${plotY + height} L${plotX + points[0][3]},${plotY + height} Z`;
695
527
 
696
- const Plot = ({
697
- kind,
698
- points,
699
- plotFrame,
700
- barGap,
701
- setTooltipPoint,
702
- bounds: [, , yMin, yMax],
703
- }) => {
704
- const sharedProps = {points, setTooltipPoint};
705
- return /* @__PURE__ */ jsx('g', {
706
- className: 'plot',
707
- children:
708
- kind == 'line'
709
- ? /* @__PURE__ */ jsx(Line, {...sharedProps, plotFrame})
710
- : /* @__PURE__ */ jsx(Bars, {
711
- ...sharedProps,
712
- plotFrame,
713
- barGap,
714
- yMin,
715
- yMax,
716
- }),
717
- });
718
- };
719
-
720
- const TOOLTIP_WIDTH = 160;
721
- const TOOLTIP_HEIGHT = 60;
722
- const TOOLTIP_GAP = 12;
723
- const TOOLTIP_PADDING = 12;
724
- const Tooltip = ({
725
- point,
726
- width,
727
- height,
728
- plotFrame,
729
- titles: [xTitle, yTitle],
730
- }) => {
731
- if (isNullish(point)) {
732
- return null;
733
- }
734
- const [, xValue, yValue, x, y] = point;
735
- const [plotX, plotY] = plotFrame;
736
- const tooltipX =
737
- x + TOOLTIP_GAP + TOOLTIP_WIDTH > width
738
- ? x - TOOLTIP_GAP - TOOLTIP_WIDTH
739
- : x + TOOLTIP_GAP;
740
- const tooltipY = mathMax(
741
- mathMin(y - TOOLTIP_GAP - TOOLTIP_HEIGHT, height - TOOLTIP_HEIGHT),
742
- 0,
743
- );
744
- return /* @__PURE__ */ jsxs(Fragment, {
745
- children: [
746
- /* @__PURE__ */ jsx('path', {
747
- className: 'tooltip-lines',
748
- pointerEvents: 'none',
749
- stroke: CURRENT_COLOR,
750
- strokeOpacity: 0.25,
751
- strokeWidth: 1,
752
- d: `M${plotX + x},${plotY}v${height}M${plotX},${plotY + y}h${width}`,
753
- }),
754
- /* @__PURE__ */ jsxs('g', {
755
- className: 'tooltip',
756
- transform: `translate(${plotX + tooltipX} ${plotY + tooltipY})`,
757
- fill: CURRENT_COLOR,
758
- children: [
759
- /* @__PURE__ */ jsx('rect', {
760
- fillOpacity: 0.25,
761
- width: TOOLTIP_WIDTH,
762
- height: TOOLTIP_HEIGHT,
763
- rx: 4,
764
- }),
765
- /* @__PURE__ */ jsxs('text', {
766
- x: TOOLTIP_PADDING,
767
- y: 22,
768
- children: [xTitle, ': ', xValue],
769
- }),
770
- /* @__PURE__ */ jsxs('text', {
771
- x: TOOLTIP_PADDING,
772
- y: 46,
773
- children: [yTitle, ': ', yValue],
774
- }),
775
- ],
776
- }),
777
- ],
778
- });
779
- };
780
-
781
- const Layout = ({
782
- className,
783
- kind,
784
- titles,
785
- layout: [svgRef, chartSize, chartStyle],
786
- ...sharedProps
787
- }) => {
788
- const [width, height] = chartSize;
789
- const plotFrame = getPlotFrame(chartSize, chartStyle);
790
- const [, , plotWidth, plotHeight] = plotFrame;
791
- const [tickSize, tickGap, barGap, xAxisHeight, yAxisWidth, , fontSize] =
792
- chartStyle;
793
- const [tooltipPoint, setTooltipPoint] = useState();
794
- const chartProps = {...sharedProps, plotFrame};
795
- return /* @__PURE__ */ jsxs('svg', {
796
- className,
797
- preserveAspectRatio: 'none',
798
- ref: svgRef,
799
- viewBox: `0 0 ${width} ${height}`,
800
- children: [
801
- /* @__PURE__ */ jsx(Grid, {...chartProps, tickSize}),
802
- /* @__PURE__ */ jsx(Axes, {
803
- ...chartProps,
804
- titles,
805
- tickSize,
806
- tickGap,
807
- xAxisHeight,
808
- yAxisWidth,
809
- fontSize,
810
- }),
811
- /* @__PURE__ */ jsx(Plot, {
812
- ...chartProps,
813
- kind,
814
- barGap,
815
- setTooltipPoint,
816
- }),
817
- /* @__PURE__ */ jsx(Tooltip, {
818
- point: tooltipPoint,
819
- width: plotWidth,
820
- height: plotHeight,
821
- plotFrame,
822
- titles,
823
- }),
824
- ],
825
- });
826
- };
827
-
828
- const EmptyChart = ({className, kind, xCellId, yCellId}) => {
829
- const layout = useLayout();
830
- return /* @__PURE__ */ jsx(Layout, {
831
- className,
832
- kind,
833
- points: [],
834
- bounds: [],
835
- titles: [xCellId, yCellId],
836
- xTicks: [],
837
- yTicks: [],
838
- layout,
839
- });
840
- };
841
-
842
- const object = Object;
843
- const getPrototypeOf = (obj) => object.getPrototypeOf(obj);
844
- const objEntries = object.entries;
845
- const isObject = (obj) =>
846
- !isNullish(obj) &&
847
- ifNotNullish(
848
- getPrototypeOf(obj),
849
- (objPrototype) =>
850
- objPrototype == object.prototype ||
851
- isNullish(getPrototypeOf(objPrototype)),
852
-
853
- /* istanbul ignore next */
854
- () => true,
855
- );
856
- const objIds = object.keys;
857
- const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
858
- const objSize = (obj) => size(objIds(obj));
859
-
860
- /* istanbul ignore next */
861
- const objIsEqual = (
862
- obj1,
863
- obj2,
864
- isEqual = (value1, value2) => value1 === value2,
865
- ) => {
866
- const entries1 = objEntries(obj1);
867
- return (
868
- size(entries1) === objSize(obj2) &&
869
- arrayEvery(entries1, ([index, value1]) =>
870
- isObject(value1)
871
- ? /* istanbul ignore next */
872
- isObject(obj2[index])
873
- ? objIsEqual(obj2[index], value1, isEqual)
874
- : false
875
- : isEqual(value1, obj2[index]),
876
- )
877
- );
878
- };
879
-
880
- const jsonString = JSON.stringify;
881
-
882
- const TINYBASE_CONTEXT = TINYBASE + '_uirc';
883
- const Context = GLOBAL[TINYBASE_CONTEXT]
884
- ? /* istanbul ignore next */
885
- GLOBAL[TINYBASE_CONTEXT]
886
- : (GLOBAL[TINYBASE_CONTEXT] = createContext([]));
887
- const useThing = (id, offset) => {
888
- const contextValue = useContext(Context);
889
- return isUndefined(id)
890
- ? contextValue[offset * 2]
891
- : isString(id)
892
- ? objGet(contextValue[offset * 2 + 1], id)
893
- : id;
894
- };
895
- const useThingOrThingById = (thingOrThingId, offset) => {
896
- const thing = useThing(thingOrThingId, offset);
897
- return isUndefined(thingOrThingId) || isString(thingOrThingId)
898
- ? thing
899
- : thingOrThingId;
900
- };
901
-
902
- const OFFSET_STORE = 0;
903
- const OFFSET_QUERIES = 4;
528
+ const OFFSET_STORE = 0;
529
+ const OFFSET_QUERIES = 4;
904
530
 
905
531
  const EMPTY_ARRAY = [];
906
532
  const DEFAULTS = [
@@ -1067,163 +693,1091 @@ const useResultCellListener = (
1067
693
  [queryId, rowId, cellId],
1068
694
  );
1069
695
 
1070
- const useData = (kind, rowIds, chartSize, labelSize, getXCell, getYCell) => {
696
+ const EMPTY_ID = '';
697
+ const useSeriesData = ({
698
+ descending,
699
+ limit,
700
+ offset,
701
+ sortCellId,
702
+ xCellId,
703
+ yCellId,
704
+ }) => {
1071
705
  const [, rerender] = useState();
706
+ const context = useCartesianChartContext();
707
+ const {
708
+ getSeriesId,
709
+ queries,
710
+ queriesOrQueriesId,
711
+ queryId,
712
+ releaseSeriesId,
713
+ sourceType,
714
+ store,
715
+ storeOrStoreId,
716
+ tableId,
717
+ } = context;
718
+ const [seriesId] = useState(getSeriesId);
1072
719
  const handleChange = useCallback(() => rerender([]), [rerender]);
1073
- const points = getDataPoints(rowIds, (rowId) =>
1074
- getDataPoint(rowId, getXCell(rowId), getYCell(rowId)),
720
+ const tableRowIds = useSortedRowIds(
721
+ tableId ?? EMPTY_ID,
722
+ sortCellId ?? xCellId,
723
+ descending,
724
+ offset,
725
+ limit,
726
+ storeOrStoreId,
727
+ );
728
+ const queryRowIds = useResultSortedRowIds(
729
+ queryId ?? EMPTY_ID,
730
+ sortCellId ?? xCellId,
731
+ descending,
732
+ offset,
733
+ limit,
734
+ queriesOrQueriesId,
735
+ );
736
+ const rowIds = sourceType == SourceType.Table ? tableRowIds : queryRowIds;
737
+ const points =
738
+ yCellId == null
739
+ ? []
740
+ : getDataPoints(rowIds, (rowId) =>
741
+ getDataPoint(
742
+ rowId,
743
+ getCell(
744
+ sourceType,
745
+ store,
746
+ queries,
747
+ tableId,
748
+ queryId,
749
+ rowId,
750
+ xCellId,
751
+ ),
752
+ getCell(
753
+ sourceType,
754
+ store,
755
+ queries,
756
+ tableId,
757
+ queryId,
758
+ rowId,
759
+ yCellId,
760
+ ),
761
+ ),
762
+ );
763
+ useCellListener(
764
+ sourceType == SourceType.Table ? (tableId ?? null) : null,
765
+ null,
766
+ xCellId,
767
+ handleChange,
768
+ [handleChange],
769
+ false,
770
+ storeOrStoreId,
771
+ );
772
+ useCellListener(
773
+ sourceType == SourceType.Table ? (tableId ?? null) : null,
774
+ null,
775
+ yCellId ?? null,
776
+ handleChange,
777
+ [handleChange],
778
+ false,
779
+ storeOrStoreId,
780
+ );
781
+ useResultCellListener(
782
+ sourceType == SourceType.Query ? (queryId ?? null) : null,
783
+ null,
784
+ xCellId,
785
+ handleChange,
786
+ [handleChange],
787
+ queriesOrQueriesId,
788
+ );
789
+ useResultCellListener(
790
+ sourceType == SourceType.Query ? (queryId ?? null) : null,
791
+ null,
792
+ yCellId ?? null,
793
+ handleChange,
794
+ [handleChange],
795
+ queriesOrQueriesId,
796
+ );
797
+ useLayoutEffect(
798
+ () => () => releaseSeriesId(seriesId),
799
+ [releaseSeriesId, seriesId],
800
+ );
801
+ return [seriesId, points];
802
+ };
803
+ const getSeriesClassName = (baseClassName, className) =>
804
+ className == null ? baseClassName : `${baseClassName} ${className}`;
805
+ const getCell = (
806
+ sourceType,
807
+ store,
808
+ queries,
809
+ tableId,
810
+ queryId,
811
+ rowId,
812
+ cellId,
813
+ ) =>
814
+ sourceType == SourceType.Table
815
+ ? store?.getCell(tableId, rowId, cellId)
816
+ : queries?.getResultCell(queryId, rowId, cellId);
817
+
818
+ const BarSeries = (props) => {
819
+ const {
820
+ barSeriesCount,
821
+ bounds,
822
+ getBarSeriesIndex,
823
+ layout: [, , [, , barGap]],
824
+ plotFrame,
825
+ plotSize,
826
+ registerBarSeries,
827
+ releaseBarSeries,
828
+ setSeriesSummary,
829
+ setTooltipPoint,
830
+ xValues,
831
+ } = useCartesianChartContext();
832
+ const {className, label, xCellId, yCellId} = props;
833
+ const [seriesId, rawPoints] = useSeriesData(props);
834
+ const barSeriesIndex = getBarSeriesIndex(seriesId);
835
+ const [, , yMin, yMax] = bounds;
836
+ const points = getScaledPoints(
837
+ 'bar',
838
+ rawPoints,
839
+ bounds,
840
+ plotSize,
841
+ xValues,
842
+ xCellId,
843
+ label ?? yCellId,
844
+ );
845
+ useLayoutEffect(() => {
846
+ setSeriesSummary(
847
+ seriesId,
848
+ getSeriesSummary('bar', rawPoints, xCellId, yCellId, label),
849
+ );
850
+ });
851
+ useLayoutEffect(() => {
852
+ registerBarSeries(seriesId);
853
+ return () => releaseBarSeries(seriesId);
854
+ }, [registerBarSeries, releaseBarSeries, seriesId]);
855
+ return /* @__PURE__ */ jsx('g', {
856
+ className: getSeriesClassName('bar-series', className),
857
+ fill: CURRENT_COLOR,
858
+ children: /* @__PURE__ */ jsx(Bars, {
859
+ barGap,
860
+ barSeriesCount,
861
+ barSeriesIndex,
862
+ plotFrame,
863
+ points,
864
+ setTooltipPoint,
865
+ yMax,
866
+ yMin,
867
+ }),
868
+ });
869
+ };
870
+ BarSeries[CHART_SERIES] = true;
871
+
872
+ const INTEGER = /^\d+$/;
873
+ const getPoolFunctions = () => {
874
+ const pool = [];
875
+ let nextId = 0;
876
+ return [
877
+ (reuse) => (reuse ? arrayShift(pool) : null) ?? EMPTY_STRING + nextId++,
878
+ (id) => {
879
+ if (test(INTEGER, id) && size(pool) < 1e3) {
880
+ arrayPush(pool, id);
881
+ }
882
+ },
883
+ ];
884
+ };
885
+
886
+ const DEFAULT_SIZE = [1e3, 1e3];
887
+ const DEFAULT_FONT_SIZE = 12;
888
+ const DEFAULT_STYLE = [0.5, 0.5, 0.25, 3.5, 4, 1, 1];
889
+ const useLayout = () => {
890
+ const svgRef = useRef(null);
891
+ const chartLayoutRef = useRef([
892
+ DEFAULT_SIZE,
893
+ getDefaultStyle(DEFAULT_FONT_SIZE),
894
+ ]);
895
+ const [chartLayout, setChartLayout] = useState([
896
+ DEFAULT_SIZE,
897
+ getDefaultStyle(DEFAULT_FONT_SIZE),
898
+ ]);
899
+ useLayoutEffect(() => {
900
+ const svg = svgRef.current;
901
+ if (isNull(svg)) {
902
+ return;
903
+ }
904
+ const updateLayout = ({contentRect}) => {
905
+ const style = svg.ownerDocument.defaultView?.getComputedStyle(svg);
906
+ const nextLayout = [getSvgSize(contentRect), getStyle(style)];
907
+ if (!isLayoutEqual(chartLayoutRef.current, nextLayout)) {
908
+ chartLayoutRef.current = nextLayout;
909
+ setChartLayout(nextLayout);
910
+ }
911
+ };
912
+ const observer = new ResizeObserver(([entry]) => updateLayout(entry));
913
+ observer.observe(svg);
914
+ return () => observer.disconnect();
915
+ }, []);
916
+ return [svgRef, ...chartLayout];
917
+ };
918
+ const getPlotSize = ([, chartSize, chartStyle]) => {
919
+ const [, , width, height] = getPlotFrame(chartSize, chartStyle);
920
+ return [width, height];
921
+ };
922
+ const getLabelSize = ([, , chartStyle]) => chartStyle[6];
923
+ const getPlotFrame = (
924
+ [width, height],
925
+ [, , , xAxisHeight, yAxisWidth, inset, fontSize],
926
+ ) => {
927
+ const plotX = inset + mathMax(mathMin(yAxisWidth, width / 2 - 2 * inset), 0);
928
+ const plotY = inset + fontSize / 2;
929
+ const plotRight = inset + fontSize / 2;
930
+ const plotHeight = mathMax(
931
+ height -
932
+ plotY -
933
+ mathMax(mathMin(xAxisHeight, height / 2 - plotY - inset), 0) -
934
+ inset,
935
+ 0,
936
+ );
937
+ return [plotX, plotY, mathMax(width - plotX - plotRight, 0), plotHeight];
938
+ };
939
+ const getDefaultStyle = (fontSize) =>
940
+ arrayMap(DEFAULT_STYLE, (value) => value * fontSize);
941
+ const getStyle = (style) => {
942
+ const fontSize = parseFloat(style?.fontSize ?? '');
943
+ return getDefaultStyle(
944
+ isFiniteNumber(fontSize) ? fontSize : DEFAULT_FONT_SIZE,
945
+ );
946
+ };
947
+ const getSvgSize = ({width, height}) => [
948
+ mathRound(width) || DEFAULT_SIZE[0],
949
+ mathRound(height) || DEFAULT_SIZE[1],
950
+ ];
951
+ const isLayoutEqual = ([chartSize1, chartStyle1], [chartSize2, chartStyle2]) =>
952
+ arrayIsEqual(chartSize1, chartSize2) &&
953
+ arrayIsEqual(chartStyle1, chartStyle2);
954
+
955
+ const XAxis = ({
956
+ points,
957
+ xTicks,
958
+ xMin,
959
+ xMax,
960
+ xTitle,
961
+ plotFrame,
962
+ tickSize,
963
+ tickGap,
964
+ axisHeight,
965
+ fontSize,
966
+ }) => {
967
+ const [plotX, plotY, plotWidth, plotHeight] = plotFrame;
968
+ const titleGap = mathMax(axisHeight - tickSize - tickGap - 2 * fontSize, 0);
969
+ return /* @__PURE__ */ jsxs('g', {
970
+ className: 'x',
971
+ dominantBaseline: 'hanging',
972
+ textAnchor: 'middle',
973
+ children: [
974
+ /* @__PURE__ */ jsx('path', {
975
+ className: 'line',
976
+ d: `M${plotX},${plotY + plotHeight}h${plotWidth}`,
977
+ fill: 'none',
978
+ stroke: CURRENT_COLOR,
979
+ strokeOpacity: 0.5,
980
+ strokeWidth: 1,
981
+ }),
982
+ /* @__PURE__ */ jsx('g', {
983
+ className: 'ticks',
984
+ children:
985
+ arrayIsEmpty(xTicks) || !isNumber(xMin) || !isNumber(xMax)
986
+ ? arrayMap(points, ([rowId, xValue, , x]) =>
987
+ /* @__PURE__ */ jsx(
988
+ 'text',
989
+ {
990
+ x: plotX + x,
991
+ y: plotY + plotHeight + tickSize + tickGap,
992
+ children: string(xValue),
993
+ },
994
+ rowId,
995
+ ),
996
+ )
997
+ : arrayMap(xTicks, (tick) => {
998
+ const x = getScale(tick, xMin, xMax, plotWidth);
999
+ return /* @__PURE__ */ jsx(
1000
+ 'text',
1001
+ {
1002
+ x: plotX + x,
1003
+ y: plotY + plotHeight + tickSize + tickGap,
1004
+ children: tick,
1005
+ },
1006
+ tick,
1007
+ );
1008
+ }),
1009
+ }),
1010
+ /* @__PURE__ */ jsx('text', {
1011
+ className: 'title',
1012
+ x: plotX + plotWidth / 2,
1013
+ y: plotY + plotHeight + tickSize + tickGap + fontSize + titleGap,
1014
+ children: xTitle,
1015
+ }),
1016
+ ],
1017
+ });
1018
+ };
1019
+
1020
+ const YAxis = ({
1021
+ yTicks,
1022
+ yMin,
1023
+ yMax,
1024
+ yTitle,
1025
+ plotFrame,
1026
+ tickSize,
1027
+ tickGap,
1028
+ axisWidth,
1029
+ }) => {
1030
+ const [plotX, plotY, , plotHeight] = plotFrame;
1031
+ return isNullish(yMin) || isNullish(yMax)
1032
+ ? null
1033
+ : /* @__PURE__ */ jsxs('g', {
1034
+ className: 'y',
1035
+ children: [
1036
+ /* @__PURE__ */ jsx('path', {
1037
+ className: 'line',
1038
+ d: `M${plotX},${plotY}v${plotHeight}`,
1039
+ fill: 'none',
1040
+ stroke: CURRENT_COLOR,
1041
+ strokeOpacity: 0.5,
1042
+ strokeWidth: 1,
1043
+ }),
1044
+ /* @__PURE__ */ jsx('g', {
1045
+ className: 'ticks',
1046
+ dominantBaseline: 'middle',
1047
+ textAnchor: 'end',
1048
+ children: arrayMap(yTicks, (tick) => {
1049
+ const y = plotHeight - getScale(tick, yMin, yMax, plotHeight);
1050
+ return /* @__PURE__ */ jsx(
1051
+ 'text',
1052
+ {x: plotX - tickSize - tickGap, y: plotY + y, children: tick},
1053
+ tick,
1054
+ );
1055
+ }),
1056
+ }),
1057
+ /* @__PURE__ */ jsx('text', {
1058
+ className: 'title',
1059
+ dominantBaseline: 'text-before-edge',
1060
+ textAnchor: 'middle',
1061
+ transform: `translate(${plotX - axisWidth} ${plotFrame[1] + plotFrame[3] / 2}) rotate(-90)`,
1062
+ children: yTitle,
1063
+ }),
1064
+ ],
1065
+ });
1066
+ };
1067
+
1068
+ const Axes = ({
1069
+ points,
1070
+ xTicks,
1071
+ yTicks,
1072
+ bounds: [xMin, xMax, yMin, yMax],
1073
+ titles: [xTitle, yTitle],
1074
+ xAxisHeight,
1075
+ yAxisWidth,
1076
+ fontSize,
1077
+ ...sharedProps
1078
+ }) => {
1079
+ return /* @__PURE__ */ jsxs('g', {
1080
+ className: 'axes',
1081
+ fill: CURRENT_COLOR,
1082
+ fillOpacity: 0.75,
1083
+ children: [
1084
+ /* @__PURE__ */ jsx(YAxis, {
1085
+ ...sharedProps,
1086
+ yTicks,
1087
+ yMin,
1088
+ yMax,
1089
+ yTitle,
1090
+ axisWidth: yAxisWidth,
1091
+ }),
1092
+ /* @__PURE__ */ jsx(XAxis, {
1093
+ ...sharedProps,
1094
+ points,
1095
+ xTicks,
1096
+ xMin,
1097
+ xMax,
1098
+ xTitle,
1099
+ axisHeight: xAxisHeight,
1100
+ fontSize,
1101
+ }),
1102
+ ],
1103
+ });
1104
+ };
1105
+
1106
+ const Grid = ({
1107
+ points,
1108
+ xTicks,
1109
+ yTicks,
1110
+ bounds: [xMin, xMax, yMin, yMax],
1111
+ plotFrame,
1112
+ tickSize,
1113
+ }) => {
1114
+ const [plotX, plotY, width, height] = plotFrame;
1115
+ return /* @__PURE__ */ jsxs('g', {
1116
+ className: 'grid',
1117
+ stroke: CURRENT_COLOR,
1118
+ strokeOpacity: 0.75,
1119
+ strokeWidth: 0.5,
1120
+ children: [
1121
+ isNullish(yMin) || isNullish(yMax)
1122
+ ? null
1123
+ : /* @__PURE__ */ jsx('path', {
1124
+ className: 'y',
1125
+ d: arrayJoin(
1126
+ arrayMap(
1127
+ arrayFilter(
1128
+ yTicks,
1129
+ (tick) => getScale(tick, yMin, yMax, height) != 0,
1130
+ ),
1131
+ (tick) =>
1132
+ `M${plotX - tickSize},${plotY + height - getScale(tick, yMin, yMax, height)}h${width + tickSize}`,
1133
+ ),
1134
+ ' ',
1135
+ ),
1136
+ }),
1137
+ arrayIsEmpty(xTicks) || !isNumber(xMin) || !isNumber(xMax)
1138
+ ? /* @__PURE__ */ jsx('path', {
1139
+ className: 'x',
1140
+ d: arrayJoin(
1141
+ arrayMap(
1142
+ arrayFilter(points, ([, , , x]) => x != 0),
1143
+ ([, , , x]) => `M${plotX + x},${plotY}v${height + tickSize}`,
1144
+ ),
1145
+ ' ',
1146
+ ),
1147
+ })
1148
+ : /* @__PURE__ */ jsx('path', {
1149
+ className: 'x',
1150
+ d: arrayJoin(
1151
+ arrayMap(
1152
+ arrayFilter(
1153
+ xTicks,
1154
+ (tick) => getScale(tick, xMin, xMax, width) != 0,
1155
+ ),
1156
+ (tick) =>
1157
+ `M${plotX + getScale(tick, xMin, xMax, width)},${plotY}v${height + tickSize}`,
1158
+ ),
1159
+ ' ',
1160
+ ),
1161
+ }),
1162
+ ],
1163
+ });
1164
+ };
1165
+
1166
+ const TOOLTIP_WIDTH = 160;
1167
+ const TOOLTIP_HEIGHT = 60;
1168
+ const TOOLTIP_GAP = 12;
1169
+ const TOOLTIP_PADDING = 12;
1170
+ const TOOLTIP_BACKGROUND = '#111827';
1171
+ const TOOLTIP_TEXT = '#fff';
1172
+ const Tooltip = ({
1173
+ point,
1174
+ width,
1175
+ height,
1176
+ plotFrame,
1177
+ titles: [xTitle, yTitle],
1178
+ }) => {
1179
+ if (isNullish(point)) {
1180
+ return null;
1181
+ }
1182
+ const [, xValue, yValue, x, y, pointXTitle, pointYTitle] = point;
1183
+ const [plotX, plotY] = plotFrame;
1184
+ const tooltipX =
1185
+ x + TOOLTIP_GAP + TOOLTIP_WIDTH > width
1186
+ ? x - TOOLTIP_GAP - TOOLTIP_WIDTH
1187
+ : x + TOOLTIP_GAP;
1188
+ const tooltipY = mathMax(
1189
+ mathMin(y - TOOLTIP_GAP - TOOLTIP_HEIGHT, height - TOOLTIP_HEIGHT),
1190
+ 0,
1075
1191
  );
1076
- const dataBounds = getBounds(kind, points);
1077
- const xTicks = getXTicks(kind, dataBounds, chartSize, labelSize);
1078
- const yTicks = getYTicks(dataBounds, chartSize, labelSize);
1079
- const bounds = getTickBounds(dataBounds, xTicks, yTicks);
1080
- return [
1081
- handleChange,
1082
- getScaledPoints(kind, points, bounds, chartSize),
1083
- bounds,
1084
- xTicks,
1085
- yTicks,
1086
- ];
1192
+ return /* @__PURE__ */ jsxs(Fragment$1, {
1193
+ children: [
1194
+ /* @__PURE__ */ jsx('path', {
1195
+ className: 'tooltip-lines',
1196
+ pointerEvents: 'none',
1197
+ stroke: CURRENT_COLOR,
1198
+ strokeOpacity: 0.25,
1199
+ strokeWidth: 1,
1200
+ d: `M${plotX + x},${plotY}v${height}M${plotX},${plotY + y}h${width}`,
1201
+ }),
1202
+ /* @__PURE__ */ jsxs('g', {
1203
+ className: 'tooltip',
1204
+ transform: `translate(${plotX + tooltipX} ${plotY + tooltipY})`,
1205
+ fontFamily: 'sans-serif',
1206
+ fontWeight: 600,
1207
+ pointerEvents: 'none',
1208
+ children: [
1209
+ /* @__PURE__ */ jsx('rect', {
1210
+ fill: TOOLTIP_BACKGROUND,
1211
+ fillOpacity: 0.9,
1212
+ width: TOOLTIP_WIDTH,
1213
+ height: TOOLTIP_HEIGHT,
1214
+ rx: 6,
1215
+ }),
1216
+ /* @__PURE__ */ jsxs('text', {
1217
+ fill: TOOLTIP_TEXT,
1218
+ x: TOOLTIP_PADDING,
1219
+ y: 22,
1220
+ children: [pointXTitle ?? xTitle, ': ', string(xValue)],
1221
+ }),
1222
+ /* @__PURE__ */ jsxs('text', {
1223
+ fill: TOOLTIP_TEXT,
1224
+ x: TOOLTIP_PADDING,
1225
+ y: 46,
1226
+ children: [pointYTitle ?? yTitle, ': ', yValue],
1227
+ }),
1228
+ ],
1229
+ }),
1230
+ ],
1231
+ });
1087
1232
  };
1088
1233
 
1089
- const QueryChart = ({
1090
- descending,
1234
+ const EMPTY_DOMAIN_STATE = {
1235
+ bounds: [],
1236
+ continuousX: false,
1237
+ xValues: [],
1238
+ };
1239
+ const CartesianChart = ({
1240
+ children,
1091
1241
  className,
1092
- kind,
1093
- limit,
1094
- offset,
1095
- queriesOrQueriesId,
1242
+ initialSummary,
1243
+ queries,
1096
1244
  queryId,
1097
- sortCellId,
1098
- xCellId,
1099
- yCellId,
1245
+ store,
1246
+ tableId,
1100
1247
  }) => {
1101
1248
  const layout = useLayout();
1102
- const queries = useQueriesOrQueriesById(queriesOrQueriesId);
1103
- const rowIds = useResultSortedRowIds(
1104
- queryId,
1105
- sortCellId ?? xCellId,
1106
- descending,
1107
- offset,
1108
- limit,
1109
- queriesOrQueriesId,
1249
+ const [svgRef, chartSize, chartStyle] = layout;
1250
+ const [tickSize, tickGap, , xAxisHeight, yAxisWidth, , fontSize] = chartStyle;
1251
+ const plotFrame = getPlotFrame(chartSize, chartStyle);
1252
+ const plotSize = getPlotSize(layout);
1253
+ const labelSize = getLabelSize(layout);
1254
+ const storeObject = useStoreOrStoreById(store);
1255
+ const queriesObject = useQueriesOrQueriesById(queries);
1256
+ const sourceType =
1257
+ tableId == null
1258
+ ? queryId == null
1259
+ ? SourceType.None
1260
+ : SourceType.Query
1261
+ : SourceType.Table;
1262
+ const initialSummaries = initialSummary == null ? {} : {0: initialSummary};
1263
+ const initialDomainState =
1264
+ initialSummary == null
1265
+ ? EMPTY_DOMAIN_STATE
1266
+ : getDomainState(objValues(initialSummaries));
1267
+ const initialXTitle = getTitle(initialSummaries, 'xCellId');
1268
+ const initialYTitle = getTitle(initialSummaries, 'yCellId');
1269
+ const summariesRef = useRef(initialSummaries);
1270
+ const boundsRef = useRef(initialDomainState.bounds);
1271
+ const domainStateRef = useRef(initialDomainState);
1272
+ const xTitleRef = useRef(initialXTitle);
1273
+ const yTitleRef = useRef(initialYTitle);
1274
+ const pool = useRef(getPoolFunctions());
1275
+ const [domainState, setDomainState] = useState(initialDomainState);
1276
+ const [xTitle, setXTitle] = useState(initialXTitle);
1277
+ const [yTitle, setYTitle] = useState(initialYTitle);
1278
+ const barSeriesIdsRef = useRef([]);
1279
+ const [barSeriesIds, setBarSeriesIds] = useState([]);
1280
+ const [tooltipPoint, setTooltipPoint] = useState();
1281
+ const xValues = domainState.xValues;
1282
+ const dataBounds = domainState.bounds;
1283
+ const axisKind =
1284
+ domainState.continuousX || arrayIsEmpty(barSeriesIds) ? 'line' : 'bar';
1285
+ const xTicks = getXTicks(axisKind, dataBounds, plotSize, labelSize);
1286
+ const yTicks = getYTicks(dataBounds, plotSize, labelSize);
1287
+ const tickBounds = getTickBounds(dataBounds, xTicks, yTicks);
1288
+ const axisPoints = getScaledPoints(
1289
+ axisKind,
1290
+ xValues.map((xValue, index) => [`${index}`, xValue, 0]),
1291
+ tickBounds,
1292
+ plotSize,
1293
+ xValues,
1110
1294
  );
1111
- const [handleChange, points, bounds, xTicks, yTicks] = useData(
1112
- kind,
1113
- rowIds,
1114
- getPlotSize(layout),
1115
- getLabelSize(layout),
1116
- (rowId) => queries?.getResultCell(queryId, rowId, xCellId),
1117
- (rowId) => queries?.getResultCell(queryId, rowId, yCellId),
1295
+ const setNextDomainState = useCallback((summaryById) => {
1296
+ const nextDomainState = getDomainState(objValues(summaryById));
1297
+ const nextBounds = nextDomainState.bounds;
1298
+ if (
1299
+ !boundsAreEqual(boundsRef.current, nextBounds) ||
1300
+ !arrayIsEqual(domainStateRef.current.xValues, nextDomainState.xValues)
1301
+ ) {
1302
+ boundsRef.current = nextBounds;
1303
+ domainStateRef.current = nextDomainState;
1304
+ setDomainState(nextDomainState);
1305
+ }
1306
+ }, []);
1307
+ const setNextTitles = useCallback((summaryById) => {
1308
+ const nextXTitle = getTitle(summaryById, 'xCellId');
1309
+ const nextYTitle = getTitle(summaryById, 'yCellId');
1310
+ if (xTitleRef.current != nextXTitle) {
1311
+ xTitleRef.current = nextXTitle;
1312
+ setXTitle(nextXTitle);
1313
+ }
1314
+ if (yTitleRef.current != nextYTitle) {
1315
+ yTitleRef.current = nextYTitle;
1316
+ setYTitle(nextYTitle);
1317
+ }
1318
+ }, []);
1319
+ const setIncrementalDomainState = useCallback((summary) => {
1320
+ const currentBounds = boundsRef.current;
1321
+ const nextBounds = [
1322
+ getMin(currentBounds[0], summary.xMin),
1323
+ getMax(currentBounds[1], summary.xMax),
1324
+ getNumberMin(currentBounds[2], summary.yMin),
1325
+ getNumberMax(currentBounds[3], summary.yMax),
1326
+ ];
1327
+ if (!boundsAreEqual(currentBounds, nextBounds)) {
1328
+ boundsRef.current = nextBounds;
1329
+ domainStateRef.current = {
1330
+ bounds: nextBounds,
1331
+ continuousX: domainStateRef.current.continuousX,
1332
+ xValues: domainStateRef.current.xValues,
1333
+ };
1334
+ setDomainState(domainStateRef.current);
1335
+ }
1336
+ }, []);
1337
+ const setSeriesSummary = useCallback(
1338
+ (seriesId, summary) => {
1339
+ const currentSummaries = summariesRef.current;
1340
+ const currentSummary = currentSummaries[seriesId];
1341
+ if (summary == null) {
1342
+ if (currentSummary == null) {
1343
+ return;
1344
+ }
1345
+ delete currentSummaries[seriesId];
1346
+ setNextTitles(currentSummaries);
1347
+ setNextDomainState(currentSummaries);
1348
+ return;
1349
+ }
1350
+ currentSummaries[seriesId] = summary;
1351
+ setNextTitles(currentSummaries);
1352
+ if (
1353
+ currentSummary == null
1354
+ ? addsXValues(summary.xValues, domainStateRef.current.xValues) ||
1355
+ summary.continuousX != domainStateRef.current.continuousX
1356
+ : ownsBound(currentSummary, boundsRef.current) ||
1357
+ currentSummary.continuousX != summary.continuousX ||
1358
+ !arrayIsEqual(currentSummary.xValues, summary.xValues)
1359
+ ) {
1360
+ setNextDomainState(currentSummaries);
1361
+ return;
1362
+ }
1363
+ setIncrementalDomainState(summary);
1364
+ },
1365
+ [setIncrementalDomainState, setNextDomainState, setNextTitles],
1118
1366
  );
1119
- useResultCellListener(
1120
- queryId,
1121
- null,
1122
- xCellId,
1123
- handleChange,
1124
- [handleChange],
1125
- queries,
1367
+ const [getId, releaseId] = pool.current;
1368
+ const getSeriesId = useCallback(() => getId(1), [getId]);
1369
+ const releaseSeriesId = useCallback(
1370
+ (seriesId) => {
1371
+ setSeriesSummary(seriesId, void 0);
1372
+ releaseId(seriesId);
1373
+ },
1374
+ [releaseId, setSeriesSummary],
1126
1375
  );
1127
- useResultCellListener(
1376
+ const registerBarSeries = useCallback((seriesId) => {
1377
+ if (!arrayHas(barSeriesIdsRef.current, seriesId)) {
1378
+ const barSeriesIds2 = [...barSeriesIdsRef.current];
1379
+ arrayPush(barSeriesIds2, seriesId);
1380
+ barSeriesIdsRef.current = barSeriesIds2;
1381
+ setBarSeriesIds(barSeriesIds2);
1382
+ }
1383
+ }, []);
1384
+ const releaseBarSeries = useCallback((seriesId) => {
1385
+ if (arrayHas(barSeriesIdsRef.current, seriesId)) {
1386
+ const barSeriesIds2 = arrayFilter(
1387
+ barSeriesIdsRef.current,
1388
+ (barSeriesId) => barSeriesId != seriesId,
1389
+ );
1390
+ barSeriesIdsRef.current = barSeriesIds2;
1391
+ setBarSeriesIds(barSeriesIds2);
1392
+ }
1393
+ }, []);
1394
+ const getBarSeriesIndex = useCallback(
1395
+ (seriesId) => arrayIndexOf(barSeriesIdsRef.current, seriesId),
1396
+ [],
1397
+ );
1398
+ const context = useMemo(
1399
+ () => ({
1400
+ bounds: tickBounds,
1401
+ barSeriesCount: size(barSeriesIds),
1402
+ domainState,
1403
+ getBarSeriesIndex,
1404
+ getSeriesId,
1405
+ layout,
1406
+ plotFrame,
1407
+ plotSize,
1408
+ queries: queriesObject,
1409
+ queriesOrQueriesId: queries,
1410
+ queryId,
1411
+ registerBarSeries,
1412
+ releaseBarSeries,
1413
+ releaseSeriesId,
1414
+ setSeriesSummary,
1415
+ setTooltipPoint,
1416
+ sourceType,
1417
+ store: storeObject,
1418
+ storeOrStoreId: store,
1419
+ tableId,
1420
+ xTicks,
1421
+ xValues,
1422
+ yTicks,
1423
+ }),
1424
+ [
1425
+ barSeriesIds,
1426
+ domainState,
1427
+ getBarSeriesIndex,
1428
+ getSeriesId,
1429
+ layout,
1430
+ plotFrame,
1431
+ plotSize,
1432
+ queries,
1433
+ queriesObject,
1434
+ queryId,
1435
+ registerBarSeries,
1436
+ releaseBarSeries,
1437
+ releaseSeriesId,
1438
+ setSeriesSummary,
1439
+ sourceType,
1440
+ store,
1441
+ storeObject,
1442
+ tableId,
1443
+ tickBounds,
1444
+ xTicks,
1445
+ xValues,
1446
+ yTicks,
1447
+ ],
1448
+ );
1449
+ return /* @__PURE__ */ jsx(CartesianChartContext.Provider, {
1450
+ value: context,
1451
+ children: /* @__PURE__ */ jsxs('svg', {
1452
+ className,
1453
+ preserveAspectRatio: 'none',
1454
+ ref: svgRef,
1455
+ viewBox: `0 0 ${chartSize[0]} ${chartSize[1]}`,
1456
+ children: [
1457
+ /* @__PURE__ */ jsx(Grid, {
1458
+ bounds: tickBounds,
1459
+ points: axisPoints,
1460
+ plotFrame,
1461
+ tickSize,
1462
+ xTicks,
1463
+ yTicks,
1464
+ }),
1465
+ /* @__PURE__ */ jsx(Axes, {
1466
+ bounds: tickBounds,
1467
+ fontSize,
1468
+ points: axisPoints,
1469
+ plotFrame,
1470
+ tickGap,
1471
+ tickSize,
1472
+ titles: [xTitle, yTitle],
1473
+ xAxisHeight,
1474
+ xTicks,
1475
+ yAxisWidth,
1476
+ yTicks,
1477
+ }),
1478
+ /* @__PURE__ */ jsx('g', {
1479
+ className: 'plot',
1480
+ children: getChartChildren(children),
1481
+ }),
1482
+ /* @__PURE__ */ jsx(Tooltip, {
1483
+ height: plotSize[1],
1484
+ point: tooltipPoint,
1485
+ plotFrame,
1486
+ titles: [xTitle, yTitle],
1487
+ width: plotSize[0],
1488
+ }),
1489
+ ],
1490
+ }),
1491
+ });
1492
+ };
1493
+ const boundsAreEqual = (bounds1, bounds2) =>
1494
+ bounds1[0] === bounds2[0] &&
1495
+ bounds1[1] === bounds2[1] &&
1496
+ bounds1[2] === bounds2[2] &&
1497
+ bounds1[3] === bounds2[3];
1498
+ const ownsBound = (
1499
+ {xMin, xMax, yMin, yMax},
1500
+ [boundXMin, boundXMax, boundYMin, boundYMax],
1501
+ ) =>
1502
+ xMin === boundXMin ||
1503
+ xMax === boundXMax ||
1504
+ yMin === boundYMin ||
1505
+ yMax === boundYMax;
1506
+ const addsXValues = (xValues, currentXValues) => {
1507
+ let adds = false;
1508
+ arrayForEach(xValues, (xValue) => {
1509
+ if (!arrayHas(currentXValues, xValue)) {
1510
+ adds = true;
1511
+ }
1512
+ });
1513
+ return adds;
1514
+ };
1515
+ const getMin = (value1, value2) =>
1516
+ isNumber(value1) && isNumber(value2)
1517
+ ? mathMin(value1, value2)
1518
+ : (value1 ?? value2);
1519
+ const getMax = (value1, value2) =>
1520
+ isNumber(value1) && isNumber(value2)
1521
+ ? mathMax(value1, value2)
1522
+ : (value1 ?? value2);
1523
+ const getNumberMin = (value1, value2) =>
1524
+ value1 == null || value2 == null
1525
+ ? (value1 ?? value2)
1526
+ : mathMin(value1, value2);
1527
+ const getNumberMax = (value1, value2) =>
1528
+ value1 == null || value2 == null
1529
+ ? (value1 ?? value2)
1530
+ : mathMax(value1, value2);
1531
+ const getTitle = (summaryById, cellIdType) => {
1532
+ const titles = [];
1533
+ arrayForEach(objValues(summaryById), (summary) => {
1534
+ const title =
1535
+ cellIdType == 'yCellId'
1536
+ ? (summary.yLabel ?? summary.yCellId)
1537
+ : summary.xCellId;
1538
+ if (title != null && !arrayHas(titles, title)) {
1539
+ arrayPush(titles, title);
1540
+ }
1541
+ });
1542
+ return arrayIsEmpty(titles) ? '' : titles.join(' & ');
1543
+ };
1544
+ const getChartChildren = (children) => {
1545
+ const chartChildren = [];
1546
+ Children.forEach(children, (child) => {
1547
+ if (isValidElement(child)) {
1548
+ if (child.type === Fragment) {
1549
+ arrayForEach(getChartChildren(child.props.children), (chartChild) =>
1550
+ arrayPush(chartChildren, chartChild),
1551
+ );
1552
+ } else if (isChartSeriesComponent(child.type)) {
1553
+ arrayPush(chartChildren, child);
1554
+ }
1555
+ }
1556
+ });
1557
+ return chartChildren;
1558
+ };
1559
+
1560
+ const useInitialSeriesSummary = (
1561
+ kind,
1562
+ {
1563
+ descending,
1564
+ limit,
1565
+ offset,
1566
+ queries,
1128
1567
  queryId,
1129
- null,
1568
+ sortCellId,
1569
+ store,
1570
+ tableId,
1571
+ xCellId,
1130
1572
  yCellId,
1131
- handleChange,
1132
- [handleChange],
1133
- queries,
1134
- );
1135
- return /* @__PURE__ */ jsx(Layout, {
1136
- className,
1573
+ },
1574
+ ) => {
1575
+ const storeObject = useStoreOrStoreById(store);
1576
+ const queriesObject = useQueriesOrQueriesById(queries);
1577
+ return useMemo(() => {
1578
+ const points =
1579
+ tableId == null
1580
+ ? getDataPoints(
1581
+ queriesObject?.getResultSortedRowIds(
1582
+ queryId ?? '',
1583
+ sortCellId ?? xCellId,
1584
+ descending,
1585
+ offset,
1586
+ limit,
1587
+ ) ?? [],
1588
+ (rowId) =>
1589
+ getDataPoint(
1590
+ rowId,
1591
+ queriesObject?.getResultCell(queryId ?? '', rowId, xCellId),
1592
+ queriesObject?.getResultCell(queryId ?? '', rowId, yCellId),
1593
+ ),
1594
+ )
1595
+ : getDataPoints(
1596
+ storeObject?.getSortedRowIds(
1597
+ tableId,
1598
+ sortCellId ?? xCellId,
1599
+ descending,
1600
+ offset,
1601
+ limit,
1602
+ ) ?? [],
1603
+ (rowId) =>
1604
+ getDataPoint(
1605
+ rowId,
1606
+ storeObject?.getCell(tableId, rowId, xCellId),
1607
+ storeObject?.getCell(tableId, rowId, yCellId),
1608
+ ),
1609
+ );
1610
+ return getSeriesSummary(kind, points, xCellId, yCellId);
1611
+ }, [
1612
+ descending,
1137
1613
  kind,
1138
- points,
1139
- bounds,
1140
- titles: [xCellId, yCellId],
1141
- xTicks,
1142
- yTicks,
1143
- layout,
1144
- });
1614
+ limit,
1615
+ offset,
1616
+ queriesObject,
1617
+ queryId,
1618
+ sortCellId,
1619
+ storeObject,
1620
+ tableId,
1621
+ xCellId,
1622
+ yCellId,
1623
+ ]);
1145
1624
  };
1146
1625
 
1147
- const TableChart = ({
1626
+ const BarChart = (props) => {
1627
+ const initialSummary = useInitialSeriesSummary('bar', props);
1628
+ return /* @__PURE__ */ jsx(CartesianChart, {
1629
+ ...getSourceProps$1(props),
1630
+ initialSummary,
1631
+ children: /* @__PURE__ */ jsx(BarSeries, {...getSeriesProps$1(props)}),
1632
+ });
1633
+ };
1634
+ const getSourceProps$1 = (props) =>
1635
+ props.tableId == null
1636
+ ? {
1637
+ className: props.className,
1638
+ queries: props.queries,
1639
+ queryId: props.queryId,
1640
+ }
1641
+ : {className: props.className, store: props.store, tableId: props.tableId};
1642
+ const getSeriesProps$1 = ({
1148
1643
  descending,
1149
- className,
1150
- kind,
1151
1644
  limit,
1152
1645
  offset,
1153
1646
  sortCellId,
1154
- storeOrStoreId,
1155
- tableId,
1156
1647
  xCellId,
1157
1648
  yCellId,
1158
- }) => {
1159
- const layout = useLayout();
1160
- const store = useStoreOrStoreById(storeOrStoreId);
1161
- const rowIds = useSortedRowIds(
1162
- tableId,
1163
- sortCellId ?? xCellId,
1164
- descending,
1165
- offset,
1166
- limit,
1167
- storeOrStoreId,
1168
- );
1169
- const [handleChange, points, bounds, xTicks, yTicks] = useData(
1170
- kind,
1171
- rowIds,
1172
- getPlotSize(layout),
1173
- getLabelSize(layout),
1174
- (rowId) => store?.getCell(tableId, rowId, xCellId),
1175
- (rowId) => store?.getCell(tableId, rowId, yCellId),
1649
+ }) => ({
1650
+ descending,
1651
+ limit,
1652
+ offset,
1653
+ sortCellId,
1654
+ xCellId,
1655
+ yCellId,
1656
+ });
1657
+
1658
+ const Line = ({plotFrame, points, setTooltipPoint}) => {
1659
+ const [plotX, plotY, , height] = plotFrame;
1660
+ return /* @__PURE__ */ jsxs(Fragment$1, {
1661
+ children: [
1662
+ /* @__PURE__ */ jsx('path', {
1663
+ className: 'area',
1664
+ d: getAreaPath(points, plotX, plotY, height),
1665
+ fill: CURRENT_COLOR,
1666
+ fillOpacity: 0.25,
1667
+ stroke: 'none',
1668
+ }),
1669
+ /* @__PURE__ */ jsx('path', {
1670
+ className: 'line',
1671
+ d: getLinePath(points, plotX, plotY),
1672
+ fill: 'none',
1673
+ stroke: CURRENT_COLOR,
1674
+ strokeOpacity: 0.75,
1675
+ strokeWidth: 2,
1676
+ }),
1677
+ /* @__PURE__ */ jsx('g', {
1678
+ className: 'points',
1679
+ fill: CURRENT_COLOR,
1680
+ children: arrayMap(points, (point) => {
1681
+ const [rowId, , , x, y] = point;
1682
+ return /* @__PURE__ */ jsx(
1683
+ 'circle',
1684
+ {
1685
+ cx: plotX + x,
1686
+ cy: plotY + y,
1687
+ onPointerEnter: () => setTooltipPoint(point),
1688
+ onPointerLeave: () => setTooltipPoint(void 0),
1689
+ r: 5,
1690
+ },
1691
+ rowId,
1692
+ );
1693
+ }),
1694
+ }),
1695
+ ],
1696
+ });
1697
+ };
1698
+ const getLinePath = (points, plotX, plotY) =>
1699
+ arrayJoin(
1700
+ arrayMap(
1701
+ points,
1702
+ ([, , , x, y], index) =>
1703
+ `${index == 0 ? 'M' : 'L'}${plotX + x},${plotY + y}`,
1704
+ ),
1705
+ ' ',
1176
1706
  );
1177
- useCellListener(
1178
- tableId,
1179
- null,
1707
+ const getAreaPath = (points, plotX, plotY, height) =>
1708
+ arrayIsEmpty(points)
1709
+ ? ''
1710
+ : `${getLinePath(points, plotX, plotY)} L${plotX + points[size(points) - 1][3]},${plotY + height} L${plotX + points[0][3]},${plotY + height} Z`;
1711
+
1712
+ const LineSeries = (props) => {
1713
+ const {
1714
+ barSeriesCount,
1715
+ bounds,
1716
+ domainState,
1717
+ plotFrame,
1718
+ plotSize,
1719
+ setSeriesSummary,
1720
+ setTooltipPoint,
1721
+ xValues,
1722
+ } = useCartesianChartContext();
1723
+ const {className, label, xCellId, yCellId} = props;
1724
+ const [seriesId, rawPoints] = useSeriesData(props);
1725
+ const points = getScaledPoints(
1726
+ domainState.continuousX || barSeriesCount == 0 ? 'line' : 'bar',
1727
+ rawPoints,
1728
+ bounds,
1729
+ plotSize,
1730
+ xValues,
1180
1731
  xCellId,
1181
- handleChange,
1182
- [handleChange],
1183
- false,
1184
- storeOrStoreId,
1185
- );
1186
- useCellListener(
1187
- tableId,
1188
- null,
1189
- yCellId,
1190
- handleChange,
1191
- [handleChange],
1192
- false,
1193
- storeOrStoreId,
1732
+ label ?? yCellId,
1194
1733
  );
1195
- return /* @__PURE__ */ jsx(Layout, {
1196
- className,
1197
- kind,
1198
- points,
1199
- bounds,
1200
- titles: [xCellId, yCellId],
1201
- xTicks,
1202
- yTicks,
1203
- layout,
1734
+ useLayoutEffect(() => {
1735
+ setSeriesSummary(
1736
+ seriesId,
1737
+ getSeriesSummary('line', rawPoints, xCellId, yCellId, label),
1738
+ );
1739
+ });
1740
+ return /* @__PURE__ */ jsx('g', {
1741
+ className: getSeriesClassName('line-series', className),
1742
+ children: /* @__PURE__ */ jsx(Line, {
1743
+ plotFrame,
1744
+ points,
1745
+ setTooltipPoint,
1746
+ }),
1204
1747
  });
1205
1748
  };
1749
+ LineSeries[CHART_SERIES] = true;
1206
1750
 
1207
- const Chart = ({className, store, tableId, queries, queryId, ...props}) =>
1208
- isUndefined(tableId)
1209
- ? isUndefined(queryId)
1210
- ? /* @__PURE__ */ jsx(EmptyChart, {...props, className})
1211
- : /* @__PURE__ */ jsx(QueryChart, {
1212
- ...props,
1213
- className,
1214
- queriesOrQueriesId: queries,
1215
- queryId,
1216
- })
1217
- : /* @__PURE__ */ jsx(TableChart, {
1218
- ...props,
1219
- className,
1220
- storeOrStoreId: store,
1221
- tableId,
1222
- });
1223
-
1224
- const BarChart = (props) => /* @__PURE__ */ jsx(Chart, {...props, kind: 'bar'});
1225
-
1226
- const LineChart = (props) =>
1227
- /* @__PURE__ */ jsx(Chart, {...props, kind: 'line'});
1751
+ const LineChart = (props) => {
1752
+ const initialSummary = useInitialSeriesSummary('line', props);
1753
+ return /* @__PURE__ */ jsx(CartesianChart, {
1754
+ ...getSourceProps(props),
1755
+ initialSummary,
1756
+ children: /* @__PURE__ */ jsx(LineSeries, {...getSeriesProps(props)}),
1757
+ });
1758
+ };
1759
+ const getSourceProps = (props) =>
1760
+ props.tableId == null
1761
+ ? {
1762
+ className: props.className,
1763
+ queries: props.queries,
1764
+ queryId: props.queryId,
1765
+ }
1766
+ : {className: props.className, store: props.store, tableId: props.tableId};
1767
+ const getSeriesProps = ({
1768
+ descending,
1769
+ limit,
1770
+ offset,
1771
+ sortCellId,
1772
+ xCellId,
1773
+ yCellId,
1774
+ }) => ({
1775
+ descending,
1776
+ limit,
1777
+ offset,
1778
+ sortCellId,
1779
+ xCellId,
1780
+ yCellId,
1781
+ });
1228
1782
 
1229
- export {BarChart, LineChart};
1783
+ export {BarChart, BarSeries, CartesianChart, LineChart, LineSeries};