@adsgency_npm/adsgency-ads-ui 0.1.0-alpha.33 → 0.1.0-alpha.35

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.cjs CHANGED
@@ -6118,9 +6118,7 @@ function LineChartTooltipContent({
6118
6118
  tooltipLabelFormatter,
6119
6119
  tooltipValueFormatter
6120
6120
  }) {
6121
- if (!active || !payload.length) {
6122
- return null;
6123
- }
6121
+ if (!active || !payload.length) return null;
6124
6122
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
6125
6123
  "div",
6126
6124
  {
@@ -6132,15 +6130,30 @@ function LineChartTooltipContent({
6132
6130
  children: [
6133
6131
  tooltipLabelFormatter && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: tooltipLabelFormatter(label) }),
6134
6132
  /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "space-y-1.5", children: series.map((item, index) => {
6135
- const entry = payload.find((payloadItem) => payloadItem.dataKey === item.dataKey);
6133
+ const entry = payload.find(
6134
+ (payloadItem) => payloadItem.dataKey === item.dataKey
6135
+ );
6136
6136
  const value = typeof entry?.value === "number" && Number.isFinite(entry.value) ? entry.value : 0;
6137
6137
  const color = getSeriesColor(item, index);
6138
- const displayLabel = item.label ?? item.dataKey;
6139
- return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex items-center gap-1.5 text-sm", children: [
6140
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { "aria-hidden": "true", className: "size-2 rounded-full", style: { backgroundColor: color } }),
6141
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "text-muted-foreground", children: displayLabel }),
6142
- /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "font-semibold text-popover-foreground", children: tooltipValueFormatter ? tooltipValueFormatter(value, item) : value })
6143
- ] }, item.dataKey);
6138
+ return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
6139
+ "div",
6140
+ {
6141
+ className: "flex items-center gap-1.5 text-sm",
6142
+ children: [
6143
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6144
+ "span",
6145
+ {
6146
+ "aria-hidden": "true",
6147
+ className: "size-2 rounded-full",
6148
+ style: { backgroundColor: color }
6149
+ }
6150
+ ),
6151
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "text-muted-foreground", children: item.label ?? item.dataKey }),
6152
+ /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "font-semibold text-popover-foreground", children: tooltipValueFormatter ? tooltipValueFormatter(value, item) : value })
6153
+ ]
6154
+ },
6155
+ item.dataKey
6156
+ );
6144
6157
  }) }),
6145
6158
  tooltipFooter && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("p", { className: "mt-2 text-xs font-bold leading-[1.4]", children: tooltipFooter })
6146
6159
  ]
@@ -6150,8 +6163,8 @@ function LineChartTooltipContent({
6150
6163
  function AdsLineChart({
6151
6164
  ariaLabel,
6152
6165
  chartProps,
6153
- className,
6154
6166
  children,
6167
+ className,
6155
6168
  containerProps,
6156
6169
  curve = "linear",
6157
6170
  data,
@@ -6175,29 +6188,47 @@ function AdsLineChart({
6175
6188
  yAxisProps
6176
6189
  }) {
6177
6190
  const [activeDataKey, setActiveDataKey] = React48.useState(null);
6191
+ const chartElementRef = React48.useRef(null);
6192
+ const previousDataRef = React48.useRef(data);
6178
6193
  const hoverHighlightDataKey = series.find((item) => item.activeColor)?.dataKey ?? null;
6179
- const chartData = data.map((datum) => {
6180
- const safeDatum = { ...datum, [xKey]: datum[xKey] };
6181
- series.forEach((item) => {
6182
- safeDatum[item.dataKey] = getSafeValue(datum[item.dataKey]);
6183
- });
6184
- return safeDatum;
6185
- });
6186
- const safeHeight = getSafeHeight(height);
6187
- const chartConfig = getChartConfig(series);
6194
+ const chartData = React48.useMemo(
6195
+ () => data.map((datum) => {
6196
+ const safeDatum = { ...datum, [xKey]: datum[xKey] };
6197
+ series.forEach((item) => {
6198
+ safeDatum[item.dataKey] = getSafeValue(datum[item.dataKey]);
6199
+ });
6200
+ return safeDatum;
6201
+ }),
6202
+ [data, series, xKey]
6203
+ );
6204
+ const chartConfig = React48.useMemo(() => getChartConfig(series), [series]);
6188
6205
  const {
6189
6206
  cursor: tooltipCursor,
6190
6207
  wrapperStyle: tooltipWrapperStyle,
6191
6208
  ...restTooltipProps
6192
6209
  } = tooltipProps ?? {};
6210
+ React48.useEffect(() => {
6211
+ if (previousDataRef.current === data) {
6212
+ return;
6213
+ }
6214
+ previousDataRef.current = data;
6215
+ chartElementRef.current?.animate?.(
6216
+ [
6217
+ { opacity: 0.72, transform: "translateY(4px)" },
6218
+ { opacity: 1, transform: "translateY(0)" }
6219
+ ],
6220
+ { duration: 360, easing: "ease-out" }
6221
+ );
6222
+ }, [data]);
6193
6223
  return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6194
6224
  "div",
6195
6225
  {
6196
6226
  "aria-label": ariaLabel ?? "Line chart",
6197
6227
  className: cn("w-full", className),
6198
6228
  "data-testid": "ads-line-chart",
6229
+ ref: chartElementRef,
6199
6230
  role: "img",
6200
- style: { height: safeHeight },
6231
+ style: { height: getSafeHeight(height) },
6201
6232
  children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
6202
6233
  ChartContainer,
6203
6234
  {
@@ -6296,12 +6327,12 @@ function AdsLineChart({
6296
6327
  import_recharts3.Area,
6297
6328
  {
6298
6329
  ...item.areaProps,
6330
+ animationDuration: item.areaProps?.animationDuration ?? 360,
6331
+ animationEasing: item.areaProps?.animationEasing ?? "ease-out",
6299
6332
  dataKey: item.dataKey,
6300
6333
  fill: item.areaProps?.fill ?? color,
6301
6334
  fillOpacity: item.areaProps?.fillOpacity ?? opacity,
6302
- animationDuration: item.areaProps?.animationDuration ?? 360,
6303
- animationEasing: item.areaProps?.animationEasing ?? "ease-out",
6304
- isAnimationActive: item.areaProps?.isAnimationActive ?? true,
6335
+ isAnimationActive: item.areaProps?.isAnimationActive ?? false,
6305
6336
  stroke: item.areaProps?.stroke ?? "none",
6306
6337
  type: item.areaProps?.type ?? curve
6307
6338
  }
@@ -6315,7 +6346,7 @@ function AdsLineChart({
6315
6346
  animationEasing: item.lineProps?.animationEasing ?? "ease-out",
6316
6347
  dataKey: item.dataKey,
6317
6348
  dot: item.lineProps?.dot ?? false,
6318
- isAnimationActive: item.lineProps?.isAnimationActive ?? true,
6349
+ isAnimationActive: item.lineProps?.isAnimationActive ?? false,
6319
6350
  onMouseEnter: () => setActiveDataKey(item.dataKey),
6320
6351
  onMouseLeave: () => setActiveDataKey(null),
6321
6352
  stroke: activeDataKey === item.dataKey ? item.activeColor ?? "#2196f3" : item.lineProps?.stroke ?? color,
@@ -6337,6 +6368,34 @@ function AdsLineChart({
6337
6368
 
6338
6369
  // src/components/AdsSparklineChart/index.tsx
6339
6370
  var import_recharts4 = require("recharts");
6371
+
6372
+ // src/lib/chartTooltip.ts
6373
+ var ISO_TIMESTAMP_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/;
6374
+ var DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH:mm:ss";
6375
+ function formatChartTooltipLabel(label, dateFormat = DEFAULT_DATE_FORMAT) {
6376
+ if (typeof label !== "string") {
6377
+ return String(label ?? "");
6378
+ }
6379
+ const match = label.match(ISO_TIMESTAMP_PATTERN);
6380
+ if (!match) {
6381
+ return label;
6382
+ }
6383
+ const [year, month, day] = match[1].split("-");
6384
+ const [hour, minute, second] = match[2].split(":");
6385
+ return dateFormat.replace(/YYYY|MM|DD|HH|mm|ss/g, (token) => {
6386
+ const values = {
6387
+ YYYY: year,
6388
+ MM: month,
6389
+ DD: day,
6390
+ HH: hour,
6391
+ mm: minute,
6392
+ ss: second
6393
+ };
6394
+ return values[token];
6395
+ });
6396
+ }
6397
+
6398
+ // src/components/AdsSparklineChart/index.tsx
6340
6399
  var import_jsx_runtime56 = require("react/jsx-runtime");
6341
6400
  var DEFAULT_HEIGHT2 = 40;
6342
6401
  var tooltipContentStyle2 = {
@@ -6352,6 +6411,13 @@ function getSafeHeight2(height) {
6352
6411
  function getSafeValue2(value) {
6353
6412
  return typeof value === "number" && Number.isFinite(value) ? Math.max(value, 0) : 0;
6354
6413
  }
6414
+ function getChartMargin(height, plotHeight) {
6415
+ if (!Number.isFinite(plotHeight) || !plotHeight || plotHeight >= height) {
6416
+ return { bottom: 1, left: 1, right: 1, top: 1 };
6417
+ }
6418
+ const verticalMargin = (height - Math.max(plotHeight, 1)) / 2;
6419
+ return { bottom: verticalMargin, left: 1, right: 1, top: verticalMargin };
6420
+ }
6355
6421
  function AdsSparklineChart({
6356
6422
  ariaLabel,
6357
6423
  className,
@@ -6359,7 +6425,9 @@ function AdsSparklineChart({
6359
6425
  data,
6360
6426
  dataKey,
6361
6427
  height,
6428
+ plotHeight,
6362
6429
  showTooltip = true,
6430
+ tooltipDateFormat,
6363
6431
  xKey
6364
6432
  }) {
6365
6433
  const chartData = data.map((datum) => ({
@@ -6368,6 +6436,7 @@ function AdsSparklineChart({
6368
6436
  [dataKey]: getSafeValue2(datum[dataKey])
6369
6437
  }));
6370
6438
  const safeHeight = getSafeHeight2(height);
6439
+ const chartMargin = getChartMargin(safeHeight, plotHeight);
6371
6440
  return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
6372
6441
  "div",
6373
6442
  {
@@ -6388,10 +6457,17 @@ function AdsSparklineChart({
6388
6457
  {
6389
6458
  accessibilityLayer: false,
6390
6459
  data: chartData,
6391
- margin: { bottom: 1, left: 1, right: 1, top: 1 },
6460
+ margin: chartMargin,
6392
6461
  children: [
6393
6462
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_recharts4.XAxis, { dataKey: xKey, hide: true, type: "category" }),
6394
- showTooltip && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_recharts4.Tooltip, { contentStyle: tooltipContentStyle2, cursor: false }),
6463
+ showTooltip && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
6464
+ import_recharts4.Tooltip,
6465
+ {
6466
+ contentStyle: tooltipContentStyle2,
6467
+ cursor: false,
6468
+ labelFormatter: (label) => formatChartTooltipLabel(label, tooltipDateFormat)
6469
+ }
6470
+ ),
6395
6471
  /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
6396
6472
  import_recharts4.Line,
6397
6473
  {
@@ -6578,6 +6654,7 @@ function AdsBarChart({
6578
6654
  highlightIndex,
6579
6655
  hoverColor,
6580
6656
  showTooltip = true,
6657
+ tooltipDateFormat,
6581
6658
  xAxis,
6582
6659
  xKey,
6583
6660
  yAxis
@@ -6637,7 +6714,14 @@ function AdsBarChart({
6637
6714
  width: yAxis.width
6638
6715
  }
6639
6716
  ),
6640
- showTooltip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(import_recharts5.Tooltip, { contentStyle: tooltipContentStyle3, cursor: { fill: "transparent" } }),
6717
+ showTooltip && /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6718
+ import_recharts5.Tooltip,
6719
+ {
6720
+ contentStyle: tooltipContentStyle3,
6721
+ cursor: { fill: "transparent" },
6722
+ labelFormatter: (label) => formatChartTooltipLabel(label, tooltipDateFormat)
6723
+ }
6724
+ ),
6641
6725
  /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
6642
6726
  import_recharts5.Bar,
6643
6727
  {
package/dist/index.d.cts CHANGED
@@ -807,8 +807,8 @@ interface AdsLineChartReferenceLine {
807
807
  interface AdsLineChartProps {
808
808
  ariaLabel?: string;
809
809
  chartProps?: Omit<React$1.ComponentProps<typeof ComposedChart>, "accessibilityLayer" | "children" | "data">;
810
- className?: string;
811
810
  children?: React$1.ReactNode;
811
+ className?: string;
812
812
  containerProps?: Omit<ChartContainerProps, "children" | "config" | "height">;
813
813
  curve?: AdsLineChartCurve;
814
814
  data: AdsChartDatum[];
@@ -834,7 +834,7 @@ interface AdsLineChartProps {
834
834
  yAxis?: AdsLineChartYAxisOptions;
835
835
  yAxisProps?: React$1.ComponentProps<typeof YAxis>;
836
836
  }
837
- declare function AdsLineChart({ ariaLabel, chartProps, className, children, containerProps, curve, data, gridColor, gridProps, height, referenceLine, series, showGrid, showTooltip, tooltipContent, tooltipContentClassName, tooltipFooter, tooltipLabelFormatter, tooltipProps, tooltipValueFormatter, xAxis, xAxisProps, xKey, yAxis, yAxisProps, }: AdsLineChartProps): React$1.JSX.Element;
837
+ declare function AdsLineChart({ ariaLabel, chartProps, children, className, containerProps, curve, data, gridColor, gridProps, height, referenceLine, series, showGrid, showTooltip, tooltipContent, tooltipContentClassName, tooltipFooter, tooltipLabelFormatter, tooltipProps, tooltipValueFormatter, xAxis, xAxisProps, xKey, yAxis, yAxisProps, }: AdsLineChartProps): React$1.JSX.Element;
838
838
 
839
839
  interface AdsSparklineChartProps {
840
840
  ariaLabel?: string;
@@ -843,10 +843,12 @@ interface AdsSparklineChartProps {
843
843
  data: AdsChartDatum[];
844
844
  dataKey: string;
845
845
  height?: number;
846
+ plotHeight?: number;
846
847
  showTooltip?: boolean;
848
+ tooltipDateFormat?: string;
847
849
  xKey: string;
848
850
  }
849
- declare function AdsSparklineChart({ ariaLabel, className, color, data, dataKey, height, showTooltip, xKey, }: AdsSparklineChartProps): React$1.JSX.Element;
851
+ declare function AdsSparklineChart({ ariaLabel, className, color, data, dataKey, height, plotHeight, showTooltip, tooltipDateFormat, xKey, }: AdsSparklineChartProps): React$1.JSX.Element;
850
852
 
851
853
  interface AdsStackedBarChartProps {
852
854
  ariaLabel?: string;
@@ -888,11 +890,12 @@ interface AdsBarChartProps {
888
890
  highlightIndex?: number;
889
891
  hoverColor?: string;
890
892
  showTooltip?: boolean;
893
+ tooltipDateFormat?: string;
891
894
  xAxis?: AdsBarChartXAxisOptions;
892
895
  xKey: string;
893
896
  yAxis?: AdsBarChartYAxisOptions;
894
897
  }
895
- declare function AdsBarChart({ ariaLabel, barRadius, barSize, className, color, data, dataKey, height, highlightColor, highlightIndex, hoverColor, showTooltip, xAxis, xKey, yAxis, }: AdsBarChartProps): React$1.JSX.Element;
898
+ declare function AdsBarChart({ ariaLabel, barRadius, barSize, className, color, data, dataKey, height, highlightColor, highlightIndex, hoverColor, showTooltip, tooltipDateFormat, xAxis, xKey, yAxis, }: AdsBarChartProps): React$1.JSX.Element;
896
899
 
897
900
  declare const RadioGroup: React$1.ForwardRefExoticComponent<Omit<_radix_ui_react_radio_group.RadioGroupProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
898
901
 
package/dist/index.d.ts CHANGED
@@ -807,8 +807,8 @@ interface AdsLineChartReferenceLine {
807
807
  interface AdsLineChartProps {
808
808
  ariaLabel?: string;
809
809
  chartProps?: Omit<React$1.ComponentProps<typeof ComposedChart>, "accessibilityLayer" | "children" | "data">;
810
- className?: string;
811
810
  children?: React$1.ReactNode;
811
+ className?: string;
812
812
  containerProps?: Omit<ChartContainerProps, "children" | "config" | "height">;
813
813
  curve?: AdsLineChartCurve;
814
814
  data: AdsChartDatum[];
@@ -834,7 +834,7 @@ interface AdsLineChartProps {
834
834
  yAxis?: AdsLineChartYAxisOptions;
835
835
  yAxisProps?: React$1.ComponentProps<typeof YAxis>;
836
836
  }
837
- declare function AdsLineChart({ ariaLabel, chartProps, className, children, containerProps, curve, data, gridColor, gridProps, height, referenceLine, series, showGrid, showTooltip, tooltipContent, tooltipContentClassName, tooltipFooter, tooltipLabelFormatter, tooltipProps, tooltipValueFormatter, xAxis, xAxisProps, xKey, yAxis, yAxisProps, }: AdsLineChartProps): React$1.JSX.Element;
837
+ declare function AdsLineChart({ ariaLabel, chartProps, children, className, containerProps, curve, data, gridColor, gridProps, height, referenceLine, series, showGrid, showTooltip, tooltipContent, tooltipContentClassName, tooltipFooter, tooltipLabelFormatter, tooltipProps, tooltipValueFormatter, xAxis, xAxisProps, xKey, yAxis, yAxisProps, }: AdsLineChartProps): React$1.JSX.Element;
838
838
 
839
839
  interface AdsSparklineChartProps {
840
840
  ariaLabel?: string;
@@ -843,10 +843,12 @@ interface AdsSparklineChartProps {
843
843
  data: AdsChartDatum[];
844
844
  dataKey: string;
845
845
  height?: number;
846
+ plotHeight?: number;
846
847
  showTooltip?: boolean;
848
+ tooltipDateFormat?: string;
847
849
  xKey: string;
848
850
  }
849
- declare function AdsSparklineChart({ ariaLabel, className, color, data, dataKey, height, showTooltip, xKey, }: AdsSparklineChartProps): React$1.JSX.Element;
851
+ declare function AdsSparklineChart({ ariaLabel, className, color, data, dataKey, height, plotHeight, showTooltip, tooltipDateFormat, xKey, }: AdsSparklineChartProps): React$1.JSX.Element;
850
852
 
851
853
  interface AdsStackedBarChartProps {
852
854
  ariaLabel?: string;
@@ -888,11 +890,12 @@ interface AdsBarChartProps {
888
890
  highlightIndex?: number;
889
891
  hoverColor?: string;
890
892
  showTooltip?: boolean;
893
+ tooltipDateFormat?: string;
891
894
  xAxis?: AdsBarChartXAxisOptions;
892
895
  xKey: string;
893
896
  yAxis?: AdsBarChartYAxisOptions;
894
897
  }
895
- declare function AdsBarChart({ ariaLabel, barRadius, barSize, className, color, data, dataKey, height, highlightColor, highlightIndex, hoverColor, showTooltip, xAxis, xKey, yAxis, }: AdsBarChartProps): React$1.JSX.Element;
898
+ declare function AdsBarChart({ ariaLabel, barRadius, barSize, className, color, data, dataKey, height, highlightColor, highlightIndex, hoverColor, showTooltip, tooltipDateFormat, xAxis, xKey, yAxis, }: AdsBarChartProps): React$1.JSX.Element;
896
899
 
897
900
  declare const RadioGroup: React$1.ForwardRefExoticComponent<Omit<_radix_ui_react_radio_group.RadioGroupProps & React$1.RefAttributes<HTMLDivElement>, "ref"> & React$1.RefAttributes<HTMLDivElement>>;
898
901
 
package/dist/index.js CHANGED
@@ -5955,9 +5955,7 @@ function LineChartTooltipContent({
5955
5955
  tooltipLabelFormatter,
5956
5956
  tooltipValueFormatter
5957
5957
  }) {
5958
- if (!active || !payload.length) {
5959
- return null;
5960
- }
5958
+ if (!active || !payload.length) return null;
5961
5959
  return /* @__PURE__ */ jsxs28(
5962
5960
  "div",
5963
5961
  {
@@ -5969,15 +5967,30 @@ function LineChartTooltipContent({
5969
5967
  children: [
5970
5968
  tooltipLabelFormatter && /* @__PURE__ */ jsx55("p", { className: "mb-2 text-xs font-medium text-muted-foreground", children: tooltipLabelFormatter(label) }),
5971
5969
  /* @__PURE__ */ jsx55("div", { className: "space-y-1.5", children: series.map((item, index) => {
5972
- const entry = payload.find((payloadItem) => payloadItem.dataKey === item.dataKey);
5970
+ const entry = payload.find(
5971
+ (payloadItem) => payloadItem.dataKey === item.dataKey
5972
+ );
5973
5973
  const value = typeof entry?.value === "number" && Number.isFinite(entry.value) ? entry.value : 0;
5974
5974
  const color = getSeriesColor(item, index);
5975
- const displayLabel = item.label ?? item.dataKey;
5976
- return /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-1.5 text-sm", children: [
5977
- /* @__PURE__ */ jsx55("span", { "aria-hidden": "true", className: "size-2 rounded-full", style: { backgroundColor: color } }),
5978
- /* @__PURE__ */ jsx55("span", { className: "text-muted-foreground", children: displayLabel }),
5979
- /* @__PURE__ */ jsx55("span", { className: "font-semibold text-popover-foreground", children: tooltipValueFormatter ? tooltipValueFormatter(value, item) : value })
5980
- ] }, item.dataKey);
5975
+ return /* @__PURE__ */ jsxs28(
5976
+ "div",
5977
+ {
5978
+ className: "flex items-center gap-1.5 text-sm",
5979
+ children: [
5980
+ /* @__PURE__ */ jsx55(
5981
+ "span",
5982
+ {
5983
+ "aria-hidden": "true",
5984
+ className: "size-2 rounded-full",
5985
+ style: { backgroundColor: color }
5986
+ }
5987
+ ),
5988
+ /* @__PURE__ */ jsx55("span", { className: "text-muted-foreground", children: item.label ?? item.dataKey }),
5989
+ /* @__PURE__ */ jsx55("span", { className: "font-semibold text-popover-foreground", children: tooltipValueFormatter ? tooltipValueFormatter(value, item) : value })
5990
+ ]
5991
+ },
5992
+ item.dataKey
5993
+ );
5981
5994
  }) }),
5982
5995
  tooltipFooter && /* @__PURE__ */ jsx55("p", { className: "mt-2 text-xs font-bold leading-[1.4]", children: tooltipFooter })
5983
5996
  ]
@@ -5987,8 +6000,8 @@ function LineChartTooltipContent({
5987
6000
  function AdsLineChart({
5988
6001
  ariaLabel,
5989
6002
  chartProps,
5990
- className,
5991
6003
  children,
6004
+ className,
5992
6005
  containerProps,
5993
6006
  curve = "linear",
5994
6007
  data,
@@ -6012,29 +6025,47 @@ function AdsLineChart({
6012
6025
  yAxisProps
6013
6026
  }) {
6014
6027
  const [activeDataKey, setActiveDataKey] = React48.useState(null);
6028
+ const chartElementRef = React48.useRef(null);
6029
+ const previousDataRef = React48.useRef(data);
6015
6030
  const hoverHighlightDataKey = series.find((item) => item.activeColor)?.dataKey ?? null;
6016
- const chartData = data.map((datum) => {
6017
- const safeDatum = { ...datum, [xKey]: datum[xKey] };
6018
- series.forEach((item) => {
6019
- safeDatum[item.dataKey] = getSafeValue(datum[item.dataKey]);
6020
- });
6021
- return safeDatum;
6022
- });
6023
- const safeHeight = getSafeHeight(height);
6024
- const chartConfig = getChartConfig(series);
6031
+ const chartData = React48.useMemo(
6032
+ () => data.map((datum) => {
6033
+ const safeDatum = { ...datum, [xKey]: datum[xKey] };
6034
+ series.forEach((item) => {
6035
+ safeDatum[item.dataKey] = getSafeValue(datum[item.dataKey]);
6036
+ });
6037
+ return safeDatum;
6038
+ }),
6039
+ [data, series, xKey]
6040
+ );
6041
+ const chartConfig = React48.useMemo(() => getChartConfig(series), [series]);
6025
6042
  const {
6026
6043
  cursor: tooltipCursor,
6027
6044
  wrapperStyle: tooltipWrapperStyle,
6028
6045
  ...restTooltipProps
6029
6046
  } = tooltipProps ?? {};
6047
+ React48.useEffect(() => {
6048
+ if (previousDataRef.current === data) {
6049
+ return;
6050
+ }
6051
+ previousDataRef.current = data;
6052
+ chartElementRef.current?.animate?.(
6053
+ [
6054
+ { opacity: 0.72, transform: "translateY(4px)" },
6055
+ { opacity: 1, transform: "translateY(0)" }
6056
+ ],
6057
+ { duration: 360, easing: "ease-out" }
6058
+ );
6059
+ }, [data]);
6030
6060
  return /* @__PURE__ */ jsx55(
6031
6061
  "div",
6032
6062
  {
6033
6063
  "aria-label": ariaLabel ?? "Line chart",
6034
6064
  className: cn("w-full", className),
6035
6065
  "data-testid": "ads-line-chart",
6066
+ ref: chartElementRef,
6036
6067
  role: "img",
6037
- style: { height: safeHeight },
6068
+ style: { height: getSafeHeight(height) },
6038
6069
  children: /* @__PURE__ */ jsx55(
6039
6070
  ChartContainer,
6040
6071
  {
@@ -6133,12 +6164,12 @@ function AdsLineChart({
6133
6164
  Area,
6134
6165
  {
6135
6166
  ...item.areaProps,
6167
+ animationDuration: item.areaProps?.animationDuration ?? 360,
6168
+ animationEasing: item.areaProps?.animationEasing ?? "ease-out",
6136
6169
  dataKey: item.dataKey,
6137
6170
  fill: item.areaProps?.fill ?? color,
6138
6171
  fillOpacity: item.areaProps?.fillOpacity ?? opacity,
6139
- animationDuration: item.areaProps?.animationDuration ?? 360,
6140
- animationEasing: item.areaProps?.animationEasing ?? "ease-out",
6141
- isAnimationActive: item.areaProps?.isAnimationActive ?? true,
6172
+ isAnimationActive: item.areaProps?.isAnimationActive ?? false,
6142
6173
  stroke: item.areaProps?.stroke ?? "none",
6143
6174
  type: item.areaProps?.type ?? curve
6144
6175
  }
@@ -6152,7 +6183,7 @@ function AdsLineChart({
6152
6183
  animationEasing: item.lineProps?.animationEasing ?? "ease-out",
6153
6184
  dataKey: item.dataKey,
6154
6185
  dot: item.lineProps?.dot ?? false,
6155
- isAnimationActive: item.lineProps?.isAnimationActive ?? true,
6186
+ isAnimationActive: item.lineProps?.isAnimationActive ?? false,
6156
6187
  onMouseEnter: () => setActiveDataKey(item.dataKey),
6157
6188
  onMouseLeave: () => setActiveDataKey(null),
6158
6189
  stroke: activeDataKey === item.dataKey ? item.activeColor ?? "#2196f3" : item.lineProps?.stroke ?? color,
@@ -6174,6 +6205,34 @@ function AdsLineChart({
6174
6205
 
6175
6206
  // src/components/AdsSparklineChart/index.tsx
6176
6207
  import { Line as Line2, LineChart, Tooltip as Tooltip3, XAxis as XAxis2 } from "recharts";
6208
+
6209
+ // src/lib/chartTooltip.ts
6210
+ var ISO_TIMESTAMP_PATTERN = /^(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?$/;
6211
+ var DEFAULT_DATE_FORMAT = "YYYY-MM-DD HH:mm:ss";
6212
+ function formatChartTooltipLabel(label, dateFormat = DEFAULT_DATE_FORMAT) {
6213
+ if (typeof label !== "string") {
6214
+ return String(label ?? "");
6215
+ }
6216
+ const match = label.match(ISO_TIMESTAMP_PATTERN);
6217
+ if (!match) {
6218
+ return label;
6219
+ }
6220
+ const [year, month, day] = match[1].split("-");
6221
+ const [hour, minute, second] = match[2].split(":");
6222
+ return dateFormat.replace(/YYYY|MM|DD|HH|mm|ss/g, (token) => {
6223
+ const values = {
6224
+ YYYY: year,
6225
+ MM: month,
6226
+ DD: day,
6227
+ HH: hour,
6228
+ mm: minute,
6229
+ ss: second
6230
+ };
6231
+ return values[token];
6232
+ });
6233
+ }
6234
+
6235
+ // src/components/AdsSparklineChart/index.tsx
6177
6236
  import { jsx as jsx56, jsxs as jsxs29 } from "react/jsx-runtime";
6178
6237
  var DEFAULT_HEIGHT2 = 40;
6179
6238
  var tooltipContentStyle2 = {
@@ -6189,6 +6248,13 @@ function getSafeHeight2(height) {
6189
6248
  function getSafeValue2(value) {
6190
6249
  return typeof value === "number" && Number.isFinite(value) ? Math.max(value, 0) : 0;
6191
6250
  }
6251
+ function getChartMargin(height, plotHeight) {
6252
+ if (!Number.isFinite(plotHeight) || !plotHeight || plotHeight >= height) {
6253
+ return { bottom: 1, left: 1, right: 1, top: 1 };
6254
+ }
6255
+ const verticalMargin = (height - Math.max(plotHeight, 1)) / 2;
6256
+ return { bottom: verticalMargin, left: 1, right: 1, top: verticalMargin };
6257
+ }
6192
6258
  function AdsSparklineChart({
6193
6259
  ariaLabel,
6194
6260
  className,
@@ -6196,7 +6262,9 @@ function AdsSparklineChart({
6196
6262
  data,
6197
6263
  dataKey,
6198
6264
  height,
6265
+ plotHeight,
6199
6266
  showTooltip = true,
6267
+ tooltipDateFormat,
6200
6268
  xKey
6201
6269
  }) {
6202
6270
  const chartData = data.map((datum) => ({
@@ -6205,6 +6273,7 @@ function AdsSparklineChart({
6205
6273
  [dataKey]: getSafeValue2(datum[dataKey])
6206
6274
  }));
6207
6275
  const safeHeight = getSafeHeight2(height);
6276
+ const chartMargin = getChartMargin(safeHeight, plotHeight);
6208
6277
  return /* @__PURE__ */ jsx56(
6209
6278
  "div",
6210
6279
  {
@@ -6225,10 +6294,17 @@ function AdsSparklineChart({
6225
6294
  {
6226
6295
  accessibilityLayer: false,
6227
6296
  data: chartData,
6228
- margin: { bottom: 1, left: 1, right: 1, top: 1 },
6297
+ margin: chartMargin,
6229
6298
  children: [
6230
6299
  /* @__PURE__ */ jsx56(XAxis2, { dataKey: xKey, hide: true, type: "category" }),
6231
- showTooltip && /* @__PURE__ */ jsx56(Tooltip3, { contentStyle: tooltipContentStyle2, cursor: false }),
6300
+ showTooltip && /* @__PURE__ */ jsx56(
6301
+ Tooltip3,
6302
+ {
6303
+ contentStyle: tooltipContentStyle2,
6304
+ cursor: false,
6305
+ labelFormatter: (label) => formatChartTooltipLabel(label, tooltipDateFormat)
6306
+ }
6307
+ ),
6232
6308
  /* @__PURE__ */ jsx56(
6233
6309
  Line2,
6234
6310
  {
@@ -6415,6 +6491,7 @@ function AdsBarChart({
6415
6491
  highlightIndex,
6416
6492
  hoverColor,
6417
6493
  showTooltip = true,
6494
+ tooltipDateFormat,
6418
6495
  xAxis,
6419
6496
  xKey,
6420
6497
  yAxis
@@ -6474,7 +6551,14 @@ function AdsBarChart({
6474
6551
  width: yAxis.width
6475
6552
  }
6476
6553
  ),
6477
- showTooltip && /* @__PURE__ */ jsx60(Tooltip5, { contentStyle: tooltipContentStyle3, cursor: { fill: "transparent" } }),
6554
+ showTooltip && /* @__PURE__ */ jsx60(
6555
+ Tooltip5,
6556
+ {
6557
+ contentStyle: tooltipContentStyle3,
6558
+ cursor: { fill: "transparent" },
6559
+ labelFormatter: (label) => formatChartTooltipLabel(label, tooltipDateFormat)
6560
+ }
6561
+ ),
6478
6562
  /* @__PURE__ */ jsx60(
6479
6563
  Bar,
6480
6564
  {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adsgency_npm/adsgency-ads-ui",
3
- "version": "0.1.0-alpha.33",
3
+ "version": "0.1.0-alpha.35",
4
4
  "description": "AdsGency Ads Design System React component library.",
5
5
  "private": false,
6
6
  "type": "module",
@@ -111,8 +111,8 @@
111
111
  "verify:package": "node scripts/verify-package.mjs",
112
112
  "lint": "eslint src tests --max-warnings=0 && pnpm verify:hygiene && pnpm verify:tokens",
113
113
  "typecheck": "tsc --noEmit",
114
- "test": "NODE_OPTIONS=--max-old-space-size=1536 vitest run",
115
- "test:watch": "NODE_OPTIONS=--max-old-space-size=1536 vitest",
114
+ "test": "vitest run",
115
+ "test:watch": "vitest",
116
116
  "pack:dry": "pnpm build && npm pack --dry-run",
117
117
  "verify": "pnpm lint && pnpm typecheck && pnpm test && pnpm demo:typecheck && pnpm build && pnpm verify:package"
118
118
  }