nanoplot 0.0.80 → 0.0.81

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 (38) hide show
  1. package/dist/index.css +96 -22
  2. package/dist/src/components/Bars/Bars.d.ts +22 -0
  3. package/dist/src/components/Bars/Bars.js +2 -0
  4. package/dist/src/components/Bars/components/BarsMouse.d.ts +25 -0
  5. package/dist/src/components/Bars/components/BarsMouse.js +12 -0
  6. package/dist/src/components/Bars/components/HorizontalBars.d.ts +5 -1
  7. package/dist/src/components/Bars/components/HorizontalBars.js +32 -15
  8. package/dist/src/components/Bars/components/Rect.js +2 -2
  9. package/dist/src/components/Bars/components/VerticalBars.d.ts +12 -5
  10. package/dist/src/components/Bars/components/VerticalBars.js +25 -10
  11. package/dist/src/components/GradientLegend/GradientLegend.d.ts +1 -5
  12. package/dist/src/components/GradientLegend/GradientLegend.js +19 -18
  13. package/dist/src/components/Heatmap/Heatmap.js +1 -1
  14. package/dist/src/components/Lines/Lines.js +3 -4
  15. package/dist/src/components/Lines/components/LinesMouse.js +5 -5
  16. package/dist/src/components/Lines/components/LinesTooltip.js +3 -3
  17. package/dist/src/components/Pie/Pie.d.ts +2 -1
  18. package/dist/src/components/Pie/Pie.js +45 -23
  19. package/dist/src/components/Pie/components/PieTooltip.js +1 -1
  20. package/dist/src/components/Worldmap/Worldmap.d.ts +9 -5
  21. package/dist/src/components/Worldmap/Worldmap.js +13 -11
  22. package/dist/src/components/Worldmap/components/WorldmapTooltip.js +2 -3
  23. package/dist/src/components/XAxis/XAxis.js +12 -17
  24. package/dist/src/components/YAxis/YAxis.js +4 -1
  25. package/dist/src/hooks/use-mouse-coordinates.d.ts +55 -1
  26. package/dist/src/hooks/use-mouse-coordinates.js +61 -20
  27. package/dist/src/models/domain/domain.d.ts +1 -0
  28. package/dist/src/utils/coordinates/coordinates.js +9 -9
  29. package/dist/src/utils/domain/domain.d.ts +2 -2
  30. package/dist/src/utils/domain/domain.js +4 -4
  31. package/dist/src/utils/domain/utils/date-domain.js +1 -1
  32. package/dist/src/utils/domain/utils/range.d.ts +1 -1
  33. package/dist/src/utils/domain/utils/range.js +9 -1
  34. package/dist/src/utils/gradient/gradient.d.ts +6 -5
  35. package/dist/src/utils/gradient/gradient.js +18 -6
  36. package/dist/src/utils/path/path.js +3 -3
  37. package/dist/tsconfig.typings.tsbuildinfo +1 -1
  38. package/package.json +1 -1
package/dist/index.css CHANGED
@@ -64,10 +64,6 @@
64
64
  bottom: 0px;
65
65
  }
66
66
 
67
- .left-0 {
68
- left: 0px;
69
- }
70
-
71
67
  .left-2 {
72
68
  left: 0.5rem;
73
69
  }
@@ -108,6 +104,10 @@
108
104
  z-index: 10;
109
105
  }
110
106
 
107
+ .z-\[-1\] {
108
+ z-index: -1;
109
+ }
110
+
111
111
  .z-\[2\] {
112
112
  z-index: 2;
113
113
  }
@@ -182,10 +182,6 @@
182
182
  aspect-ratio: 1090/539;
183
183
  }
184
184
 
185
- .aspect-square {
186
- aspect-ratio: 1 / 1;
187
- }
188
-
189
185
  .size-4 {
190
186
  width: 1rem;
191
187
  height: 1rem;
@@ -195,10 +191,6 @@
195
191
  height: 0.5rem;
196
192
  }
197
193
 
198
- .h-\[1\.25em\] {
199
- height: 1.25em;
200
- }
201
-
202
194
  .h-\[14px\] {
203
195
  height: 14px;
204
196
  }
@@ -211,10 +203,6 @@
211
203
  height: 8px;
212
204
  }
213
205
 
214
- .h-auto {
215
- height: auto;
216
- }
217
-
218
206
  .h-full {
219
207
  height: 100%;
220
208
  }
@@ -395,6 +383,14 @@
395
383
  fill: #efefef;
396
384
  }
397
385
 
386
+ .fill-\[url\(\#bar-shadow-light\)\] {
387
+ fill: url(#bar-shadow-light);
388
+ }
389
+
390
+ .fill-\[var\(--worldmap-fill-light\)\] {
391
+ fill: var(--worldmap-fill-light);
392
+ }
393
+
398
394
  .fill-gray-200 {
399
395
  fill: #e5e7eb;
400
396
  }
@@ -581,10 +577,20 @@
581
577
  opacity: 0;
582
578
  }
583
579
 
580
+ .opacity-40 {
581
+ opacity: 0.4;
582
+ }
583
+
584
584
  .opacity-\[0\.8\] {
585
585
  opacity: 0.8;
586
586
  }
587
587
 
588
+ .shadow {
589
+ --tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
590
+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
591
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
592
+ }
593
+
588
594
  .shadow-md {
589
595
  --tw-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
590
596
  --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);
@@ -627,6 +633,10 @@
627
633
  transition-duration: 200ms;
628
634
  }
629
635
 
636
+ .duration-300 {
637
+ transition-duration: 300ms;
638
+ }
639
+
630
640
  .ease-in-out {
631
641
  transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
632
642
  }
@@ -635,6 +645,10 @@
635
645
  will-change: transform;
636
646
  }
637
647
 
648
+ .\@container-\[inline-size\] {
649
+ container-type: inline-size;
650
+ }
651
+
638
652
  .\@container-\[size\] {
639
653
  container-type: size;
640
654
  }
@@ -748,6 +762,10 @@
748
762
  line-height: 1rem;
749
763
  }
750
764
 
765
+ .\[scale\:1\.02\] {
766
+ scale: 1.02;
767
+ }
768
+
751
769
  .\[scale\:1\] {
752
770
  scale: 1;
753
771
  }
@@ -954,12 +972,8 @@
954
972
  inset: calc(-1 * var(--b) - var(--h)) calc(-1 * var(--b)) calc(-1 * var(--b));
955
973
  }
956
974
 
957
- .hover\:stroke-white:hover {
958
- stroke: #fff;
959
- }
960
-
961
- .hover\:stroke-\[1\.2\]:hover {
962
- stroke-width: 1.2;
975
+ .hover\:stroke-\[var\(--worldmap-stroke\)\]:hover {
976
+ stroke: var(--worldmap-stroke);
963
977
  }
964
978
 
965
979
  .hover\:\[fill-opacity\:0\.2\]:hover {
@@ -995,6 +1009,10 @@
995
1009
  .\@\[width\:100ch\]\:\!\[writing-mode\:unset\] {
996
1010
  writing-mode: unset !important;
997
1011
  }
1012
+
1013
+ .\@\[width\:100ch\]\:\[writing-mode\:unset\] {
1014
+ writing-mode: unset;
1015
+ }
998
1016
  }
999
1017
 
1000
1018
  @container (min-width:10ch) {
@@ -1005,6 +1023,10 @@
1005
1023
  .\@\[width\:10ch\]\:\!\[writing-mode\:unset\] {
1006
1024
  writing-mode: unset !important;
1007
1025
  }
1026
+
1027
+ .\@\[width\:10ch\]\:\[writing-mode\:unset\] {
1028
+ writing-mode: unset;
1029
+ }
1008
1030
  }
1009
1031
 
1010
1032
  @container (min-width:10ch) and (min-height:1.25em) {
@@ -1021,6 +1043,10 @@
1021
1043
  .\@\[width\:130ch\]\:\!\[writing-mode\:unset\] {
1022
1044
  writing-mode: unset !important;
1023
1045
  }
1046
+
1047
+ .\@\[width\:130ch\]\:\[writing-mode\:unset\] {
1048
+ writing-mode: unset;
1049
+ }
1024
1050
  }
1025
1051
 
1026
1052
  @container (min-width:15ch) and (min-height:1.25em) {
@@ -1037,6 +1063,10 @@
1037
1063
  .\@\[width\:160ch\]\:\!\[writing-mode\:unset\] {
1038
1064
  writing-mode: unset !important;
1039
1065
  }
1066
+
1067
+ .\@\[width\:160ch\]\:\[writing-mode\:unset\] {
1068
+ writing-mode: unset;
1069
+ }
1040
1070
  }
1041
1071
 
1042
1072
  @container (min-width:190ch) {
@@ -1047,6 +1077,10 @@
1047
1077
  .\@\[width\:190ch\]\:\!\[writing-mode\:unset\] {
1048
1078
  writing-mode: unset !important;
1049
1079
  }
1080
+
1081
+ .\@\[width\:190ch\]\:\[writing-mode\:unset\] {
1082
+ writing-mode: unset;
1083
+ }
1050
1084
  }
1051
1085
 
1052
1086
  @container (min-width:20ch) {
@@ -1057,6 +1091,10 @@
1057
1091
  .\@\[width\:20ch\]\:\!\[writing-mode\:unset\] {
1058
1092
  writing-mode: unset !important;
1059
1093
  }
1094
+
1095
+ .\@\[width\:20ch\]\:\[writing-mode\:unset\] {
1096
+ writing-mode: unset;
1097
+ }
1060
1098
  }
1061
1099
 
1062
1100
  @container (min-width:20ch) and (min-height:1.25em) {
@@ -1079,6 +1117,10 @@
1079
1117
  .\@\[width\:30ch\]\:\!\[writing-mode\:unset\] {
1080
1118
  writing-mode: unset !important;
1081
1119
  }
1120
+
1121
+ .\@\[width\:30ch\]\:\[writing-mode\:unset\] {
1122
+ writing-mode: unset;
1123
+ }
1082
1124
  }
1083
1125
 
1084
1126
  @container (min-width:400px) {
@@ -1095,6 +1137,10 @@
1095
1137
  .\@\[width\:40ch\]\:\!\[writing-mode\:unset\] {
1096
1138
  writing-mode: unset !important;
1097
1139
  }
1140
+
1141
+ .\@\[width\:40ch\]\:\[writing-mode\:unset\] {
1142
+ writing-mode: unset;
1143
+ }
1098
1144
  }
1099
1145
 
1100
1146
  @container (min-width:4ch) and (min-height:1.25em) {
@@ -1111,6 +1157,10 @@
1111
1157
  .\@\[width\:50ch\]\:\!\[writing-mode\:unset\] {
1112
1158
  writing-mode: unset !important;
1113
1159
  }
1160
+
1161
+ .\@\[width\:50ch\]\:\[writing-mode\:unset\] {
1162
+ writing-mode: unset;
1163
+ }
1114
1164
  }
1115
1165
 
1116
1166
  @container (min-width:5ch) and (min-height:1.25em) {
@@ -1127,6 +1177,10 @@
1127
1177
  .\@\[width\:60ch\]\:\!\[writing-mode\:unset\] {
1128
1178
  writing-mode: unset !important;
1129
1179
  }
1180
+
1181
+ .\@\[width\:60ch\]\:\[writing-mode\:unset\] {
1182
+ writing-mode: unset;
1183
+ }
1130
1184
  }
1131
1185
 
1132
1186
  @container (min-width:6ch) and (min-height:1.25em) {
@@ -1143,6 +1197,10 @@
1143
1197
  .\@\[width\:70ch\]\:\!\[writing-mode\:unset\] {
1144
1198
  writing-mode: unset !important;
1145
1199
  }
1200
+
1201
+ .\@\[width\:70ch\]\:\[writing-mode\:unset\] {
1202
+ writing-mode: unset;
1203
+ }
1146
1204
  }
1147
1205
 
1148
1206
  @container (min-width:80ch) {
@@ -1153,6 +1211,10 @@
1153
1211
  .\@\[width\:80ch\]\:\!\[writing-mode\:unset\] {
1154
1212
  writing-mode: unset !important;
1155
1213
  }
1214
+
1215
+ .\@\[width\:80ch\]\:\[writing-mode\:unset\] {
1216
+ writing-mode: unset;
1217
+ }
1156
1218
  }
1157
1219
 
1158
1220
  @container (min-width:8ch) and (min-height:1.25em) {
@@ -1169,6 +1231,10 @@
1169
1231
  .\@\[width\:90ch\]\:\!\[writing-mode\:unset\] {
1170
1232
  writing-mode: unset !important;
1171
1233
  }
1234
+
1235
+ .\@\[width\:90ch\]\:\[writing-mode\:unset\] {
1236
+ writing-mode: unset;
1237
+ }
1172
1238
  }
1173
1239
 
1174
1240
  .dark\:fill-\[\#111111\]:where(.dark, .dark *) {
@@ -1183,6 +1249,14 @@
1183
1249
  fill: #2d2d2d;
1184
1250
  }
1185
1251
 
1252
+ .dark\:fill-\[url\(\#bar-shadow-dark\)\]:where(.dark, .dark *) {
1253
+ fill: url(#bar-shadow-dark);
1254
+ }
1255
+
1256
+ .dark\:fill-\[var\(--worldmap-fill-dark\)\]:where(.dark, .dark *) {
1257
+ fill: var(--worldmap-fill-dark);
1258
+ }
1259
+
1186
1260
  .dark\:fill-dark-priority-100:where(.dark, .dark *) {
1187
1261
  fill: rgb(45, 45, 45);
1188
1262
  }
@@ -11,5 +11,27 @@ type HorizontalProps = {
11
11
  export declare const Bars: {
12
12
  ({ horizontal, ...props }: VerticalProps | HorizontalProps): React.JSX.Element;
13
13
  context(ctx: InternalGraphContext): InternalGraphContext;
14
+ Mouse: ({ onMove, onLeave, onEnter, className }: {
15
+ className?: string;
16
+ onMove?: (mouse: null | {
17
+ coordinates: SVGPoint;
18
+ px: {
19
+ x: number;
20
+ y: number;
21
+ };
22
+ closest: {
23
+ datapoint: {
24
+ x: Date | string | number;
25
+ y: Date | string | number;
26
+ };
27
+ tick: {
28
+ x: string | number | Date;
29
+ y: string | number | Date;
30
+ };
31
+ };
32
+ }, e: React.MouseEvent<SVGSVGElement>) => void;
33
+ onEnter?: (e: React.MouseEvent<SVGSVGElement>) => void;
34
+ onLeave?: (e: React.MouseEvent<SVGSVGElement>) => void;
35
+ }) => React.JSX.Element;
14
36
  };
15
37
  export {};
@@ -13,6 +13,7 @@ import React from "react";
13
13
  import { HorizontalBars } from "./components/HorizontalBars";
14
14
  import { VerticalBars } from "./components/VerticalBars";
15
15
  import { ColorUtils } from "../../utils/color/color";
16
+ import { BarsMouse } from "./components/BarsMouse";
16
17
  export const Bars = (_a) => {
17
18
  var { horizontal } = _a, props = __rest(_a, ["horizontal"]);
18
19
  return horizontal ? React.createElement(HorizontalBars, Object.assign({}, props)) : React.createElement(VerticalBars, Object.assign({}, props));
@@ -20,3 +21,4 @@ export const Bars = (_a) => {
20
21
  Bars.context = (ctx) => {
21
22
  return Object.assign(Object.assign({}, ctx), { colors: ColorUtils.scheme.contrast });
22
23
  };
24
+ Bars.Mouse = BarsMouse;
@@ -0,0 +1,25 @@
1
+ import { MouseEvent } from "react";
2
+ type Props = {
3
+ className?: string;
4
+ onMove?: (mouse: null | {
5
+ coordinates: SVGPoint;
6
+ px: {
7
+ x: number;
8
+ y: number;
9
+ };
10
+ closest: {
11
+ datapoint: {
12
+ x: Date | string | number;
13
+ y: Date | string | number;
14
+ };
15
+ tick: {
16
+ x: string | number | Date;
17
+ y: string | number | Date;
18
+ };
19
+ };
20
+ }, e: MouseEvent<SVGSVGElement>) => void;
21
+ onEnter?: (e: MouseEvent<SVGSVGElement>) => void;
22
+ onLeave?: (e: MouseEvent<SVGSVGElement>) => void;
23
+ };
24
+ export declare const BarsMouse: ({ onMove, onLeave, onEnter, className }: Props) => import("react").JSX.Element;
25
+ export {};
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import { useMouseCoordinates } from "../../../hooks/use-mouse-coordinates";
3
+ import { useRef } from "react";
4
+ import { useGraph, useIsZooming } from "../../../hooks/use-graph/use-graph";
5
+ import { tw } from "../../../utils/cx/cx";
6
+ export const BarsMouse = ({ onMove, onLeave, onEnter, className }) => {
7
+ const ref = useRef(null);
8
+ const isZooming = useIsZooming();
9
+ const { viewbox } = useGraph();
10
+ const mouse = useMouseCoordinates(ref, { x: true, y: true, lazy: true });
11
+ return (React.createElement("svg", { ref: ref, viewBox: `0 0 ${viewbox.x} ${viewbox.y}`, preserveAspectRatio: "none", className: tw("bars-mouse h-full w-full [grid-area:graph] absolute overflow-visible [backface-visibility:hidden]", isZooming && "block overflow-hidden", className), onMouseEnter: onEnter, onMouseLeave: onLeave, onMouseMove: (e) => onMove === null || onMove === void 0 ? void 0 : onMove(mouse, e) }));
12
+ };
@@ -18,8 +18,12 @@ type Props = Omit<React.SVGAttributes<SVGSVGElement>, "onMouseEnter" | "onMouseL
18
18
  */
19
19
  fill?: (segment: Segment) => string;
20
20
  stroke?: (segment: Segment) => string;
21
+ interactions?: {
22
+ y?: number | string | Date;
23
+ shadow?: boolean;
24
+ };
21
25
  onMouseEnter?: (rect: Segment, event: MouseEvent) => void;
22
26
  onMouseLeave?: (event: MouseEvent) => void;
23
27
  };
24
- export declare const HorizontalBars: ({ children, fill, stroke, labels, size, radius, anchor, onMouseEnter, onMouseLeave, className, }: Props) => React.JSX.Element | null;
28
+ export declare const HorizontalBars: ({ children, fill, stroke, labels, size, radius, anchor, interactions, onMouseEnter, onMouseLeave, className, }: Props) => React.JSX.Element | null;
25
29
  export {};
@@ -19,32 +19,49 @@ import { Rect } from "./Rect";
19
19
  import { scale } from "../../../utils/math/math";
20
20
  import { overlay } from "../../Overlay/Overlay";
21
21
  import { ColorUtils } from "../../../utils/color/color";
22
- export const HorizontalBars = ({ children, fill, stroke, labels, size = 50, radius = 0, anchor = 0, onMouseEnter, onMouseLeave, className, }) => {
22
+ import { LinearGradient } from "../../LinearGradient/LinearGradient";
23
+ export const HorizontalBars = ({ children, fill, stroke, labels, size = 50, radius = 0, anchor = 0, interactions, onMouseEnter, onMouseLeave, className, }) => {
23
24
  const context = useGraph();
24
25
  if (!GraphUtils.isXYData(context.data))
25
26
  return null;
26
27
  const xForValue = CoordinatesUtils.xCoordinateFor(context);
28
+ const yForValue = CoordinatesUtils.yCoordinateFor(context);
27
29
  const bars = context.data.flatMap((bar, i) => bar.data.map((xy) => {
28
- var _a, _b, _c, _d, _e;
29
- return (Object.assign(Object.assign({}, bar), { fill: (_c = (_b = (_a = bar.fill) !== null && _a !== void 0 ? _a : bar.stroke) !== null && _b !== void 0 ? _b : context.colors[i]) !== null && _c !== void 0 ? _c : context.colors.at(-1), group: (_e = (_d = bar.group) !== null && _d !== void 0 ? _d : bar.id) !== null && _e !== void 0 ? _e : bar.name, data: xy }));
30
- })); // bars excl segments.
31
- const BAR_WIDTH = Math.floor((context.viewbox.y * (size / 100)) / new Set(bars.map((bar) => `${bar.data.y}|${bar.group}`)).size);
32
- /* dataset is a single array of rect's with x1/x2/y1/y2; rect can be a segment of a bar (grouped) or a bar itself */
33
- const dataset = context.domain.y
34
- .flatMap(({ tick, coordinate }) => {
35
- return Object.entries(ObjectUtils.groupBy(bars.filter((d) => d.data.y === tick), ({ group }) => group)).flatMap(([, barsForGroup], i, groups) => {
36
- const y1 = coordinate + BAR_WIDTH * i - (BAR_WIDTH * Object.keys(groups).length) / 2;
37
- return barsForGroup === null || barsForGroup === void 0 ? void 0 : barsForGroup.map((bar) => {
38
- return Object.assign(Object.assign({}, bar), { x1: xForValue(anchor), x2: xForValue(bar.data.x), y1, y2: y1 + BAR_WIDTH });
39
- }).map((segment, i, segments) => {
40
- const previousX = segments.slice(0, i).reduce((acc, { x2 }) => acc + x2, xForValue(anchor));
41
- return Object.assign(Object.assign({}, segment), { x1: previousX, x2: segment.x2 - previousX ? segment.x2 : segment.x2 + previousX, radius: i === segments.length - 1 ? radius : undefined });
30
+ var _a;
31
+ return (Object.assign(Object.assign({}, bar), { group: (_a = bar.group) !== null && _a !== void 0 ? _a : bar.id, data: xy }));
32
+ }));
33
+ const BAR_HEIGHT = Math.floor(context.viewbox.y / context.domain.y.length / new Set(bars.map((bar) => { var _a; return (_a = bar.group) !== null && _a !== void 0 ? _a : "no-group"; })).size) * (size / 100);
34
+ const yValues = new Set(bars.map((bar) => (bar.data.y instanceof Date ? bar.data.y.getTime() : bar.data.y)));
35
+ const dataset = Array.from(yValues)
36
+ .flatMap((y) => {
37
+ const coordinate = yForValue(y);
38
+ const barsForTick = bars.filter((bar) => (bar.data.y instanceof Date ? bar.data.y.getTime() : bar.data.y) === y);
39
+ return Object.entries(ObjectUtils.groupBy(barsForTick, ({ group }) => group)).flatMap(([, barsForGroup], i, groups) => {
40
+ const y1 = coordinate + BAR_HEIGHT * i - (BAR_HEIGHT * Object.keys(groups).length) / 2;
41
+ return barsForGroup === null || barsForGroup === void 0 ? void 0 : barsForGroup.map((bar) => (Object.assign(Object.assign({}, bar), { x1: xForValue(anchor), x2: xForValue(bar.data.x), y1, y2: y1 + BAR_HEIGHT }))).map((segment, ii, segments) => {
42
+ const isAboveAnchor = Math.min(segment.x1, segment.x2) < xForValue(anchor);
43
+ const prevWidth = segments.slice(0, ii).reduce((acc, { x1, x2 }) => {
44
+ if (isAboveAnchor ? x1 >= xForValue(anchor) : xForValue(anchor) >= x1)
45
+ return acc;
46
+ return isAboveAnchor ? acc + Math.abs(x1 - x2) : acc - Math.abs(x1 - x2);
47
+ }, 0);
48
+ const x1 = segment.x1 - prevWidth;
49
+ const x2 = segment.x2 - prevWidth;
50
+ return Object.assign(Object.assign({}, segment), { x1: Math.max(x1, x2), x2: Math.min(x1, x2), radius: ii === segments.length - 1 ? radius : undefined });
42
51
  });
43
52
  });
44
53
  })
45
54
  .filter((x) => !!x);
46
55
  return (React.createElement(React.Fragment, null,
47
56
  React.createElement("svg", { viewBox: `0 0 ${context.viewbox.x} ${context.viewbox.y}`, className: cx("horizontal-bars [grid-area:graph] h-full w-full", className), preserveAspectRatio: "none" },
57
+ React.createElement(LinearGradient, { gradient: "linear-gradient(to left, rgba(45, 45, 45, 0) 0%, rgba(45, 45, 45, 0.35) 65%, rgba(45, 45, 45, 1) 100%)", id: "bar-shadow-dark" }),
58
+ React.createElement(LinearGradient, { gradient: "linear-gradient(to left, rgba(180, 180, 180, 0) 0%, rgba(180, 180, 180, 0.15) 65%, rgba(180, 180, 180, 0.2) 100%)", id: "bar-shadow-light" }),
59
+ context.domain.y.map(({ coordinate }, i) => {
60
+ const isShadowed = (interactions === null || interactions === void 0 ? void 0 : interactions.shadow) && (interactions === null || interactions === void 0 ? void 0 : interactions.y) && yForValue(interactions.y) === coordinate;
61
+ if (!(interactions === null || interactions === void 0 ? void 0 : interactions.shadow))
62
+ return null;
63
+ return (React.createElement(Rect, { key: i, x1: 0, x2: context.viewbox.x, y2: coordinate + context.viewbox.x / context.domain.x.length / 2, y1: coordinate - context.viewbox.x / context.domain.x.length / 2, stroke: "transparent", className: cx("bars__bar bars__bar--shadow transition-all duration-300 opacity-0 fill-[url(#bar-shadow-light)]", isShadowed && "opacity-1", `dark:fill-[url(#bar-shadow-dark)]`) }));
64
+ }),
48
65
  dataset.map((_a, index) => {
49
66
  var { x1, x2, y1, y2 } = _a, bar = __rest(_a, ["x1", "x2", "y1", "y2"]);
50
67
  const fillColor = fill ? fill(bar) : bar.fill;
@@ -27,12 +27,12 @@ export const Rect = (_a) => {
27
27
  return (React.createElement(React.Fragment, null,
28
28
  isFillGradient && rest.fill && React.createElement(LinearGradient, { id: fillId, gradient: rest.fill }),
29
29
  isGradientStroke && rest.stroke && React.createElement(LinearGradient, { id: strokeId, gradient: rest.stroke }),
30
- React.createElement("path", { id: clipId, d: path, fill: isFillGradient ? `url(#${fillId})` : rest.fill, stroke: isGradientStroke ? `url(#${strokeId})` : rest.stroke }),
30
+ React.createElement("path", { id: clipId, d: path, fill: isFillGradient ? `url(#${fillId})` : rest.fill, stroke: isGradientStroke ? `url(#${strokeId})` : rest.stroke, className: rest.className }),
31
31
  React.createElement("clipPath", { id: clip },
32
32
  React.createElement("use", { xlinkHref: "#" + clipId })),
33
33
  glow && (React.createElement(React.Fragment, null,
34
34
  React.createElement("use", { xlinkHref: `#${glowId}`, filter: "blur(45px)", opacity: 0.5 }),
35
35
  React.createElement("g", { id: glowId },
36
36
  React.createElement("path", { fill: isFillGradient ? `url(#${fillId})` : rest.fill, stroke: "transparent", d: path, vectorEffect: "non-scaling-stroke", className: rest.className, strokeWidth: 5 })))),
37
- isFillMasked ? (React.createElement("rect", Object.assign({}, rest, { x: x1, y: 0, width: x2 - x1, height: "100%", fill: `url(#${fillId})`, clipPath: `url(#${clip})` }))) : (React.createElement("path", Object.assign({}, rest, { fill: isFillGradient ? `url(#${fillId})` : rest.fill, stroke: isGradientStroke ? `url(#${strokeId})` : rest.stroke, d: path, vectorEffect: "non-scaling-stroke", strokeWidth: (_e = rest.strokeWidth) !== null && _e !== void 0 ? _e : 10, className: rest.className, clipPath: `url(#${clip})` })))));
37
+ isFillMasked ? (React.createElement("rect", Object.assign({}, rest, { x: x1, y: 0, width: x2 - x1, height: "100%", fill: `url(#${fillId})`, clipPath: `url(#${clip})`, className: rest.className }))) : (React.createElement("path", Object.assign({}, rest, { fill: isFillGradient ? `url(#${fillId})` : rest.fill, stroke: isGradientStroke ? `url(#${strokeId})` : rest.stroke, d: path, vectorEffect: "non-scaling-stroke", strokeWidth: (_e = rest.strokeWidth) !== null && _e !== void 0 ? _e : 10, clipPath: `url(#${clip})`, className: rest.className })))));
38
38
  };
@@ -4,10 +4,8 @@ type Segment = Simplify<Omit<InternalCartesianDataset[number], "data"> & {
4
4
  data: InternalCartesianDataset[number]["data"][number];
5
5
  }>;
6
6
  type Props = Omit<React.SVGAttributes<SVGSVGElement>, "onMouseEnter" | "onMouseLeave" | "fill" | "stroke"> & {
7
- children?: ReactNode;
8
- loading?: boolean;
9
- glow?: boolean;
10
7
  size?: number;
8
+ glow?: boolean;
11
9
  radius?: number;
12
10
  anchor?: number;
13
11
  labels?: boolean | ((segment: Segment) => string) | {
@@ -15,13 +13,22 @@ type Props = Omit<React.SVGAttributes<SVGSVGElement>, "onMouseEnter" | "onMouseL
15
13
  collision?: boolean;
16
14
  display: (segment: Segment) => string;
17
15
  };
16
+ loading?: boolean;
17
+ children?: ReactNode;
18
18
  /**
19
- * Function that can change the 'fill' for individual segments based on some condition.
19
+ * Function that can change the 'fill' for individual bar segments based on some condition.
20
20
  */
21
21
  fill?: (segment: Segment) => string;
22
+ /**
23
+ * Function that can change the 'stroke' for individual bar segments based on some condition.
24
+ */
22
25
  stroke?: (segment: Segment) => string;
26
+ interactions?: {
27
+ x?: number | string | Date;
28
+ shadow?: boolean;
29
+ };
23
30
  onMouseEnter?: (rect: Segment, event: MouseEvent) => void;
24
31
  onMouseLeave?: (event: MouseEvent) => void;
25
32
  };
26
- export declare const VerticalBars: ({ children, fill, stroke, size, anchor, labels, radius, glow, className, loading, onMouseEnter, onMouseLeave, ...rest }: Props) => React.JSX.Element | null;
33
+ export declare const VerticalBars: ({ children, fill, stroke, size, anchor, labels, radius, glow, className, loading, interactions, onMouseEnter, onMouseLeave, ...rest }: Props) => React.JSX.Element | null;
27
34
  export {};
@@ -20,26 +20,30 @@ import { cx } from "../../../utils/cx/cx";
20
20
  import { scale } from "../../../utils/math/math";
21
21
  import { overlay } from "../../Overlay/Overlay";
22
22
  import { ColorUtils } from "../../../utils/color/color";
23
+ import { LinearGradient } from "../../LinearGradient/LinearGradient";
23
24
  export const VerticalBars = (_a) => {
24
- var { children, fill, stroke, size = 50, anchor = 0, labels, radius = 0, glow, className, loading, onMouseEnter, onMouseLeave } = _a, rest = __rest(_a, ["children", "fill", "stroke", "size", "anchor", "labels", "radius", "glow", "className", "loading", "onMouseEnter", "onMouseLeave"]);
25
+ var { children, fill, stroke, size = 50, anchor = 0, labels, radius = 0, glow, className, loading, interactions, onMouseEnter, onMouseLeave } = _a, rest = __rest(_a, ["children", "fill", "stroke", "size", "anchor", "labels", "radius", "glow", "className", "loading", "interactions", "onMouseEnter", "onMouseLeave"]);
25
26
  const context = useGraph();
27
+ const { interactions: { hovered, pinned }, } = context;
26
28
  if (!GraphUtils.isXYData(context.data))
27
29
  return null;
28
30
  if (loading)
29
31
  return React.createElement(BarsVerticalLoading, null);
30
32
  const yForValue = CoordinatesUtils.yCoordinateFor(context);
33
+ const xForValue = CoordinatesUtils.xCoordinateFor(context);
31
34
  const bars = context.data.flatMap((bar, i) => bar.data.map((xy) => {
32
35
  var _a, _b, _c, _d, _e;
33
36
  return (Object.assign(Object.assign({}, bar), { fill: (_c = (_b = (_a = bar.fill) !== null && _a !== void 0 ? _a : bar.stroke) !== null && _b !== void 0 ? _b : context.colors[i]) !== null && _c !== void 0 ? _c : context.colors.at(-1), group: (_e = (_d = bar.group) !== null && _d !== void 0 ? _d : bar.id) !== null && _e !== void 0 ? _e : bar.name, data: xy }));
34
37
  }));
35
- const BAR_WIDTH = Math.floor((context.viewbox.x * (size / 100)) / new Set(bars.map((bar) => `${bar.data.x}|${bar.group}`)).size);
36
- const dataset = context.domain.x
37
- .flatMap(({ tick, coordinate }) => {
38
- return Object.entries(ObjectUtils.groupBy(bars.filter((d) => d.data.x === tick), ({ group }) => group)).flatMap(([, barsForGroup], i, groups) => {
38
+ const BAR_WIDTH = Math.floor(context.viewbox.x / context.domain.x.length / new Set(bars.map((bar) => { var _a; return (_a = bar.group) !== null && _a !== void 0 ? _a : "no-group"; })).size) * (size / 100); // this divided by number of unique groups?
39
+ const xValues = new Set(bars.map((bar) => (bar.data.x instanceof Date ? bar.data.x.getTime() : bar.data.x)));
40
+ const dataset = Array.from(xValues)
41
+ .flatMap((x) => {
42
+ const coordinate = xForValue(x);
43
+ const barsForTick = bars.filter((bar) => (bar.data.x instanceof Date ? bar.data.x.getTime() : bar.data.x) === x);
44
+ return Object.entries(ObjectUtils.groupBy(barsForTick, ({ group }) => group)).flatMap(([, barsForGroup], i, groups) => {
39
45
  const x1 = coordinate + BAR_WIDTH * i - (BAR_WIDTH * Object.keys(groups).length) / 2;
40
- return barsForGroup === null || barsForGroup === void 0 ? void 0 : barsForGroup.map((bar) => {
41
- return Object.assign(Object.assign({}, bar), { x1, x2: x1 + BAR_WIDTH, y1: yForValue(bar.data.y), y2: yForValue(anchor) });
42
- }).map((segment, ii, segments) => {
46
+ return barsForGroup === null || barsForGroup === void 0 ? void 0 : barsForGroup.map((bar) => (Object.assign(Object.assign({}, bar), { x1, x2: x1 + BAR_WIDTH, y1: yForValue(bar.data.y), y2: yForValue(anchor) }))).map((segment, ii, segments) => {
43
47
  /* this stacks segments in same group */
44
48
  const isAboveAnchor = Math.min(segment.y1, segment.y2) < yForValue(anchor);
45
49
  const prevHeight = segments.slice(0, ii).reduce((acc, { y1, y2 }) => {
@@ -57,11 +61,22 @@ export const VerticalBars = (_a) => {
57
61
  const isBelowAnchor = bars.some((bar) => +bar.data.y < anchor); /* is any bar below the anchor */
58
62
  return (React.createElement(React.Fragment, null,
59
63
  React.createElement("svg", Object.assign({}, rest, { viewBox: `0 0 ${context.viewbox.x} ${context.viewbox.y}`, className: cx("vertical-bars [grid-area:graph] h-full w-full bars", className), preserveAspectRatio: "none" }),
64
+ React.createElement(LinearGradient, { gradient: "linear-gradient(to bottom, rgba(45, 45, 45, 0) 0%, rgba(45, 45, 45, 0.35) 65%, rgba(45, 45, 45, 1) 100%)", id: "bar-shadow-dark" }),
65
+ React.createElement(LinearGradient, { gradient: "linear-gradient(to bottom, rgba(180, 180, 180, 0) 0%, rgba(180, 180, 180, 0.15) 65%, rgba(180, 180, 180, 0.2) 100%)", id: "bar-shadow-light" }),
66
+ context.domain.x.map(({ coordinate }, i) => {
67
+ const isShadowed = (interactions === null || interactions === void 0 ? void 0 : interactions.shadow) && (interactions === null || interactions === void 0 ? void 0 : interactions.x) && xForValue(interactions.x) === coordinate;
68
+ if (!(interactions === null || interactions === void 0 ? void 0 : interactions.shadow))
69
+ return null;
70
+ return (React.createElement(Rect, { key: i, x1: coordinate - context.viewbox.x / context.domain.x.length / 2, x2: coordinate + context.viewbox.x / context.domain.x.length / 2, y2: context.viewbox.y, y1: 0, stroke: "transparent", className: cx("bars__bar bars__bar--shadow transition-all duration-300 opacity-0 fill-[url(#bar-shadow-light)]", isShadowed && "opacity-1", `dark:fill-[url(#bar-shadow-dark)]`) }));
71
+ }),
60
72
  dataset.map((_a, index) => {
61
73
  var { x1, x2, y1, y2 } = _a, bar = __rest(_a, ["x1", "x2", "y1", "y2"]);
74
+ const disabled = Boolean(pinned.concat(hovered).length && !pinned.includes(bar.id) && !hovered.includes(bar.id)) ||
75
+ ((interactions === null || interactions === void 0 ? void 0 : interactions.x) ? xForValue(interactions.x) !== xForValue(bar.data.x) : false);
62
76
  const fillColor = fill ? fill(bar) : bar.fill;
63
77
  const strokeColor = stroke ? stroke(bar) : bar.stroke;
64
- return (React.createElement(Rect, { key: index, x1: x1, x2: x2, y2: y2, y1: y1, fill: fillColor, stroke: strokeColor, radius: bar.radius, glow: glow, onMouseEnter: onMouseEnter ? (event) => onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(bar, event) : undefined, onMouseLeave: onMouseLeave, className: "bars__bar" }));
78
+ return (React.createElement(React.Fragment, { key: index },
79
+ React.createElement(Rect, { key: index, x1: x1, x2: x2, y2: y2, y1: y1, fill: fillColor, stroke: strokeColor, radius: bar.radius, glow: glow, onMouseEnter: onMouseEnter ? (event) => onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(bar, event) : undefined, onMouseLeave: onMouseLeave, className: cx("bars__bar transition-all duration-300", disabled && "opacity-40", onMouseEnter && "cursor-pointer") })));
65
80
  }),
66
81
  isBelowAnchor && (React.createElement("path", { strokeWidth: 2, vectorEffect: "non-scaling-stroke", stroke: "red", className: "stroke-dark-priority-100", d: `M 0 ${yForValue(anchor)} L ${context.viewbox.x} ${yForValue(anchor)}` })),
67
82
  children),
@@ -82,7 +97,7 @@ export const VerticalBars = (_a) => {
82
97
  return (React.createElement(overlay.div, { key: i, className: "bars__label @container-[size] absolute text-center", style: {
83
98
  width,
84
99
  height: Math.abs(height - (position === "above" ? 100 : 0)) + "%",
85
- left: `${scale(bar.x1, context.viewbox.x, 100)}%`,
100
+ left: scale(bar.x1, context.viewbox.x, 100) + "%",
86
101
  top: top,
87
102
  } },
88
103
  React.createElement("div", { className: "h-full w-full relative" },
@@ -4,14 +4,10 @@ type Props = React.HTMLAttributes<HTMLDivElement> & {
4
4
  position: "top" | "bottom";
5
5
  alignment?: "start" | "center" | "end";
6
6
  gradient: `linear-gradient(${string})`;
7
- scalars: number[] | Array<{
8
- tick: number;
9
- percent: number;
10
- }>;
11
7
  labels?: boolean | ((value: string | number | Date) => string);
12
8
  };
13
9
  export declare const GradientLegend: {
14
- ({ position, alignment, gradient, scalars, labels, ...rest }: Props): React.JSX.Element;
10
+ ({ position, alignment, gradient, labels, ...rest }: Props): React.JSX.Element;
15
11
  context(ctx: InternalGraphContext, props: Props): {
16
12
  layout: {
17
13
  rows: string;
@@ -10,33 +10,34 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import React from "react";
13
- import { useGraphColumn } from "../../hooks/use-graph/use-graph";
14
- import { scale } from "../../utils/math/math";
13
+ import { useGraph, useGraphColumn } from "../../hooks/use-graph/use-graph";
15
14
  import { cx } from "../../utils/cx/cx";
15
+ import { GradientUtils } from "../../utils/gradient/gradient";
16
16
  export const GradientLegend = (_a) => {
17
- var { position, alignment = "center", gradient, scalars, labels = true } = _a, rest = __rest(_a, ["position", "alignment", "gradient", "scalars", "labels"]);
17
+ var { position, alignment = "center", gradient, labels = true } = _a, rest = __rest(_a, ["position", "alignment", "gradient", "labels"]);
18
+ const context = useGraph();
18
19
  const column = useGraphColumn().column;
19
- const ticks = scalars.map((tick, i, ticks) => {
20
- if (typeof tick === "number")
21
- return { label: tick, left: scale(i, ticks.length - 1, 100) + "%" };
22
- return { label: tick.tick, left: tick.percent + "%" };
20
+ const css = GradientUtils.deserialize({ gradient, viewbox: context.viewbox });
21
+ const parsed = GradientUtils.parse({ gradient, viewbox: context.viewbox });
22
+ const ticks = parsed.stops.map((stop) => {
23
+ var _a;
24
+ const label = (() => {
25
+ if (!labels)
26
+ return undefined;
27
+ if (typeof labels === "function")
28
+ return labels(stop.value);
29
+ return stop.value;
30
+ })();
31
+ return { left: ((_a = stop.offset) !== null && _a !== void 0 ? _a : 0) * 100 + "%", label };
23
32
  });
24
- // linear-gradient(to right, red 1590, blue 120000);
25
- // gradient`linear-gradient(to right, red 1590, blue ${new Date()})`
26
33
  return (React.createElement("div", Object.assign({}, rest, { className: cx("gradient-legend w-[100%] px-[20px]", alignment === "center" && "mx-auto", alignment === "start" && "mr-auto", alignment === "end" && "ml-auto", rest.className), style: Object.assign({ gridColumn: column }, rest.style) }),
27
34
  React.createElement("div", { className: "relative mb-[40px]" },
28
35
  React.createElement("div", { className: "text-xs text-gray-500" }, "Value \u2192"),
29
- React.createElement("div", { className: "gradient-legend__gradient h-[8px] rounded-sm", style: { background: gradient } }),
36
+ React.createElement("div", { className: "gradient-legend__gradient h-[8px] rounded-sm", style: { background: css } }),
30
37
  React.createElement("div", { className: "gradient-legend__labels relative mx-1" },
31
- React.createElement("div", { className: "flex items-center justify-between" }, ticks.map((tick, i) => (React.createElement("div", { key: i, className: "gradient-legend__tick absolute -translate-x-1/2 top-[100%] flex flex-col items-center", style: { left: tick.left } },
38
+ React.createElement("div", { className: "flex items-center justify-between" }, ticks.map(({ left, label }, i) => (React.createElement("div", { key: i, className: "gradient-legend__tick absolute -translate-x-1/2 top-[100%] flex flex-col items-center", style: { left } },
32
39
  React.createElement("div", { className: "h-2 w-[1px] bg-gray-400" }),
33
- React.createElement("span", { className: "gradient-legend__label text-[10px] text-gray-600 mt-1" }, (() => {
34
- if (!labels)
35
- return null;
36
- if (typeof labels === "function")
37
- return labels(tick.label);
38
- return tick.label;
39
- })())))))))));
40
+ label !== undefined && (React.createElement("span", { className: "gradient-legend__label text-[10px] text-gray-600 mt-1" }, label))))))))));
40
41
  };
41
42
  GradientLegend.context = (ctx, props) => {
42
43
  const rows = (() => {