@indusaction/cms-design-system 0.2.0 → 0.2.1

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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react';
2
- import { Button as Button$1, theme as theme$1, Skeleton as Skeleton$1, Tag as Tag$1, Typography, Card as Card$1, Modal as Modal$1, Breadcrumb, Avatar, Layout, ConfigProvider, Dropdown as Dropdown$1, Tabs as Tabs$1, Input, Pagination, Table as Table$1, Drawer, Result, Grid, Menu, Popconfirm } from 'antd';
1
+ import React, { createContext, useMemo, useState, useRef, useEffect, useCallback, useContext } from 'react';
2
+ import { Button as Button$1, theme as theme$1, Skeleton as Skeleton$1, Tag as Tag$1, Typography, Card as Card$1, Statistic, Modal as Modal$1, Breadcrumb, Avatar, Layout, Alert, ConfigProvider, Dropdown as Dropdown$1, message, notification, Tabs as Tabs$1, Input, Pagination, Table as Table$1, Drawer, Result, Grid, Menu, Popconfirm } from 'antd';
3
3
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
4
  import { createPortal } from 'react-dom';
5
5
 
@@ -727,6 +727,682 @@ var Card = React.forwardRef(
727
727
  }
728
728
  );
729
729
  Card.displayName = "Card";
730
+ var statusColors = {
731
+ primary: colors.brand.primary,
732
+ success: colors.semantic.success,
733
+ warning: colors.semantic.warning,
734
+ error: colors.semantic.error,
735
+ info: colors.semantic.info,
736
+ neutral: colors.neutral.gray600
737
+ };
738
+ var sizeStyles = {
739
+ small: {
740
+ padding: spacing.sm,
741
+ titleSize: fontSize.xs,
742
+ valueSize: fontSize.md,
743
+ iconSize: spacing.xl
744
+ },
745
+ default: {
746
+ minHeight: 120,
747
+ padding: spacing.md,
748
+ titleSize: fontSize.sm,
749
+ valueSize: fontSize.xl,
750
+ iconSize: 40
751
+ },
752
+ large: {
753
+ minHeight: 160,
754
+ padding: spacing.md,
755
+ titleSize: fontSize.md,
756
+ valueSize: fontSize.xxl,
757
+ iconSize: spacing.xxl
758
+ }
759
+ };
760
+ var MetricCard = React.forwardRef(
761
+ ({
762
+ title,
763
+ value,
764
+ description,
765
+ variant = "outlined",
766
+ layout = "vertical",
767
+ size = "default",
768
+ status = "primary",
769
+ color,
770
+ textColor,
771
+ icon,
772
+ prefix,
773
+ suffix,
774
+ precision,
775
+ formatter,
776
+ groupSeparator = ",",
777
+ decimalSeparator = ".",
778
+ loading = false,
779
+ className,
780
+ style
781
+ }, ref) => {
782
+ const isMissingValue = value == null || typeof value === "number" && !Number.isFinite(value);
783
+ const displayValue = isMissingValue ? "\u2014" : value;
784
+ const accent = color ?? statusColors[status];
785
+ const dimensions = sizeStyles[size];
786
+ const isSolid = variant === "solid";
787
+ const isTinted = variant === "tinted";
788
+ const lightPreset = color == null && ["success", "warning", "error"].includes(status);
789
+ const foreground = textColor ?? (isSolid && !lightPreset ? colors.neutral.white : colors.neutral.gray800);
790
+ const tintedBackground = `color-mix(in srgb, ${accent} 12%, ${colors.neutral.white})`;
791
+ const cardBackground = isSolid ? accent : isTinted ? tintedBackground : colors.neutral.white;
792
+ const cardBorder = isTinted ? "none" : `1px solid ${variant === "outlined" ? colors.neutral.gray200 : accent}`;
793
+ const iconBadge = icon ? /* @__PURE__ */ jsx(
794
+ "span",
795
+ {
796
+ "aria-hidden": "true",
797
+ style: {
798
+ display: "inline-flex",
799
+ alignItems: "center",
800
+ justifyContent: "center",
801
+ flexShrink: 0,
802
+ width: dimensions.iconSize,
803
+ height: dimensions.iconSize,
804
+ borderRadius: "50%",
805
+ fontSize: fontSize.lg,
806
+ color: foreground,
807
+ background: isSolid ? "rgba(255, 255, 255, 0.18)" : isTinted ? `color-mix(in srgb, ${accent} 22%, ${colors.neutral.white})` : colors.brand.primaryLight
808
+ },
809
+ children: icon
810
+ }
811
+ ) : null;
812
+ const hasDescription = description != null && description !== false && description !== "";
813
+ return /* @__PURE__ */ jsx(
814
+ Card,
815
+ {
816
+ ref,
817
+ className,
818
+ loading,
819
+ loadingRows: 2,
820
+ "aria-busy": loading,
821
+ styles: {
822
+ body: {
823
+ boxSizing: "border-box",
824
+ padding: dimensions.padding
825
+ }
826
+ },
827
+ style: {
828
+ background: cardBackground,
829
+ border: cardBorder,
830
+ color: foreground,
831
+ minHeight: dimensions.minHeight,
832
+ minWidth: 0,
833
+ ...style
834
+ },
835
+ children: /* @__PURE__ */ jsxs(
836
+ "div",
837
+ {
838
+ style: {
839
+ display: "flex",
840
+ flexDirection: layout === "horizontal" ? "row" : "column",
841
+ gap: spacing.sm,
842
+ minWidth: 0
843
+ },
844
+ children: [
845
+ layout === "horizontal" ? iconBadge : null,
846
+ /* @__PURE__ */ jsxs(
847
+ "div",
848
+ {
849
+ style: {
850
+ display: "flex",
851
+ flexDirection: "column",
852
+ flex: 1,
853
+ minWidth: 0
854
+ },
855
+ children: [
856
+ /* @__PURE__ */ jsx(
857
+ "div",
858
+ {
859
+ style: {
860
+ color: foreground,
861
+ fontSize: dimensions.titleSize,
862
+ fontWeight: 500,
863
+ lineHeight: 1.4,
864
+ overflowWrap: "anywhere"
865
+ },
866
+ children: title
867
+ }
868
+ ),
869
+ /* @__PURE__ */ jsxs(
870
+ "div",
871
+ {
872
+ style: {
873
+ display: "flex",
874
+ alignItems: "flex-end",
875
+ justifyContent: "space-between",
876
+ gap: spacing.sm,
877
+ paddingTop: spacing.xs,
878
+ flexWrap: "wrap"
879
+ },
880
+ children: [
881
+ /* @__PURE__ */ jsx(
882
+ Statistic,
883
+ {
884
+ value: displayValue,
885
+ prefix: isMissingValue ? void 0 : prefix,
886
+ suffix: isMissingValue ? void 0 : suffix,
887
+ precision,
888
+ formatter: isMissingValue ? void 0 : formatter,
889
+ groupSeparator,
890
+ decimalSeparator,
891
+ style: { flex: 1, minWidth: 0 },
892
+ valueStyle: {
893
+ color: foreground,
894
+ fontSize: dimensions.valueSize,
895
+ fontWeight: 600,
896
+ lineHeight: 1.5,
897
+ overflowWrap: "anywhere"
898
+ }
899
+ }
900
+ ),
901
+ layout === "vertical" ? iconBadge : null
902
+ ]
903
+ }
904
+ ),
905
+ hasDescription ? /* @__PURE__ */ jsx(
906
+ "div",
907
+ {
908
+ style: {
909
+ color: foreground,
910
+ marginTop: spacing.xs,
911
+ overflowWrap: "anywhere"
912
+ },
913
+ children: description
914
+ }
915
+ ) : null
916
+ ]
917
+ }
918
+ )
919
+ ]
920
+ }
921
+ )
922
+ }
923
+ );
924
+ }
925
+ );
926
+ MetricCard.displayName = "MetricCard";
927
+ var defaultPalette = [
928
+ colors.brand.primary,
929
+ colors.brand.accent,
930
+ colors.semantic.success,
931
+ colors.semantic.warning,
932
+ colors.semantic.error,
933
+ colors.neutral.gray500
934
+ ];
935
+ var defaultFormatter = (value) => value.toLocaleString("en-IN");
936
+ var truncateLabel = (label, max) => label.length > max ? `${label.slice(0, max - 1)}\u2026` : label;
937
+ function isGroupedData(data) {
938
+ return data.length > 0 && "values" in data[0];
939
+ }
940
+ function ChartLegend({ items }) {
941
+ return /* @__PURE__ */ jsx(
942
+ "div",
943
+ {
944
+ "aria-label": "Chart legend",
945
+ style: { display: "flex", flexWrap: "wrap", gap: spacing.md, marginBottom: spacing.xs },
946
+ children: items.map(({ label, color }) => /* @__PURE__ */ jsxs(
947
+ "span",
948
+ {
949
+ style: { alignItems: "center", color: colors.neutral.gray700, display: "inline-flex", fontSize: fontSize.xs, gap: spacing.xs },
950
+ children: [
951
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { background: color, borderRadius: "50%", height: 8, width: 8 } }),
952
+ label
953
+ ]
954
+ },
955
+ label
956
+ ))
957
+ }
958
+ );
959
+ }
960
+ function ChartGrid({
961
+ padding,
962
+ width,
963
+ chartHeight,
964
+ maxValue,
965
+ formatValue
966
+ }) {
967
+ return /* @__PURE__ */ jsx(Fragment, { children: [0, 0.5, 1].map((ratio) => {
968
+ const y = padding.top + chartHeight * (1 - ratio);
969
+ return /* @__PURE__ */ jsxs("g", { children: [
970
+ /* @__PURE__ */ jsx("line", { x1: padding.left, x2: width - padding.right, y1: y, y2: y, stroke: colors.neutral.gray200 }),
971
+ /* @__PURE__ */ jsx("text", { x: padding.left - 8, y: y + 4, textAnchor: "end", fill: colors.neutral.gray500, fontSize: 11, children: formatValue(Math.round(maxValue * ratio)) })
972
+ ] }, ratio);
973
+ }) });
974
+ }
975
+ function ChartEmptyState({ height }) {
976
+ return /* @__PURE__ */ jsx(
977
+ "div",
978
+ {
979
+ style: { alignItems: "center", color: colors.neutral.gray500, display: "flex", height, justifyContent: "center" },
980
+ children: "No data available"
981
+ }
982
+ );
983
+ }
984
+ function ColumnChart({
985
+ data,
986
+ mode = "basic",
987
+ seriesColors = defaultPalette,
988
+ showLegend = true,
989
+ height = 280,
990
+ color = colors.brand.primary,
991
+ ariaLabel = "Column chart",
992
+ formatValue = defaultFormatter,
993
+ style
994
+ }) {
995
+ if (!data.length) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
996
+ const grouped = isGroupedData(data);
997
+ const activeMode = grouped && mode === "basic" ? "stacked" : mode;
998
+ const W = 640;
999
+ const pad = { top: 28, right: 20, bottom: 48, left: 48 };
1000
+ const cH = height - pad.top - pad.bottom;
1001
+ const cW = W - pad.left - pad.right;
1002
+ let maxVal = 1;
1003
+ let legendKeys = [];
1004
+ let barContent;
1005
+ if (activeMode === "stacked" && grouped) {
1006
+ const gd = data;
1007
+ legendKeys = [...new Set(gd.flatMap((d) => Object.keys(d.values)))];
1008
+ const totals = gd.map((d) => Object.values(d.values).reduce((s, v) => s + v, 0));
1009
+ maxVal = Math.max(...totals, 1);
1010
+ const slotW = cW / gd.length;
1011
+ const bw = Math.min(56, slotW * 0.58);
1012
+ barContent = gd.map((datum, i) => {
1013
+ const x = pad.left + slotW * i + (slotW - bw) / 2;
1014
+ let curY = pad.top + cH;
1015
+ return /* @__PURE__ */ jsxs("g", { children: [
1016
+ /* @__PURE__ */ jsx("title", { children: `${datum.label}: ${formatValue(totals[i])}` }),
1017
+ legendKeys.map((series, sIdx) => {
1018
+ const val = datum.values[series] ?? 0;
1019
+ if (val <= 0) return null;
1020
+ const h = val / maxVal * cH;
1021
+ curY -= h;
1022
+ return /* @__PURE__ */ jsx("rect", { x, y: curY, width: bw, height: h, fill: seriesColors[sIdx % seriesColors.length], children: /* @__PURE__ */ jsx("title", { children: `${datum.label} - ${series}: ${formatValue(val)}` }) }, series);
1023
+ }),
1024
+ /* @__PURE__ */ jsx("text", { x: x + bw / 2, y: curY - 8, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: formatValue(totals[i]) }),
1025
+ /* @__PURE__ */ jsx("text", { x: x + bw / 2, y: height - 18, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 16) })
1026
+ ] }, datum.id ?? datum.label);
1027
+ });
1028
+ } else if (activeMode === "grouped" && grouped) {
1029
+ const gd = data;
1030
+ legendKeys = [...new Set(gd.flatMap((d) => Object.keys(d.values)))];
1031
+ maxVal = Math.max(...gd.flatMap((d) => Object.values(d.values)), 1);
1032
+ const slotW = cW / gd.length;
1033
+ const n = legendKeys.length;
1034
+ const gap = 2;
1035
+ const subW = Math.min(28, (slotW * 0.75 - (n - 1) * gap) / Math.max(n, 1));
1036
+ const grpW = n * subW + (n - 1) * gap;
1037
+ barContent = gd.map((datum, i) => {
1038
+ const gx = pad.left + slotW * i + (slotW - grpW) / 2;
1039
+ return /* @__PURE__ */ jsxs("g", { children: [
1040
+ legendKeys.map((series, sIdx) => {
1041
+ const val = datum.values[series] ?? 0;
1042
+ const h = Math.max(0, val / maxVal * cH);
1043
+ return /* @__PURE__ */ jsxs("g", { children: [
1044
+ /* @__PURE__ */ jsx("title", { children: `${datum.label} - ${series}: ${formatValue(val)}` }),
1045
+ /* @__PURE__ */ jsx("rect", { x: gx + sIdx * (subW + gap), y: pad.top + cH - h, width: subW, height: h, rx: 3, fill: seriesColors[sIdx % seriesColors.length] })
1046
+ ] }, series);
1047
+ }),
1048
+ /* @__PURE__ */ jsx("text", { x: pad.left + slotW * i + slotW / 2, y: height - 18, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 16) })
1049
+ ] }, datum.id ?? datum.label);
1050
+ });
1051
+ } else {
1052
+ const sd = data;
1053
+ maxVal = Math.max(...sd.map((d) => d.value), 1);
1054
+ const slotW = cW / sd.length;
1055
+ const bw = Math.min(56, slotW * 0.58);
1056
+ barContent = sd.map((datum, i) => {
1057
+ const h = Math.max(0, datum.value / maxVal * cH);
1058
+ const x = pad.left + slotW * i + (slotW - bw) / 2;
1059
+ const y = pad.top + cH - h;
1060
+ return /* @__PURE__ */ jsxs("g", { children: [
1061
+ /* @__PURE__ */ jsx("title", { children: `${datum.label}: ${formatValue(datum.value)}` }),
1062
+ /* @__PURE__ */ jsx("rect", { x, y, width: bw, height: h, rx: 4, fill: datum.color ?? color }),
1063
+ /* @__PURE__ */ jsx("text", { x: x + bw / 2, y: y - 8, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: formatValue(datum.value) }),
1064
+ /* @__PURE__ */ jsx("text", { x: x + bw / 2, y: height - 18, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 16) })
1065
+ ] }, datum.id ?? datum.label);
1066
+ });
1067
+ }
1068
+ const hasLegend = showLegend && legendKeys.length > 1;
1069
+ const legendH = hasLegend ? 28 : 0;
1070
+ const svgH = height - legendH;
1071
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height, justifyContent: "flex-end", ...style }, children: [
1072
+ hasLegend && /* @__PURE__ */ jsx(ChartLegend, { items: legendKeys.map((k, i) => ({ label: k, color: seriesColors[i % seriesColors.length] })) }),
1073
+ /* @__PURE__ */ jsxs("svg", { "aria-label": ariaLabel, role: "img", viewBox: `0 0 ${W} ${height}`, style: { display: "block", height: svgH, maxWidth: "100%", width: "100%" }, children: [
1074
+ /* @__PURE__ */ jsx("title", { children: ariaLabel }),
1075
+ /* @__PURE__ */ jsx(ChartGrid, { padding: pad, width: W, chartHeight: cH, maxValue: maxVal, formatValue }),
1076
+ barContent
1077
+ ] })
1078
+ ] });
1079
+ }
1080
+ var defaultPalette2 = [
1081
+ colors.brand.primary,
1082
+ colors.brand.accent,
1083
+ colors.semantic.success,
1084
+ colors.semantic.warning,
1085
+ colors.semantic.error,
1086
+ colors.neutral.gray500
1087
+ ];
1088
+ function BarChart({
1089
+ data,
1090
+ mode = "basic",
1091
+ seriesColors = defaultPalette2,
1092
+ showLegend = true,
1093
+ height = 280,
1094
+ color = colors.brand.primary,
1095
+ ariaLabel = "Bar chart",
1096
+ formatValue = defaultFormatter,
1097
+ style
1098
+ }) {
1099
+ if (!data.length) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
1100
+ const grouped = isGroupedData(data);
1101
+ const activeMode = grouped && mode === "basic" ? "stacked" : mode;
1102
+ const W = 640;
1103
+ const pad = { top: 18, right: 70, bottom: 16, left: 145 };
1104
+ const cH = height - pad.top - pad.bottom;
1105
+ const cW = W - pad.left - pad.right;
1106
+ let maxVal = 1;
1107
+ let legendKeys = [];
1108
+ let rowContent;
1109
+ if (activeMode === "stacked" && grouped) {
1110
+ const gd = data;
1111
+ legendKeys = [...new Set(gd.flatMap((d) => Object.keys(d.values)))];
1112
+ const totals = gd.map((d) => Object.values(d.values).reduce((s, v) => s + v, 0));
1113
+ const maxVal2 = Math.max(...totals, 1);
1114
+ const rowH = cH / gd.length;
1115
+ const bh = Math.min(28, rowH * 0.62);
1116
+ rowContent = gd.map((datum, i) => {
1117
+ const y = pad.top + i * rowH + (rowH - bh) / 2;
1118
+ let curX = pad.left;
1119
+ return /* @__PURE__ */ jsxs("g", { children: [
1120
+ /* @__PURE__ */ jsx("title", { children: `${datum.label}: ${formatValue(totals[i])}` }),
1121
+ /* @__PURE__ */ jsx("text", { x: pad.left - 10, y: y + bh / 2 + 4, textAnchor: "end", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 22) }),
1122
+ /* @__PURE__ */ jsx("rect", { x: pad.left, y, width: cW, height: bh, fill: colors.neutral.gray200, rx: 4 }),
1123
+ legendKeys.map((series, sIdx) => {
1124
+ const val = datum.values[series] ?? 0;
1125
+ if (val <= 0) return null;
1126
+ const w = val / maxVal2 * cW;
1127
+ const segX = curX;
1128
+ curX += w;
1129
+ return /* @__PURE__ */ jsx("rect", { x: segX, y, width: w, height: bh, fill: seriesColors[sIdx % seriesColors.length], children: /* @__PURE__ */ jsx("title", { children: `${datum.label} - ${series}: ${formatValue(val)}` }) }, series);
1130
+ }),
1131
+ /* @__PURE__ */ jsx("text", { x: curX + 8, y: y + bh / 2 + 4, fill: colors.neutral.gray700, fontSize: 11, children: formatValue(totals[i]) })
1132
+ ] }, datum.id ?? datum.label);
1133
+ });
1134
+ } else if (activeMode === "grouped" && grouped) {
1135
+ const gd = data;
1136
+ legendKeys = [...new Set(gd.flatMap((d) => Object.keys(d.values)))];
1137
+ const maxVal2 = Math.max(...gd.flatMap((d) => Object.values(d.values)), 1);
1138
+ const rowH = cH / gd.length;
1139
+ const n = legendKeys.length;
1140
+ const gap = 2;
1141
+ const subH = Math.min(18, (rowH * 0.75 - (n - 1) * gap) / Math.max(n, 1));
1142
+ const grpH = n * subH + (n - 1) * gap;
1143
+ rowContent = gd.map((datum, i) => {
1144
+ const gy = pad.top + i * rowH + (rowH - grpH) / 2;
1145
+ return /* @__PURE__ */ jsxs("g", { children: [
1146
+ /* @__PURE__ */ jsx("text", { x: pad.left - 10, y: gy + grpH / 2 + 4, textAnchor: "end", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 22) }),
1147
+ legendKeys.map((series, sIdx) => {
1148
+ const val = datum.values[series] ?? 0;
1149
+ const bw = val / maxVal2 * cW;
1150
+ const sy = gy + sIdx * (subH + gap);
1151
+ return /* @__PURE__ */ jsxs("g", { children: [
1152
+ /* @__PURE__ */ jsx("title", { children: `${datum.label} - ${series}: ${formatValue(val)}` }),
1153
+ /* @__PURE__ */ jsx("rect", { x: pad.left, y: sy, width: cW, height: subH, fill: colors.neutral.gray200, rx: 2 }),
1154
+ /* @__PURE__ */ jsx("rect", { x: pad.left, y: sy, width: bw, height: subH, fill: seriesColors[sIdx % seriesColors.length], rx: 2 }),
1155
+ /* @__PURE__ */ jsx("text", { x: pad.left + bw + 6, y: sy + subH / 2 + 4, fill: colors.neutral.gray700, fontSize: 10, children: formatValue(val) })
1156
+ ] }, series);
1157
+ })
1158
+ ] }, datum.id ?? datum.label);
1159
+ });
1160
+ } else {
1161
+ const sd = data;
1162
+ maxVal = Math.max(...sd.map((d) => d.value), 1);
1163
+ const rowH = cH / sd.length;
1164
+ const bh = Math.min(28, rowH * 0.62);
1165
+ rowContent = sd.map((datum, i) => {
1166
+ const y = pad.top + i * rowH + (rowH - bh) / 2;
1167
+ const bw = datum.value / maxVal * cW;
1168
+ return /* @__PURE__ */ jsxs("g", { children: [
1169
+ /* @__PURE__ */ jsx("title", { children: `${datum.label}: ${formatValue(datum.value)}` }),
1170
+ /* @__PURE__ */ jsx("text", { x: pad.left - 10, y: y + bh / 2 + 4, textAnchor: "end", fill: colors.neutral.gray700, fontSize: 11, children: truncateLabel(datum.label, 22) }),
1171
+ /* @__PURE__ */ jsx("rect", { x: pad.left, y, width: cW, height: bh, fill: colors.neutral.gray200, rx: 4 }),
1172
+ /* @__PURE__ */ jsx("rect", { x: pad.left, y, width: bw, height: bh, fill: datum.color ?? color, rx: 4 }),
1173
+ /* @__PURE__ */ jsx("text", { x: pad.left + bw + 8, y: y + bh / 2 + 4, fill: colors.neutral.gray700, fontSize: 11, children: formatValue(datum.value) })
1174
+ ] }, datum.id ?? datum.label);
1175
+ });
1176
+ }
1177
+ const hasLegend = showLegend && legendKeys.length > 1;
1178
+ const legendH = hasLegend ? 28 : 0;
1179
+ const svgH = height - legendH;
1180
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height, justifyContent: "flex-end", ...style }, children: [
1181
+ hasLegend && /* @__PURE__ */ jsx("div", { style: { paddingLeft: pad.left }, children: /* @__PURE__ */ jsx(ChartLegend, { items: legendKeys.map((k, i) => ({ label: k, color: seriesColors[i % seriesColors.length] })) }) }),
1182
+ /* @__PURE__ */ jsxs("svg", { "aria-label": ariaLabel, role: "img", viewBox: `0 0 ${W} ${height}`, style: { display: "block", height: svgH, maxWidth: "100%", width: "100%" }, children: [
1183
+ /* @__PURE__ */ jsx("title", { children: ariaLabel }),
1184
+ rowContent
1185
+ ] })
1186
+ ] });
1187
+ }
1188
+ var defaultPalette3 = [
1189
+ colors.brand.primary,
1190
+ colors.brand.accent,
1191
+ colors.semantic.success,
1192
+ colors.semantic.warning,
1193
+ colors.semantic.error,
1194
+ colors.neutral.gray500
1195
+ ];
1196
+ function DonutChart({
1197
+ data,
1198
+ height = 280,
1199
+ centerLabel = "Total",
1200
+ ariaLabel = "Donut chart",
1201
+ showLegend = true,
1202
+ formatValue = defaultFormatter,
1203
+ style
1204
+ }) {
1205
+ const usableData = data.filter(({ value }) => value > 0);
1206
+ const total = usableData.reduce((sum, { value }) => sum + value, 0);
1207
+ if (!total) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
1208
+ const radius = 76;
1209
+ const circumference = 2 * Math.PI * radius;
1210
+ let consumed = 0;
1211
+ return /* @__PURE__ */ jsxs("div", { style: { alignItems: "center", display: "flex", flexWrap: "wrap", gap: spacing.lg, justifyContent: "center", height, minHeight: height, ...style }, children: [
1212
+ /* @__PURE__ */ jsxs("svg", { "aria-label": ariaLabel, role: "img", viewBox: "0 0 220 220", style: { height: Math.min(height, 220), width: Math.min(height, 220) }, children: [
1213
+ /* @__PURE__ */ jsx("title", { children: ariaLabel }),
1214
+ /* @__PURE__ */ jsx("circle", { cx: "110", cy: "110", fill: "none", r: radius, stroke: colors.neutral.gray200, strokeWidth: "30" }),
1215
+ usableData.map((datum, index) => {
1216
+ const segment = datum.value / total * circumference;
1217
+ const offset = -consumed;
1218
+ consumed += segment;
1219
+ return /* @__PURE__ */ jsx(
1220
+ "circle",
1221
+ {
1222
+ cx: "110",
1223
+ cy: "110",
1224
+ fill: "none",
1225
+ r: radius,
1226
+ stroke: datum.color ?? defaultPalette3[index % defaultPalette3.length],
1227
+ strokeDasharray: `${segment} ${circumference - segment}`,
1228
+ strokeDashoffset: offset,
1229
+ strokeWidth: "30",
1230
+ transform: "rotate(-90 110 110)",
1231
+ children: /* @__PURE__ */ jsx("title", { children: `${datum.label}: ${formatValue(datum.value)}` })
1232
+ },
1233
+ datum.id ?? datum.label
1234
+ );
1235
+ }),
1236
+ /* @__PURE__ */ jsx("text", { x: "110", y: "102", textAnchor: "middle", fill: colors.neutral.gray500, fontSize: "13", children: centerLabel }),
1237
+ /* @__PURE__ */ jsx("text", { x: "110", y: "128", textAnchor: "middle", fill: colors.neutral.gray700, fontSize: "22", fontWeight: "600", children: formatValue(total) })
1238
+ ] }),
1239
+ showLegend ? /* @__PURE__ */ jsx("div", { "aria-label": "Chart legend", style: { display: "grid", gap: spacing.xs }, children: usableData.map((datum, index) => /* @__PURE__ */ jsxs("div", { style: { alignItems: "center", display: "flex", gap: spacing.xs }, children: [
1240
+ /* @__PURE__ */ jsx("span", { "aria-hidden": "true", style: { background: datum.color ?? defaultPalette3[index % defaultPalette3.length], borderRadius: "50%", height: 10, width: 10 } }),
1241
+ /* @__PURE__ */ jsxs("span", { style: { color: colors.neutral.gray700, fontSize: fontSize.xs }, children: [
1242
+ datum.label,
1243
+ ": ",
1244
+ formatValue(datum.value)
1245
+ ] })
1246
+ ] }, datum.id ?? datum.label)) }) : null
1247
+ ] });
1248
+ }
1249
+ var defaultPalette4 = [
1250
+ colors.brand.primary,
1251
+ colors.brand.accent,
1252
+ colors.semantic.success,
1253
+ colors.semantic.warning,
1254
+ colors.semantic.error,
1255
+ colors.neutral.gray500
1256
+ ];
1257
+ function createSmoothSplinePath(points) {
1258
+ if (points.length === 0) return "";
1259
+ if (points.length === 1) return `M ${points[0].x} ${points[0].y}`;
1260
+ if (points.length === 2)
1261
+ return `M ${points[0].x} ${points[0].y} L ${points[1].x} ${points[1].y}`;
1262
+ let path = `M ${points[0].x} ${points[0].y}`;
1263
+ const tension = 0.2;
1264
+ for (let i = 0; i < points.length - 1; i++) {
1265
+ const p0 = points[i > 0 ? i - 1 : i];
1266
+ const p1 = points[i];
1267
+ const p2 = points[i + 1];
1268
+ const p3 = points[i + 2 < points.length ? i + 2 : i + 1];
1269
+ const cp1x = p1.x + (p2.x - p0.x) * tension;
1270
+ const cp1y = p1.y + (p2.y - p0.y) * tension;
1271
+ const cp2x = p2.x - (p3.x - p1.x) * tension;
1272
+ const cp2y = p2.y - (p3.y - p1.y) * tension;
1273
+ path += ` C ${cp1x.toFixed(2)} ${cp1y.toFixed(2)}, ${cp2x.toFixed(2)} ${cp2y.toFixed(2)}, ${p2.x.toFixed(2)} ${p2.y.toFixed(2)}`;
1274
+ }
1275
+ return path;
1276
+ }
1277
+ function TimeSeriesChart({
1278
+ data,
1279
+ type = "line",
1280
+ smooth = false,
1281
+ height = 280,
1282
+ colors: seriesColors = defaultPalette4,
1283
+ ariaLabel = "Time series chart",
1284
+ showLegend = true,
1285
+ formatValue = defaultFormatter,
1286
+ formatDate = (date) => date,
1287
+ threshold,
1288
+ thresholdLabel,
1289
+ style
1290
+ }) {
1291
+ if (!data.length) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
1292
+ const W = 640;
1293
+ const pad = { top: 28, right: 20, bottom: 48, left: 48 };
1294
+ const cH = height - pad.top - pad.bottom;
1295
+ const cW = W - pad.left - pad.right;
1296
+ const maxVal = Math.max(...data.map(({ value }) => value), threshold ?? 0, 1);
1297
+ const dates = [...new Set(data.map(({ date }) => date))];
1298
+ const seriesGroups = [...new Map(data.map((d) => [d.series ?? "Value", true])).keys()].map((s) => ({
1299
+ series: s,
1300
+ data: data.filter((d) => (d.series ?? "Value") === s)
1301
+ }));
1302
+ const xFor = (date) => pad.left + (dates.length > 1 ? dates.indexOf(date) / (dates.length - 1) * cW : cW / 2);
1303
+ const yFor = (v) => pad.top + cH - v / maxVal * cH;
1304
+ const bottom = pad.top + cH;
1305
+ const dateIdxs = dates.length <= 6 ? dates.map((_, i) => i) : [0, Math.round((dates.length - 1) / 2), dates.length - 1];
1306
+ const hasLegend = showLegend && seriesGroups.length > 1;
1307
+ const legendH = hasLegend ? 28 : 0;
1308
+ const svgH = height - legendH;
1309
+ return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", height, justifyContent: "flex-end", ...style }, children: [
1310
+ hasLegend && /* @__PURE__ */ jsx(ChartLegend, { items: seriesGroups.map(({ series: s }, i) => ({ label: s, color: seriesColors[i % seriesColors.length] })) }),
1311
+ /* @__PURE__ */ jsxs("svg", { "aria-label": ariaLabel, role: "img", viewBox: `0 0 ${W} ${height}`, style: { display: "block", height: svgH, maxWidth: "100%", width: "100%" }, children: [
1312
+ /* @__PURE__ */ jsx("title", { children: ariaLabel }),
1313
+ /* @__PURE__ */ jsx(ChartGrid, { padding: pad, width: W, chartHeight: cH, maxValue: maxVal, formatValue }),
1314
+ dateIdxs.map((i) => /* @__PURE__ */ jsx("text", { x: xFor(dates[i]), y: height - 18, textAnchor: "middle", fill: colors.neutral.gray700, fontSize: 11, children: formatDate(dates[i]) }, dates[i])),
1315
+ threshold != null && /* @__PURE__ */ jsxs("g", { children: [
1316
+ /* @__PURE__ */ jsx("line", { x1: pad.left, x2: W - pad.right, y1: yFor(threshold), y2: yFor(threshold), stroke: colors.semantic.error, strokeDasharray: "5 4" }),
1317
+ /* @__PURE__ */ jsx("text", { x: W - pad.right, y: yFor(threshold) - 6, textAnchor: "end", fill: colors.semantic.error, fontSize: 11, children: thresholdLabel ?? formatValue(threshold) })
1318
+ ] }),
1319
+ seriesGroups.map(({ series: sName, data: sd }, idx) => {
1320
+ const clr = seriesColors[idx % seriesColors.length];
1321
+ const coords = sd.map((d) => ({ x: xFor(d.date), y: yFor(d.value) }));
1322
+ const first = coords[0];
1323
+ const last = coords[coords.length - 1];
1324
+ let pathD;
1325
+ if (type === "step") {
1326
+ pathD = sd.reduce((p, d, i) => {
1327
+ const x = xFor(d.date), y = yFor(d.value);
1328
+ return i === 0 ? `M ${x} ${y}` : `${p} H ${x} V ${y}`;
1329
+ }, "");
1330
+ } else if (smooth) {
1331
+ pathD = createSmoothSplinePath(coords);
1332
+ } else {
1333
+ pathD = coords.map((c, i) => `${i === 0 ? "M" : "L"} ${c.x} ${c.y}`).join(" ");
1334
+ }
1335
+ return /* @__PURE__ */ jsxs("g", { children: [
1336
+ type === "area" && first && last && /* @__PURE__ */ jsx("path", { d: `${pathD} L ${last.x} ${bottom} L ${first.x} ${bottom} Z`, fill: clr, fillOpacity: 0.14 }),
1337
+ /* @__PURE__ */ jsx("path", { d: pathD, fill: "none", stroke: clr, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "2.5" }),
1338
+ sd.map((d) => /* @__PURE__ */ jsx("circle", { cx: xFor(d.date), cy: yFor(d.value), fill: clr, r: "3", children: /* @__PURE__ */ jsx("title", { children: `${sName}, ${formatDate(d.date)}: ${formatValue(d.value)}` }) }, d.id ?? `${sName}-${d.date}`))
1339
+ ] }, sName);
1340
+ })
1341
+ ] })
1342
+ ] });
1343
+ }
1344
+ var LineChart = TimeSeriesChart;
1345
+ function BulletChart({
1346
+ data,
1347
+ height = 280,
1348
+ ariaLabel = "Bullet chart",
1349
+ formatValue = defaultFormatter,
1350
+ style
1351
+ }) {
1352
+ if (!data.length) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
1353
+ return /* @__PURE__ */ jsx("div", { "aria-label": ariaLabel, role: "img", style: { display: "flex", flexDirection: "column", justifyContent: "center", gap: spacing.md, height, minHeight: height, ...style }, children: data.map((datum) => {
1354
+ const max = datum.max ?? Math.max(datum.value, datum.target, ...datum.ranges ?? [], 1);
1355
+ const ranges = datum.ranges ?? [max * 0.6, max * 0.8, max];
1356
+ return /* @__PURE__ */ jsxs("div", { children: [
1357
+ /* @__PURE__ */ jsxs("div", { style: { color: colors.neutral.gray700, display: "flex", fontSize: fontSize.xs, justifyContent: "space-between", marginBottom: spacing.xxs }, children: [
1358
+ /* @__PURE__ */ jsx("span", { children: datum.label }),
1359
+ /* @__PURE__ */ jsxs("span", { children: [
1360
+ formatValue(datum.value),
1361
+ " / ",
1362
+ formatValue(datum.target)
1363
+ ] })
1364
+ ] }),
1365
+ /* @__PURE__ */ jsxs("div", { style: { background: colors.neutral.gray200, height: 20, overflow: "hidden", position: "relative" }, children: [
1366
+ ranges.map((range, index) => /* @__PURE__ */ jsx("span", { style: { background: ["#F5F5F5", "#E8EBF2", "#D9DFF0"][Math.min(index, 2)], height: "100%", left: index === 0 ? 0 : `${ranges[index - 1] / max * 100}%`, position: "absolute", width: `${(range - (ranges[index - 1] ?? 0)) / max * 100}%` } }, range)),
1367
+ /* @__PURE__ */ jsx("span", { style: { background: colors.brand.primary, height: 8, left: 0, position: "absolute", top: 6, width: `${Math.min(100, datum.value / max * 100)}%` } }),
1368
+ /* @__PURE__ */ jsx("span", { "aria-label": `Target ${formatValue(datum.target)}`, style: { background: colors.neutral.gray700, height: "100%", left: `${Math.min(100, datum.target / max * 100)}%`, position: "absolute", top: 0, width: 2 } })
1369
+ ] })
1370
+ ] }, datum.id ?? datum.label);
1371
+ }) });
1372
+ }
1373
+ function HistogramChart({
1374
+ data,
1375
+ bins = "auto",
1376
+ height = 280,
1377
+ color,
1378
+ ariaLabel = "Histogram",
1379
+ style
1380
+ }) {
1381
+ if (!data.length) return /* @__PURE__ */ jsx(ChartEmptyState, { height });
1382
+ const min = Math.min(...data);
1383
+ const max = Math.max(...data);
1384
+ const binCount = typeof bins === "number" ? Math.max(1, Math.floor(bins)) : Math.max(1, Math.ceil(Math.sqrt(data.length)));
1385
+ const size = max === min ? 1 : (max - min) / binCount;
1386
+ const bucketData = Array.from({ length: binCount }, (_, index) => {
1387
+ const start = min + index * size;
1388
+ const end = index === binCount - 1 ? max : start + size;
1389
+ const count = data.filter(
1390
+ (value) => index === binCount - 1 ? value >= start && value <= end : value >= start && value < end
1391
+ ).length;
1392
+ return { label: `${start.toFixed(0)}\u2013${end.toFixed(0)}`, value: count };
1393
+ });
1394
+ return /* @__PURE__ */ jsx(
1395
+ ColumnChart,
1396
+ {
1397
+ ariaLabel,
1398
+ color,
1399
+ data: bucketData,
1400
+ formatValue: defaultFormatter,
1401
+ height,
1402
+ style
1403
+ }
1404
+ );
1405
+ }
730
1406
  var Modal = ({ children, ...rest }) => {
731
1407
  return /* @__PURE__ */ jsx(Modal$1, { ...rest, children });
732
1408
  };
@@ -805,8 +1481,10 @@ var Header = React.forwardRef(
805
1481
  gap: spacing.lg,
806
1482
  flexWrap: "nowrap",
807
1483
  padding: `${spacing.lg}px ${spacing.xl}px`,
808
- background: colors.neutral.white,
1484
+ background: "transparent",
1485
+ border: "none",
809
1486
  borderBottom: `1px solid ${colors.neutral.gray200}`,
1487
+ boxShadow: "none",
810
1488
  position: sticky ? "sticky" : void 0,
811
1489
  top: sticky ? 0 : void 0,
812
1490
  zIndex: sticky ? 20 : void 0,
@@ -1050,6 +1728,21 @@ function CloseIcon({ size = 14, className, style }) {
1050
1728
  }
1051
1729
  );
1052
1730
  }
1731
+ function DownloadIcon({ size = 14, className, style }) {
1732
+ return /* @__PURE__ */ jsx(
1733
+ "svg",
1734
+ {
1735
+ width: size,
1736
+ height: size,
1737
+ viewBox: "64 64 896 896",
1738
+ fill: "currentColor",
1739
+ "aria-hidden": "true",
1740
+ className,
1741
+ style,
1742
+ children: /* @__PURE__ */ jsx("path", { d: "M505.7 661a8 8 0 0012.6 0l112-122c4.6-5 1-13-5.7-13H544V224c0-4.4-3.6-8-8-8h-48c-4.4 0-8 3.6-8 8v302h-80.6c-6.7 0-10.4 8-5.7 13l112 122zM832 768H192c-17.7 0-32 14.3-32 32v48c0 4.4 3.6 8 8 8h688c4.4 0 8-3.6 8-8v-48c0-17.7-14.3-32-32-32z" })
1743
+ }
1744
+ );
1745
+ }
1053
1746
  var { Sider } = Layout;
1054
1747
  var MOBILE_HEADER = spacing.xxl;
1055
1748
  var LOGO_HEIGHT = spacing.xxl + spacing.md;
@@ -1100,7 +1793,6 @@ function SideNavFooter({
1100
1793
  {
1101
1794
  style: {
1102
1795
  flexShrink: 0,
1103
- borderTop: `1px solid ${colors.neutral.gray200}`,
1104
1796
  padding: collapsed ? spacing.sm : spacing.md,
1105
1797
  display: "flex",
1106
1798
  flexDirection: collapsed ? "column" : "row",
@@ -1221,8 +1913,7 @@ function SideNavPanel({
1221
1913
  flexDirection: collapsed ? "column" : "row",
1222
1914
  alignItems: "center",
1223
1915
  gap: spacing.xs,
1224
- padding: collapsed ? spacing.sm : spacing.md,
1225
- borderBottom: `1px solid ${colors.neutral.gray200}`
1916
+ padding: collapsed ? spacing.sm : spacing.md
1226
1917
  },
1227
1918
  children: [
1228
1919
  /* @__PURE__ */ jsx(
@@ -1424,7 +2115,6 @@ function SideNav({
1424
2115
  justifyContent: "space-between",
1425
2116
  gap: spacing.xs,
1426
2117
  paddingInline: spacing.md,
1427
- borderBottom: `1px solid ${colors.neutral.gray200}`,
1428
2118
  background: colors.neutral.white
1429
2119
  },
1430
2120
  children: [
@@ -1633,7 +2323,111 @@ function UnauthorizedPage({
1633
2323
  );
1634
2324
  }
1635
2325
  UnauthorizedPage.displayName = "UnauthorizedPage";
2326
+ var FILLED_BG = {
2327
+ success: colors.semantic.success,
2328
+ error: colors.semantic.error,
2329
+ warning: colors.semantic.warning,
2330
+ info: colors.brand.primary
2331
+ };
2332
+ var InlineAlert = React.forwardRef(function InlineAlert2({
2333
+ type = "info",
2334
+ showIcon = true,
2335
+ variant = "outlined",
2336
+ style,
2337
+ className,
2338
+ ...rest
2339
+ }, ref) {
2340
+ const isFilled = variant === "filled";
2341
+ const alertStyle = {
2342
+ ...isFilled ? {
2343
+ backgroundColor: FILLED_BG[type],
2344
+ borderColor: FILLED_BG[type],
2345
+ color: colors.neutral.white
2346
+ } : void 0,
2347
+ ...style
2348
+ };
2349
+ const alertElement = /* @__PURE__ */ jsx(
2350
+ Alert,
2351
+ {
2352
+ ref,
2353
+ type,
2354
+ showIcon,
2355
+ style: alertStyle,
2356
+ className: [
2357
+ isFilled ? "cms-alert-filled" : "cms-alert-outlined",
2358
+ className
2359
+ ].filter(Boolean).join(" "),
2360
+ ...rest
2361
+ }
2362
+ );
2363
+ if (isFilled) {
2364
+ return /* @__PURE__ */ jsx(
2365
+ ConfigProvider,
2366
+ {
2367
+ theme: {
2368
+ components: {
2369
+ Alert: {
2370
+ colorText: colors.neutral.white,
2371
+ colorTextHeading: colors.neutral.white,
2372
+ colorIcon: colors.neutral.white,
2373
+ colorIconHover: colors.neutral.gray200
2374
+ }
2375
+ }
2376
+ },
2377
+ children: alertElement
2378
+ }
2379
+ );
2380
+ }
2381
+ return alertElement;
2382
+ });
2383
+ InlineAlert.displayName = "InlineAlert";
2384
+ var NotificationContext = createContext(null);
2385
+ var useNotification = () => {
2386
+ const context = useContext(NotificationContext);
2387
+ if (!context) {
2388
+ throw new Error(
2389
+ "useNotification must be used within a <NotificationProvider>. Wrap your component tree with <NotificationProvider>."
2390
+ );
2391
+ }
2392
+ return context;
2393
+ };
2394
+ var useNotifications = useNotification;
2395
+ var toAntNotifyArgs = (config) => ({
2396
+ ...config,
2397
+ btn: config.actions ?? config.btn
2398
+ });
2399
+ var InternalNotificationProvider = ({
2400
+ children
2401
+ }) => {
2402
+ const [messageApi, messageContextHolder] = message.useMessage();
2403
+ const [notificationApi, notificationContextHolder] = notification.useNotification();
2404
+ const value = useMemo(
2405
+ () => ({
2406
+ toast: messageApi,
2407
+ notify: {
2408
+ ...notificationApi,
2409
+ open: (config) => notificationApi.open(toAntNotifyArgs(config)),
2410
+ success: (config) => notificationApi.success(toAntNotifyArgs(config)),
2411
+ error: (config) => notificationApi.error(toAntNotifyArgs(config)),
2412
+ info: (config) => notificationApi.info(toAntNotifyArgs(config)),
2413
+ warning: (config) => notificationApi.warning(toAntNotifyArgs(config))
2414
+ }
2415
+ }),
2416
+ [messageApi, notificationApi]
2417
+ );
2418
+ return /* @__PURE__ */ jsxs(NotificationContext.Provider, { value, children: [
2419
+ messageContextHolder,
2420
+ notificationContextHolder,
2421
+ children
2422
+ ] });
2423
+ };
2424
+ var NotificationProvider = Object.assign(
2425
+ InternalNotificationProvider,
2426
+ {
2427
+ Alert: InlineAlert
2428
+ }
2429
+ );
1636
2430
 
1637
- export { Button, Card, CloseIcon, CollapseIcon, Dropdown, Header, Link, LogoutIcon, MenuIcon, Modal, NotFoundPage, SideNav, Skeleton, StatusPage, Table, Tabs, Tag, ThemeProvider, UnauthorizedPage, breakpoints, colors, fontSize, indusActionLogo, spacing, theme };
2431
+ export { BarChart, BulletChart, Button, Card, CloseIcon, CollapseIcon, ColumnChart, DonutChart, DownloadIcon, Dropdown, Header, HistogramChart, InlineAlert, LineChart, Link, LogoutIcon, MenuIcon, MetricCard, Modal, NotFoundPage, NotificationProvider, SideNav, Skeleton, StatusPage, Table, Tabs, Tag, ThemeProvider, TimeSeriesChart, UnauthorizedPage, breakpoints, colors, fontSize, indusActionLogo, spacing, theme, useNotification, useNotifications };
1638
2432
  //# sourceMappingURL=index.js.map
1639
2433
  //# sourceMappingURL=index.js.map