@grafana/components 0.0.15 → 0.0.17

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 (34) hide show
  1. package/dist/cjs/index.cjs +393 -6
  2. package/dist/cjs/index.cjs.map +1 -1
  3. package/dist/cjs/index.d.cts +142 -3
  4. package/dist/esm/components/ComparisonBadge/ComparisonBadge.styles.js +2 -2
  5. package/dist/esm/components/ComparisonBadge/ComparisonBadge.styles.js.map +1 -1
  6. package/dist/esm/components/ComparisonTooltip/ComparisonTooltip.styles.js +2 -2
  7. package/dist/esm/components/ComparisonTooltip/ComparisonTooltip.styles.js.map +1 -1
  8. package/dist/esm/components/GenericSkeleton/GenericSkeleton.js +14 -0
  9. package/dist/esm/components/GenericSkeleton/GenericSkeleton.js.map +1 -0
  10. package/dist/esm/components/GenericSkeleton/GenericSkeleton.styles.js +47 -0
  11. package/dist/esm/components/GenericSkeleton/GenericSkeleton.styles.js.map +1 -0
  12. package/dist/esm/components/Popover/Popover.styles.js +2 -2
  13. package/dist/esm/components/StackedChart/StackedChart.js +158 -0
  14. package/dist/esm/components/StackedChart/StackedChart.js.map +1 -0
  15. package/dist/esm/components/StackedChart/StackedChart.styles.js +19 -0
  16. package/dist/esm/components/StackedChart/StackedChart.styles.js.map +1 -0
  17. package/dist/esm/components/StackedChart/shared.styles.js +6 -0
  18. package/dist/esm/components/StackedChart/shared.styles.js.map +1 -0
  19. package/dist/esm/components/StackedChartSegment/StackedChartSegment.js +32 -0
  20. package/dist/esm/components/StackedChartSegment/StackedChartSegment.js.map +1 -0
  21. package/dist/esm/components/StackedChartSegment/StackedChartSegment.styles.js +45 -0
  22. package/dist/esm/components/StackedChartSegment/StackedChartSegment.styles.js.map +1 -0
  23. package/dist/esm/components/StackedChartSegmentTooltip/StackedChartSegmentTooltip.js +40 -0
  24. package/dist/esm/components/StackedChartSegmentTooltip/StackedChartSegmentTooltip.js.map +1 -0
  25. package/dist/esm/components/StackedChartSegmentTooltip/StackedChartSegmentTooltip.styles.js +53 -0
  26. package/dist/esm/components/StackedChartSegmentTooltip/StackedChartSegmentTooltip.styles.js.map +1 -0
  27. package/dist/esm/components/StackedChartSkeleton/StackedChartSkeleton.js +11 -0
  28. package/dist/esm/components/StackedChartSkeleton/StackedChartSkeleton.js.map +1 -0
  29. package/dist/esm/components/StackedChartSkeleton/StackedChartSkeleton.styles.js +13 -0
  30. package/dist/esm/components/StackedChartSkeleton/StackedChartSkeleton.styles.js.map +1 -0
  31. package/dist/esm/index.d.ts +142 -3
  32. package/dist/esm/index.js +5 -0
  33. package/dist/esm/index.js.map +1 -1
  34. package/package.json +1 -1
@@ -12,6 +12,12 @@ var css = require('@emotion/css');
12
12
  var designTokens = require('@grafana/design-tokens');
13
13
  var ui = require('@grafana/ui');
14
14
  var react = require('@floating-ui/react');
15
+ var clsx = require('clsx');
16
+
17
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
18
+
19
+ var React__default = /*#__PURE__*/_interopDefaultCompat(React);
20
+ var clsx__default = /*#__PURE__*/_interopDefaultCompat(clsx);
15
21
 
16
22
  class RefreshEvent extends data.BusEventBase {
17
23
  }
@@ -133,7 +139,7 @@ const calculateComparison = (current, baseline) => {
133
139
  };
134
140
  };
135
141
 
136
- const getStyles$1 = () => {
142
+ const getStyles$6 = () => {
137
143
  const {
138
144
  legacy,
139
145
  primitives: { spacing, typography }
@@ -198,7 +204,7 @@ const Popover = React.forwardRef(
198
204
  const [isDelayedOpen, setDelayedOpen] = React.useState(isOpenControlled);
199
205
  const isOpen = isOpenControlled != null ? isOpenControlled : isOpenState;
200
206
  const middleware = getMiddleware({ placement, arrowRef });
201
- const styles = getStyles$1();
207
+ const styles = getStyles$6();
202
208
  const { context, refs, floatingStyles } = react.useFloating({
203
209
  open: isOpen,
204
210
  placement,
@@ -284,7 +290,7 @@ const Popover = React.forwardRef(
284
290
  );
285
291
  Popover.displayName = "Popover";
286
292
 
287
- const getStyles = () => {
293
+ const getStyles$5 = () => {
288
294
  const {
289
295
  legacy,
290
296
  primitives: { spacing, typography }
@@ -352,7 +358,7 @@ const ComparisonTooltip = ({
352
358
  previousIcon = "clock-nine",
353
359
  hideDelay
354
360
  }) => {
355
- const styles = getStyles();
361
+ const styles = getStyles$5();
356
362
  return /* @__PURE__ */ jsxRuntime.jsx(Popover, { trigger, placement, hideDelay, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.wrapper, children: [
357
363
  title && /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.heading, children: title }),
358
364
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.content, children: [
@@ -374,7 +380,7 @@ const ComparisonTooltip = ({
374
380
  ] }) });
375
381
  };
376
382
 
377
- const cssVariables = () => {
383
+ const cssVariables$1 = () => {
378
384
  const { legacy } = designTokens.getDesignTokens({ valueType: "css" });
379
385
  return {
380
386
  dark: {
@@ -531,7 +537,7 @@ const ComparisonBadge = ({
531
537
  ] })
532
538
  ] });
533
539
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
534
- /* @__PURE__ */ jsxRuntime.jsx(designTokens.GlobalCSSVariables, { variables: cssVariables(), defaultColorMode: null }),
540
+ /* @__PURE__ */ jsxRuntime.jsx(designTokens.GlobalCSSVariables, { variables: cssVariables$1(), defaultColorMode: null }),
535
541
  tooltip ? /* @__PURE__ */ jsxRuntime.jsx(
536
542
  ComparisonTooltip,
537
543
  {
@@ -547,12 +553,393 @@ const ComparisonBadge = ({
547
553
  ] });
548
554
  };
549
555
 
556
+ const cssVariables = () => {
557
+ const { legacy } = designTokens.getDesignTokens({ valueType: "css" });
558
+ return {
559
+ dark: {
560
+ "skeleton-gradient-background-color": legacy.palette.whiteBaseOpacity12
561
+ },
562
+ light: {
563
+ "skeleton-gradient-background-color": legacy.palette.blackBaseOpacity12
564
+ }
565
+ };
566
+ };
567
+ const shimmer = css.keyframes({
568
+ "0%": {
569
+ transform: "translateX(-100%);"
570
+ },
571
+ "100%": {
572
+ transform: "translateX(100%);"
573
+ }
574
+ });
575
+ const getStyles$4 = (animationDuration) => {
576
+ return css.css({
577
+ display: "flex",
578
+ width: "100%",
579
+ height: "100%",
580
+ background: "transparent",
581
+ position: "relative",
582
+ overflow: "hidden",
583
+ borderRadius: "5px",
584
+ "&::before": {
585
+ content: "''",
586
+ position: "absolute",
587
+ top: 0,
588
+ left: 0,
589
+ width: "100%",
590
+ height: "100%",
591
+ animation: `${shimmer} ${animationDuration}s ease-in-out infinite`,
592
+ transform: "translateX(-100%)",
593
+ background: "linear-gradient(90deg, transparent, var(--skeleton-gradient-background-color), transparent)"
594
+ }
595
+ });
596
+ };
597
+
598
+ const GenericSkeleton = ({ animationDuration = 2 }) => {
599
+ const styles = getStyles$4(animationDuration);
600
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
601
+ /* @__PURE__ */ jsxRuntime.jsx(designTokens.GlobalCSSVariables, { variables: cssVariables(), defaultColorMode: null }),
602
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles })
603
+ ] });
604
+ };
605
+
606
+ const filterHueRotate = (index) => ({
607
+ filter: `hue-rotate(${index * 10}deg)`
608
+ });
609
+
610
+ const diagonalStripedBackground = ({
611
+ stripeColor,
612
+ stripeWidth = 2,
613
+ gapWidth = 6
614
+ }) => {
615
+ return `repeating-linear-gradient(
616
+ -45deg,
617
+ ${stripeColor},
618
+ ${stripeColor} ${stripeWidth}px,
619
+ transparent ${stripeWidth}px,
620
+ transparent ${gapWidth}px)`;
621
+ };
622
+ const getSegmentStyles = () => css.css({
623
+ display: "flex",
624
+ height: "100%"
625
+ });
626
+ const getStyles$3 = ({
627
+ index,
628
+ state = "default"
629
+ }) => {
630
+ const { legacy } = designTokens.getDesignTokens({ valueType: "css" });
631
+ const hasColor = ["color", "active"].includes(state);
632
+ const backgroundImage = diagonalStripedBackground({
633
+ stripeColor: state === "dimmed" ? legacy.colors.secondary.shade : legacy.colors.secondary.transparent
634
+ });
635
+ return css.css({
636
+ cursor: hasColor ? "pointer" : void 0,
637
+ borderRadius: legacy.borderRadius.sm,
638
+ transitionDuration: "0.2s",
639
+ transitionTimingFunction: "ease-in-out",
640
+ transitionProperty: "background, filter, box-shadow",
641
+ background: hasColor ? legacy.colors.primary.main : legacy.colors.secondary.transparent,
642
+ backgroundImage,
643
+ opacity: state === "dimmed" ? 0.4 : void 0,
644
+ boxShadow: state === "active" ? legacy.boxShadows.z1 : "none",
645
+ ...hasColor ? filterHueRotate(index) : {}
646
+ });
647
+ };
648
+
649
+ const _StackedChartSegment = ({
650
+ categoryId,
651
+ state = "default",
652
+ index,
653
+ value,
654
+ total = 100,
655
+ minValue = 4,
656
+ onMouseOver,
657
+ onMouseOut
658
+ }, ref) => {
659
+ const width = `${Math.max(value / total * 100, minValue)}%`;
660
+ return /* @__PURE__ */ jsxRuntime.jsx(
661
+ "div",
662
+ {
663
+ ref,
664
+ className: clsx__default.default(getStyles$3({ state, index }), getSegmentStyles()),
665
+ onMouseOver: onMouseOver && onMouseOver({ ref, categoryId }),
666
+ onMouseOut: onMouseOut && onMouseOut({ ref, categoryId }),
667
+ style: { width }
668
+ }
669
+ );
670
+ };
671
+ _StackedChartSegment.displayName = "StackedChartSegment";
672
+ const StackedChartSegment = React__default.default.forwardRef(_StackedChartSegment);
673
+
674
+ const getStyles$2 = ({ height }) => {
675
+ const {
676
+ primitives: { spacing }
677
+ } = designTokens.getDesignTokens({ valueType: "css" });
678
+ return {
679
+ container: css.css({
680
+ display: "flex",
681
+ width: "100%",
682
+ height,
683
+ gap: spacing.xxs
684
+ })
685
+ };
686
+ };
687
+
688
+ const getStyles$1 = (index) => {
689
+ const {
690
+ legacy,
691
+ primitives: { spacing, typography }
692
+ } = designTokens.getDesignTokens({ valueType: "css" });
693
+ return {
694
+ wrapper: css.css({
695
+ display: "flex",
696
+ flexDirection: "column",
697
+ gap: spacing.xs
698
+ }),
699
+ content: css.css({
700
+ display: "flex",
701
+ gap: spacing.xs
702
+ }),
703
+ section: css.css({
704
+ display: "flex",
705
+ flex: 1,
706
+ flexDirection: "column",
707
+ justifyContent: "flex-end",
708
+ gap: spacing.xs,
709
+ background: legacy.colors.background.primary,
710
+ borderRadius: legacy.borderRadius.md,
711
+ padding: `${spacing.sm} ${spacing.md}`
712
+ }),
713
+ title: css.css({
714
+ fontFamily: typography.fontFamily.ui,
715
+ fontSize: typography.fontSize.ui.sm,
716
+ fontWeight: typography.fontWeight.medium,
717
+ // TODO: this should come from a token!
718
+ lineHeight: "16px",
719
+ color: legacy.colors.text.primary,
720
+ whiteSpace: "nowrap"
721
+ }),
722
+ value: css.css({
723
+ // TODO: this should come from a token!
724
+ lineHeight: "16px",
725
+ color: legacy.colors.text.secondary
726
+ }),
727
+ color: css.css({
728
+ color: legacy.colors.primary.main,
729
+ fill: "currentColor",
730
+ ...filterHueRotate(index)
731
+ })
732
+ };
733
+ };
734
+
735
+ const defaultContentFormatter = ({ value, colorClassName }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
736
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: colorClassName, children: [
737
+ value.toFixed(1),
738
+ "%"
739
+ ] }),
740
+ " of total usage"
741
+ ] });
742
+ const StackedChartSegmentTooltip = ({
743
+ trigger,
744
+ placement = "top",
745
+ hideDelay,
746
+ title,
747
+ value,
748
+ total = 100,
749
+ index,
750
+ formatContent = defaultContentFormatter,
751
+ virtualElement
752
+ }) => {
753
+ const styles = getStyles$1(index);
754
+ return /* @__PURE__ */ jsxRuntime.jsx(
755
+ Popover,
756
+ {
757
+ trigger,
758
+ placement,
759
+ hideDelay,
760
+ virtualElement,
761
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.wrapper, children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.content, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: styles.section, children: [
762
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.title, children: title }),
763
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.value, children: formatContent({ value, total, index, colorClassName: styles.color }) })
764
+ ] }) }) })
765
+ }
766
+ );
767
+ };
768
+
769
+ const getStyles = (height) => {
770
+ return css.css({
771
+ width: "100%",
772
+ height: `${height}px`,
773
+ borderRadius: "4px",
774
+ overflow: "hidden"
775
+ });
776
+ };
777
+
778
+ const StackedChartSkeleton = ({ height = 24 }) => {
779
+ const styles = getStyles(height);
780
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles, children: /* @__PURE__ */ jsxRuntime.jsx(GenericSkeleton, {}) });
781
+ };
782
+
783
+ const StackedChart = ({
784
+ categories: _categories,
785
+ highlightedCategoryId: initialHighlightedCategoryId,
786
+ isSkeleton = false,
787
+ isDimmed = false,
788
+ sortOrder = "largest-first",
789
+ height = 24,
790
+ onSegmentMouseOver,
791
+ onSegmentMouseOut
792
+ }) => {
793
+ if (isSkeleton || !_categories) return /* @__PURE__ */ jsxRuntime.jsx(StackedChartSkeleton, { height });
794
+ let highlightedSegmentRef = React.useRef(null);
795
+ const [highlightedCategoryId, setHighlightedCategoryId] = React.useState(
796
+ /**
797
+ * Using a type assertion here ultimately because you can’t pass a generic
798
+ * type argument to the type of props in React.forwardRef (it is inferred as
799
+ * of type string).
800
+ *
801
+ * See: https://stackoverflow.com/questions/51884498/using-react-forwardref-with-typescript-generic-jsx-arguments
802
+ */
803
+ initialHighlightedCategoryId
804
+ );
805
+ const [isHovered, setHovered] = React.useState(false);
806
+ const timer = React.useRef(void 0);
807
+ const categories = React.useMemo(() => {
808
+ switch (sortOrder) {
809
+ case "largest-first":
810
+ case "smallest-first":
811
+ default:
812
+ return _categories;
813
+ }
814
+ }, [_categories, sortOrder]);
815
+ const total = React.useMemo(() => {
816
+ const roundedTotal = Math.round(
817
+ Object.entries(categories).reduce(
818
+ (sum, [, category]) => sum + category.value,
819
+ 0
820
+ )
821
+ );
822
+ if (roundedTotal > 100) {
823
+ console.error(`StackedChartCategories have a total value exceeding 100% (${roundedTotal})`);
824
+ } else {
825
+ console.info(`Total of all category value values is ${roundedTotal}`);
826
+ }
827
+ return roundedTotal;
828
+ }, [categories]);
829
+ const styles = getStyles$2({ height });
830
+ const onMouseOver = ({ ref, categoryId }) => () => {
831
+ clearTimeout(timer.current);
832
+ setHovered(true);
833
+ if (!initialHighlightedCategoryId) {
834
+ setHighlightedCategoryId(categoryId);
835
+ }
836
+ if (onSegmentMouseOver) onSegmentMouseOver({ ref, categoryId });
837
+ };
838
+ const onMouseOut = ({ ref, categoryId }) => () => {
839
+ timer.current = window.setTimeout(() => {
840
+ setHovered(false);
841
+ if (!initialHighlightedCategoryId) {
842
+ setHighlightedCategoryId(void 0);
843
+ }
844
+ }, 50);
845
+ if (onSegmentMouseOut) onSegmentMouseOut({ ref, categoryId });
846
+ };
847
+ const highlightedCategory = initialHighlightedCategoryId ? {
848
+ ...categories[initialHighlightedCategoryId],
849
+ index: Object.keys(categories).indexOf(initialHighlightedCategoryId)
850
+ } : void 0;
851
+ const content = /* @__PURE__ */ jsxRuntime.jsx("div", { className: styles.container, children: Object.entries(categories).map(
852
+ ([categoryId, category], categoryIndex) => {
853
+ const ref = React.useRef(null);
854
+ if (categoryId === initialHighlightedCategoryId) highlightedSegmentRef = ref;
855
+ const segmentState = (() => {
856
+ switch (true) {
857
+ /**
858
+ * If no initial highlighted category was set, and a category is
859
+ * moused over, use the _active_ state for that category rather
860
+ * than the color state; this adds a drop shadow to the segment.
861
+ * Also, if an initial highlighted category _was_ set, and it
862
+ * receives a hover event, also set it to active.
863
+ */
864
+ case (!initialHighlightedCategoryId && highlightedCategoryId === categoryId && !isDimmed):
865
+ case (initialHighlightedCategoryId === categoryId && isHovered && !isDimmed):
866
+ return "active";
867
+ /**
868
+ * - no initial highlighted category ID was passed _and_ there is
869
+ * no highlightedCategoryId (i.e. all segments in colour)
870
+ * - the highlighted category is this category (but the chart
871
+ * isn’t dimmed)
872
+ * - the initial highlighted category is this category (but the
873
+ * chart isn’t dimmed)
874
+ */
875
+ case (!initialHighlightedCategoryId && !highlightedCategoryId && !isDimmed):
876
+ case (initialHighlightedCategoryId === categoryId && !isDimmed):
877
+ return "color";
878
+ /**
879
+ * Has an initial highlighted category, but is dimmed (i.e. all
880
+ * segments excepted the highlighted category)
881
+ */
882
+ case (Boolean(initialHighlightedCategoryId) && initialHighlightedCategoryId !== categoryId && isDimmed):
883
+ case (!initialHighlightedCategoryId && !highlightedCategoryId && isDimmed):
884
+ case (highlightedCategoryId !== categoryId && isDimmed):
885
+ return "dimmed";
886
+ /**
887
+ * In any other case, the segment should be the default grey
888
+ */
889
+ default:
890
+ return "default";
891
+ }
892
+ })();
893
+ const segment = /* @__PURE__ */ jsxRuntime.jsx(
894
+ StackedChartSegment,
895
+ {
896
+ ref,
897
+ categoryId,
898
+ index: categoryIndex,
899
+ title: category.title,
900
+ value: category.value,
901
+ total,
902
+ state: segmentState,
903
+ onMouseOver,
904
+ onMouseOut
905
+ },
906
+ categoryId
907
+ );
908
+ return initialHighlightedCategoryId ? segment : /* @__PURE__ */ jsxRuntime.jsx(
909
+ StackedChartSegmentTooltip,
910
+ {
911
+ title: category.title,
912
+ value: category.value,
913
+ index: categoryIndex,
914
+ hideDelay: 0,
915
+ trigger: segment
916
+ },
917
+ categoryId
918
+ );
919
+ }
920
+ ) });
921
+ return initialHighlightedCategoryId && highlightedCategory ? /* @__PURE__ */ jsxRuntime.jsx(
922
+ StackedChartSegmentTooltip,
923
+ {
924
+ hideDelay: 0,
925
+ trigger: content,
926
+ virtualElement: highlightedSegmentRef,
927
+ ...highlightedCategory
928
+ }
929
+ ) : content;
930
+ };
931
+
550
932
  exports.ColorMode = ColorMode;
551
933
  exports.ColorModeChangeHandler = ColorModeChangeHandler;
552
934
  exports.ColorModeProvider = ColorModeProvider;
553
935
  exports.ComparisonBadge = ComparisonBadge;
554
936
  exports.ComparisonTooltip = ComparisonTooltip;
937
+ exports.GenericSkeleton = GenericSkeleton;
555
938
  exports.Popover = Popover;
939
+ exports.StackedChart = StackedChart;
940
+ exports.StackedChartSegment = StackedChartSegment;
941
+ exports.StackedChartSegmentTooltip = StackedChartSegmentTooltip;
942
+ exports.StackedChartSkeleton = StackedChartSkeleton;
556
943
  exports.calculateComparison = calculateComparison;
557
944
  exports.formatNumber = formatNumber;
558
945
  exports.useColorMode = useColorMode;