@vectara/vectara-ui 19.1.0 → 19.2.0

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.
@@ -14,7 +14,10 @@ type Props = {
14
14
  showLegend?: boolean;
15
15
  showGrid?: boolean;
16
16
  showTooltip?: boolean;
17
+ syncId?: string;
18
+ syncMethod?: "index" | "value";
19
+ formatValue?: (value: number) => string;
17
20
  "data-testid"?: string;
18
21
  };
19
- export declare const VuiBarChart: ({ data, categoryKey, series, orientation, stacked, height, showLegend, showGrid, showTooltip, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
22
+ export declare const VuiBarChart: ({ data, categoryKey, series, orientation, stacked, height, showLegend, showGrid, showTooltip, syncId, syncMethod, formatValue, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
20
23
  export {};
@@ -14,11 +14,11 @@ import { Bar, CartesianGrid, BarChart as RechartsBarChart, Legend, ResponsiveCon
14
14
  import { getChartColor, getChartColorByIndex } from "./palette";
15
15
  import { chartAxisLineStyle, chartLegendProps, chartTickStyle, chartTooltipProps } from "./chartTheme";
16
16
  export const VuiBarChart = (_a) => {
17
- var { data, categoryKey, series, orientation = "columns", stacked = false, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "orientation", "stacked", "height", "showLegend", "showGrid", "showTooltip"]);
17
+ var { data, categoryKey, series, orientation = "columns", stacked = false, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true, syncId, syncMethod, formatValue } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "orientation", "stacked", "height", "showLegend", "showGrid", "showTooltip", "syncId", "syncMethod", "formatValue"]);
18
18
  const isHorizontal = orientation === "bars";
19
19
  const categoryAxis = (_jsx(_Fragment, { children: isHorizontal ? (_jsx(YAxis, { type: "category", dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false })) : (_jsx(XAxis, { type: "category", dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false })) }));
20
- const valueAxis = isHorizontal ? (_jsx(XAxis, { type: "number", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false })) : (_jsx(YAxis, { type: "number", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }));
21
- return (_jsx("div", Object.assign({ className: "vuiBarChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: _jsxs(RechartsBarChart, Object.assign({ data: data, layout: isHorizontal ? "vertical" : "horizontal" }, { children: [showGrid && (_jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: isHorizontal, horizontal: !isHorizontal })), categoryAxis, valueAxis, showTooltip && _jsx(Tooltip, Object.assign({ cursor: { fill: "var(--vui-color-light-shade)" } }, chartTooltipProps)), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps)), series.map((s, index) => {
20
+ const valueAxis = isHorizontal ? (_jsx(XAxis, { type: "number", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false, tickFormatter: formatValue })) : (_jsx(YAxis, { type: "number", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false, tickFormatter: formatValue }));
21
+ return (_jsx("div", Object.assign({ className: "vuiBarChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: _jsxs(RechartsBarChart, Object.assign({ data: data, layout: isHorizontal ? "vertical" : "horizontal", syncId: syncId, syncMethod: syncMethod }, { children: [showGrid && (_jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: isHorizontal, horizontal: !isHorizontal })), categoryAxis, valueAxis, showTooltip && (_jsx(Tooltip, Object.assign({ cursor: { fill: "var(--vui-color-light-shade)" }, formatter: formatValue && ((value) => (typeof value === "number" ? formatValue(value) : value)) }, chartTooltipProps))), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps)), series.map((s, index) => {
22
22
  var _a;
23
23
  return (_jsx(Bar, { dataKey: s.dataKey, name: (_a = s.name) !== null && _a !== void 0 ? _a : s.dataKey, fill: s.color ? getChartColor(s.color) : getChartColorByIndex(index), stackId: stacked ? "stack" : undefined, radius: isHorizontal ? [0, 4, 4, 0] : [4, 4, 0, 0],
24
24
  // A thin stroke separates touching segments regardless of fill,
@@ -15,7 +15,11 @@ type Props = {
15
15
  showLegend?: boolean;
16
16
  showGrid?: boolean;
17
17
  showTooltip?: boolean;
18
+ syncId?: string;
19
+ syncMethod?: "index" | "value";
20
+ formatLeftValue?: (value: number) => string;
21
+ formatRightValue?: (value: number) => string;
18
22
  "data-testid"?: string;
19
23
  };
20
- export declare const VuiComposedChart: ({ data, categoryKey, series, height, showLegend, showGrid, showTooltip, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
24
+ export declare const VuiComposedChart: ({ data, categoryKey, series, height, showLegend, showGrid, showTooltip, syncId, syncMethod, formatLeftValue, formatRightValue, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
21
25
  export {};
@@ -14,9 +14,20 @@ import { Bar, CartesianGrid, ComposedChart as RechartsComposedChart, Legend, Lin
14
14
  import { getChartColor, getChartColorByIndex } from "./palette";
15
15
  import { chartAxisLineStyle, chartLegendProps, chartTickStyle, chartTooltipProps } from "./chartTheme";
16
16
  export const VuiComposedChart = (_a) => {
17
- var { data, categoryKey, series, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "height", "showLegend", "showGrid", "showTooltip"]);
17
+ var { data, categoryKey, series, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true, syncId, syncMethod, formatLeftValue, formatRightValue } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "height", "showLegend", "showGrid", "showTooltip", "syncId", "syncMethod", "formatLeftValue", "formatRightValue"]);
18
18
  const hasRightAxis = series.some((s) => s.axis === "right");
19
- return (_jsx("div", Object.assign({ className: "vuiComposedChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: _jsxs(RechartsComposedChart, Object.assign({ data: data }, { children: [showGrid && _jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: false }), _jsx(XAxis, { dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), _jsx(YAxis, { yAxisId: "left", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), hasRightAxis && (_jsx(YAxis, { yAxisId: "right", orientation: "right", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false })), showTooltip && _jsx(Tooltip, Object.assign({ cursor: { fill: "var(--vui-color-light-shade)" } }, chartTooltipProps)), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps)), series.map((s, index) => {
19
+ // A composed chart can mix two axes, so the tooltip formats each value by the
20
+ // axis its series is measured against rather than a single shared formatter.
21
+ const axisByDataKey = new Map(series.map((s) => { var _a; return [s.dataKey, (_a = s.axis) !== null && _a !== void 0 ? _a : "left"]; }));
22
+ const hasValueFormatter = Boolean(formatLeftValue || formatRightValue);
23
+ return (_jsx("div", Object.assign({ className: "vuiComposedChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: _jsxs(RechartsComposedChart, Object.assign({ data: data, syncId: syncId, syncMethod: syncMethod }, { children: [showGrid && _jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: false }), _jsx(XAxis, { dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), _jsx(YAxis, { yAxisId: "left", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false, tickFormatter: formatLeftValue }), hasRightAxis && (_jsx(YAxis, { yAxisId: "right", orientation: "right", tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false, tickFormatter: formatRightValue })), showTooltip && (_jsx(Tooltip, Object.assign({ cursor: { fill: "var(--vui-color-light-shade)" }, formatter: hasValueFormatter
24
+ ? (value, _name, item) => {
25
+ if (typeof value !== "number")
26
+ return value;
27
+ const format = axisByDataKey.get(String(item === null || item === void 0 ? void 0 : item.dataKey)) === "right" ? formatRightValue : formatLeftValue;
28
+ return format ? format(value) : value;
29
+ }
30
+ : undefined }, chartTooltipProps))), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps)), series.map((s, index) => {
20
31
  var _a, _b;
21
32
  const color = s.color ? getChartColor(s.color) : getChartColorByIndex(index);
22
33
  const yAxisId = (_a = s.axis) !== null && _a !== void 0 ? _a : "left";
@@ -16,7 +16,10 @@ type Props = {
16
16
  showLegend?: boolean;
17
17
  showGrid?: boolean;
18
18
  showTooltip?: boolean;
19
+ syncId?: string;
20
+ syncMethod?: "index" | "value";
21
+ formatValue?: (value: number) => string;
19
22
  "data-testid"?: string;
20
23
  };
21
- export declare const VuiLineChart: ({ data, categoryKey, series, variant, curved, showPoints, height, showLegend, showGrid, showTooltip, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
24
+ export declare const VuiLineChart: ({ data, categoryKey, series, variant, curved, showPoints, height, showLegend, showGrid, showTooltip, syncId, syncMethod, formatValue, ...rest }: Props) => import("react/jsx-runtime").JSX.Element;
22
25
  export {};
@@ -14,10 +14,10 @@ import { Area, AreaChart as RechartsAreaChart, CartesianGrid, Line, LineChart as
14
14
  import { getChartColor, getChartColorByIndex } from "./palette";
15
15
  import { chartAxisLineStyle, chartLegendProps, chartTickStyle, chartTooltipProps } from "./chartTheme";
16
16
  export const VuiLineChart = (_a) => {
17
- var { data, categoryKey, series, variant = "line", curved = false, showPoints = true, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "variant", "curved", "showPoints", "height", "showLegend", "showGrid", "showTooltip"]);
17
+ var { data, categoryKey, series, variant = "line", curved = false, showPoints = true, height = 320, showLegend = series.length > 1, showGrid = true, showTooltip = true, syncId, syncMethod, formatValue } = _a, rest = __rest(_a, ["data", "categoryKey", "series", "variant", "curved", "showPoints", "height", "showLegend", "showGrid", "showTooltip", "syncId", "syncMethod", "formatValue"]);
18
18
  const isArea = variant === "area" || variant === "stacked-area";
19
19
  const isStacked = variant === "stacked-area";
20
- const axes = (_jsxs(_Fragment, { children: [showGrid && _jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: false }), _jsx(XAxis, { dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), _jsx(YAxis, { tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), showTooltip && _jsx(Tooltip, Object.assign({ cursor: { stroke: "var(--vui-color-border-medium)" } }, chartTooltipProps)), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps))] }));
20
+ const axes = (_jsxs(_Fragment, { children: [showGrid && _jsx(CartesianGrid, { stroke: "var(--vui-color-border-light)", vertical: false }), _jsx(XAxis, { dataKey: categoryKey, tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false }), _jsx(YAxis, { tick: chartTickStyle, axisLine: chartAxisLineStyle, tickLine: false, tickFormatter: formatValue }), showTooltip && (_jsx(Tooltip, Object.assign({ cursor: { stroke: "var(--vui-color-border-medium)" }, formatter: formatValue && ((value) => (typeof value === "number" ? formatValue(value) : value)) }, chartTooltipProps))), showLegend && _jsx(Legend, Object.assign({}, chartLegendProps))] }));
21
21
  // Shared marker props keep lines and areas visually identical apart from the fill.
22
22
  const markProps = (s, index) => {
23
23
  var _a;
@@ -33,10 +33,10 @@ export const VuiLineChart = (_a) => {
33
33
  activeDot: { r: 5 }
34
34
  };
35
35
  };
36
- return (_jsx("div", Object.assign({ className: "vuiLineChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: isArea ? (_jsxs(RechartsAreaChart, Object.assign({ data: data }, { children: [axes, series.map((s, index) => {
36
+ return (_jsx("div", Object.assign({ className: "vuiLineChart" }, rest, { children: _jsx(ResponsiveContainer, Object.assign({ width: "100%", height: height }, { children: isArea ? (_jsxs(RechartsAreaChart, Object.assign({ data: data, syncId: syncId, syncMethod: syncMethod }, { children: [axes, series.map((s, index) => {
37
37
  const props = markProps(s, index);
38
38
  // Stacked areas tile rather than overlap, so they take a more solid
39
39
  // fill; overlapping areas stay translucent to remain readable.
40
40
  return (_jsx(Area, Object.assign({}, props, { fill: props.stroke, fillOpacity: isStacked ? 0.85 : 0.2, stackId: isStacked ? "stack" : undefined })));
41
- })] }))) : (_jsxs(RechartsLineChart, Object.assign({ data: data }, { children: [axes, series.map((s, index) => (_jsx(Line, Object.assign({}, markProps(s, index)))))] }))) })) })));
41
+ })] }))) : (_jsxs(RechartsLineChart, Object.assign({ data: data, syncId: syncId, syncMethod: syncMethod }, { children: [axes, series.map((s, index) => (_jsx(Line, Object.assign({}, markProps(s, index)))))] }))) })) })));
42
42
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vectara/vectara-ui",
3
- "version": "19.1.0",
3
+ "version": "19.2.0",
4
4
  "homepage": "./",
5
5
  "description": "Vectara's design system, codified as a React and Sass component library",
6
6
  "author": "Vectara",
@@ -0,0 +1,32 @@
1
+ import { VuiComposedChart } from "../../../lib";
2
+
3
+ // Request volume (bars, left axis) against p95 latency (line, right axis). The
4
+ // two axes measure different units, so each gets its own value formatter — and
5
+ // the shared tooltip formats each row by the axis its series belongs to.
6
+ const data = [
7
+ { time: "10:00", requests: 4200, latency: 820 },
8
+ { time: "10:05", requests: 5100, latency: 1240 },
9
+ { time: "10:10", requests: 6800, latency: 980 },
10
+ { time: "10:15", requests: 7400, latency: 2100 },
11
+ { time: "10:20", requests: 8200, latency: 1560 },
12
+ { time: "10:25", requests: 9100, latency: 1180 }
13
+ ];
14
+
15
+ const formatCount = (value: number) => (value >= 1000 ? `${(value / 1000).toFixed(1)}k` : `${value}`);
16
+
17
+ const formatMs = (ms: number) => (ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`);
18
+
19
+ export const FormattedAxes = () => {
20
+ return (
21
+ <VuiComposedChart
22
+ data={data}
23
+ categoryKey="time"
24
+ formatLeftValue={formatCount}
25
+ formatRightValue={formatMs}
26
+ series={[
27
+ { dataKey: "requests", name: "Requests", type: "bar", axis: "left" },
28
+ { dataKey: "latency", name: "p95 latency", type: "line", axis: "right", curved: true }
29
+ ]}
30
+ />
31
+ );
32
+ };
@@ -1,6 +1,8 @@
1
1
  import { Basic } from "./Basic";
2
+ import { FormattedAxes } from "./FormattedAxes";
2
3
 
3
4
  const BasicSource = require("!!raw-loader!./Basic");
5
+ const FormattedAxesSource = require("!!raw-loader!./FormattedAxes");
4
6
 
5
7
  export const composedChart = {
6
8
  name: "Composed chart",
@@ -10,6 +12,11 @@ export const composedChart = {
10
12
  name: "Basic",
11
13
  component: <Basic />,
12
14
  source: BasicSource.default.toString()
15
+ },
16
+ {
17
+ name: "Formatted axes",
18
+ component: <FormattedAxes />,
19
+ source: FormattedAxesSource.default.toString()
13
20
  }
14
21
  ]
15
22
  };
@@ -0,0 +1,25 @@
1
+ import { VuiLineChart } from "../../../lib";
2
+
3
+ const data = [
4
+ { time: "10:00", latency: 820 },
5
+ { time: "10:05", latency: 1240 },
6
+ { time: "10:10", latency: 980 },
7
+ { time: "10:15", latency: 2100 },
8
+ { time: "10:20", latency: 1560 },
9
+ { time: "10:25", latency: 1180 }
10
+ ];
11
+
12
+ // formatValue formats both the value-axis ticks and the tooltip readout, so raw
13
+ // millisecond values render as human-readable durations.
14
+ const formatMs = (ms: number) => (ms >= 1000 ? `${(ms / 1000).toFixed(1)}s` : `${ms}ms`);
15
+
16
+ export const FormattedValues = () => {
17
+ return (
18
+ <VuiLineChart
19
+ data={data}
20
+ categoryKey="time"
21
+ formatValue={formatMs}
22
+ series={[{ dataKey: "latency", name: "Latency" }]}
23
+ />
24
+ );
25
+ };
@@ -0,0 +1,48 @@
1
+ import { VuiBarChart, VuiLineChart, VuiSpacer } from "../../../lib";
2
+
3
+ // The two charts cover the same timeline at different resolutions. Hovering
4
+ // either one highlights the matching timestamp on both. syncMethod "value"
5
+ // aligns by the x-axis value rather than by data index, which is what lets
6
+ // charts with differing point counts stay in step.
7
+ const latency = [
8
+ { time: "10:00", p95: 320 },
9
+ { time: "10:10", p95: 280 },
10
+ { time: "10:20", p95: 460 },
11
+ { time: "10:30", p95: 240 }
12
+ ];
13
+
14
+ const requests = [
15
+ { time: "10:00", requests: 1200 },
16
+ { time: "10:05", requests: 1800 },
17
+ { time: "10:10", requests: 1500 },
18
+ { time: "10:15", requests: 2100 },
19
+ { time: "10:20", requests: 1900 },
20
+ { time: "10:25", requests: 1700 },
21
+ { time: "10:30", requests: 1400 }
22
+ ];
23
+
24
+ const SYNC_ID = "trafficDemo";
25
+
26
+ export const Synced = () => {
27
+ return (
28
+ <>
29
+ <VuiLineChart
30
+ data={latency}
31
+ categoryKey="time"
32
+ syncId={SYNC_ID}
33
+ syncMethod="value"
34
+ height={200}
35
+ series={[{ dataKey: "p95", name: "p95 latency (ms)" }]}
36
+ />
37
+ <VuiSpacer size="m" />
38
+ <VuiBarChart
39
+ data={requests}
40
+ categoryKey="time"
41
+ syncId={SYNC_ID}
42
+ syncMethod="value"
43
+ height={200}
44
+ series={[{ dataKey: "requests", name: "Requests" }]}
45
+ />
46
+ </>
47
+ );
48
+ };
@@ -2,11 +2,15 @@ import { Basic } from "./Basic";
2
2
  import { Curved } from "./Curved";
3
3
  import { Area } from "./Area";
4
4
  import { StackedArea } from "./StackedArea";
5
+ import { FormattedValues } from "./FormattedValues";
6
+ import { Synced } from "./Synced";
5
7
 
6
8
  const BasicSource = require("!!raw-loader!./Basic");
7
9
  const CurvedSource = require("!!raw-loader!./Curved");
8
10
  const AreaSource = require("!!raw-loader!./Area");
9
11
  const StackedAreaSource = require("!!raw-loader!./StackedArea");
12
+ const FormattedValuesSource = require("!!raw-loader!./FormattedValues");
13
+ const SyncedSource = require("!!raw-loader!./Synced");
10
14
 
11
15
  export const lineChart = {
12
16
  name: "Line chart",
@@ -31,6 +35,16 @@ export const lineChart = {
31
35
  name: "Stacked area",
32
36
  component: <StackedArea />,
33
37
  source: StackedAreaSource.default.toString()
38
+ },
39
+ {
40
+ name: "Formatted values",
41
+ component: <FormattedValues />,
42
+ source: FormattedValuesSource.default.toString()
43
+ },
44
+ {
45
+ name: "Synced",
46
+ component: <Synced />,
47
+ source: SyncedSource.default.toString()
34
48
  }
35
49
  ]
36
50
  };