@plumile/ui 0.1.122 → 0.1.125
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/lib/esm/__tests__/reactDomTestUtils.js +48 -0
- package/lib/esm/__tests__/reactDomTestUtils.js.map +1 -0
- package/lib/esm/atomic/molecules/markdown/components/MarkdownHeading.css.js +1 -0
- package/lib/esm/atomic/molecules/markdown/components/MarkdownTable.css.js +0 -1
- package/lib/esm/components/charts/MetricHistoryChart.js +17 -39
- package/lib/esm/components/charts/MetricHistoryChart.js.map +1 -1
- package/lib/esm/components/charts/TimeSeriesLineChart.js +20 -32
- package/lib/esm/components/charts/TimeSeriesLineChart.js.map +1 -1
- package/lib/esm/components/data-table/DataTable.js +33 -35
- package/lib/esm/components/data-table/DataTable.js.map +1 -1
- package/lib/esm/components/data-table/VirtualizedConnectionTable.js +48 -60
- package/lib/esm/components/data-table/VirtualizedConnectionTable.js.map +1 -1
- package/lib/esm/internal/charts/metricHistoryChartHelpers.js +24 -0
- package/lib/esm/internal/charts/metricHistoryChartHelpers.js.map +1 -0
- package/lib/esm/internal/charts/timeSeriesLineChartHelpers.js +18 -0
- package/lib/esm/internal/charts/timeSeriesLineChartHelpers.js.map +1 -0
- package/lib/esm/internal/data-table/layout.js +6 -0
- package/lib/esm/internal/data-table/layout.js.map +1 -0
- package/lib/esm/internal/data-table/virtualization.js +12 -0
- package/lib/esm/internal/data-table/virtualization.js.map +1 -0
- package/lib/esm/node_modules/@vitest/pretty-format/dist/index.js +614 -0
- package/lib/esm/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
- package/lib/esm/node_modules/@vitest/runner/dist/chunk-artifact.js +909 -0
- package/lib/esm/node_modules/@vitest/runner/dist/chunk-artifact.js.map +1 -0
- package/lib/esm/node_modules/@vitest/runner/dist/index.js +1 -0
- package/lib/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +50 -0
- package/lib/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js.map +1 -0
- package/lib/esm/node_modules/@vitest/utils/dist/display.js +424 -0
- package/lib/esm/node_modules/@vitest/utils/dist/display.js.map +1 -0
- package/lib/esm/node_modules/@vitest/utils/dist/helpers.js +43 -0
- package/lib/esm/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
- package/lib/esm/node_modules/@vitest/utils/dist/source-map.js +68 -0
- package/lib/esm/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
- package/lib/esm/node_modules/@vitest/utils/dist/timers.js +19 -0
- package/lib/esm/node_modules/@vitest/utils/dist/timers.js.map +1 -0
- package/lib/esm/node_modules/tinyrainbow/dist/index.js +85 -0
- package/lib/esm/node_modules/tinyrainbow/dist/index.js.map +1 -0
- package/lib/types/components/charts/MetricHistoryChart.d.ts +0 -8
- package/lib/types/components/charts/MetricHistoryChart.d.ts.map +1 -1
- package/lib/types/components/charts/TimeSeriesLineChart.d.ts +0 -4
- package/lib/types/components/charts/TimeSeriesLineChart.d.ts.map +1 -1
- package/lib/types/components/data-table/DataTable.d.ts +1 -5
- package/lib/types/components/data-table/DataTable.d.ts.map +1 -1
- package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts +1 -34
- package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts.map +1 -1
- package/lib/types/internal/charts/metricHistoryChartHelpers.d.ts +4 -0
- package/lib/types/internal/charts/metricHistoryChartHelpers.d.ts.map +1 -0
- package/lib/types/internal/charts/timeSeriesLineChartHelpers.d.ts +9 -0
- package/lib/types/internal/charts/timeSeriesLineChartHelpers.d.ts.map +1 -0
- package/lib/types/internal/data-table/layout.d.ts +4 -0
- package/lib/types/internal/data-table/layout.d.ts.map +1 -0
- package/lib/types/internal/data-table/virtualization.d.ts +29 -0
- package/lib/types/internal/data-table/virtualization.d.ts.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { afterAll as e, afterEach as t } from "../node_modules/@vitest/runner/dist/chunk-artifact.js";
|
|
2
|
+
import { act as n } from "react";
|
|
3
|
+
import { createRoot as r } from "react-dom/client";
|
|
4
|
+
//#region src/__tests__/reactDomTestUtils.tsx
|
|
5
|
+
var i = /* @__PURE__ */ new Map(), a, o = !1, s = async () => {
|
|
6
|
+
let e = [...i.keys()];
|
|
7
|
+
for (let t of e) await n(async () => {
|
|
8
|
+
t.unmount();
|
|
9
|
+
}), i.get(t)?.remove(), i.delete(t);
|
|
10
|
+
document.body.innerHTML = "";
|
|
11
|
+
}, c = () => {
|
|
12
|
+
o || (o = !0, a = Object.getOwnPropertyDescriptor(globalThis, "IS_REACT_ACT_ENVIRONMENT"), Object.defineProperty(globalThis, "IS_REACT_ACT_ENVIRONMENT", {
|
|
13
|
+
value: !0,
|
|
14
|
+
configurable: !0
|
|
15
|
+
}), t(async () => {
|
|
16
|
+
await s();
|
|
17
|
+
}), e(() => {
|
|
18
|
+
if (a == null) {
|
|
19
|
+
Reflect.deleteProperty(globalThis, "IS_REACT_ACT_ENVIRONMENT");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
Object.defineProperty(globalThis, "IS_REACT_ACT_ENVIRONMENT", a);
|
|
23
|
+
}));
|
|
24
|
+
}, l = async (e, t) => {
|
|
25
|
+
let a = t?.container ?? document.createElement("div");
|
|
26
|
+
document.body.contains(a) || document.body.append(a);
|
|
27
|
+
let o = r(a);
|
|
28
|
+
i.set(o, a);
|
|
29
|
+
let s = async (e) => {
|
|
30
|
+
await n(async () => {
|
|
31
|
+
o.render(e);
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
return await s(e), {
|
|
35
|
+
container: a,
|
|
36
|
+
root: o,
|
|
37
|
+
rerender: s,
|
|
38
|
+
unmount: async () => {
|
|
39
|
+
i.has(o) && (await n(async () => {
|
|
40
|
+
o.unmount();
|
|
41
|
+
}), a.remove(), i.delete(o));
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
//#endregion
|
|
46
|
+
export { n as act, s as cleanupReactDomTests, l as renderReactDom, c as setupReactDomTests };
|
|
47
|
+
|
|
48
|
+
//# sourceMappingURL=reactDomTestUtils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reactDomTestUtils.js","names":[],"sources":["../../../src/__tests__/reactDomTestUtils.tsx"],"sourcesContent":["import { act, type ReactNode } from 'react';\nimport { createRoot, type Root } from 'react-dom/client';\nimport { afterAll, afterEach } from 'vitest';\n\ntype RenderReactDomResult = {\n container: HTMLDivElement;\n root: Root;\n rerender: (node: ReactNode) => Promise<void>;\n unmount: () => Promise<void>;\n};\n\nconst mountedRoots = new Map<Root, HTMLDivElement>();\n\nlet previousActEnvironmentDescriptor: PropertyDescriptor | null | undefined;\nlet isSetup = false;\n\nexport { act };\n\nexport const cleanupReactDomTests = async (): Promise<void> => {\n const roots = [...mountedRoots.keys()];\n for (const root of roots) {\n await act(async () => {\n root.unmount();\n });\n\n const container = mountedRoots.get(root);\n container?.remove();\n mountedRoots.delete(root);\n }\n\n document.body.innerHTML = '';\n};\n\nexport const setupReactDomTests = (): void => {\n if (isSetup) {\n return;\n }\n\n isSetup = true;\n previousActEnvironmentDescriptor = Object.getOwnPropertyDescriptor(\n globalThis,\n 'IS_REACT_ACT_ENVIRONMENT',\n );\n\n Object.defineProperty(globalThis, 'IS_REACT_ACT_ENVIRONMENT', {\n value: true,\n configurable: true,\n });\n\n afterEach(async () => {\n await cleanupReactDomTests();\n });\n\n afterAll(() => {\n if (previousActEnvironmentDescriptor == null) {\n Reflect.deleteProperty(globalThis, 'IS_REACT_ACT_ENVIRONMENT');\n return;\n }\n\n Object.defineProperty(\n globalThis,\n 'IS_REACT_ACT_ENVIRONMENT',\n previousActEnvironmentDescriptor,\n );\n });\n};\n\nexport const renderReactDom = async (\n node: ReactNode,\n options?: {\n container?: HTMLDivElement;\n },\n): Promise<RenderReactDomResult> => {\n const container = options?.container ?? document.createElement('div');\n if (!document.body.contains(container)) {\n document.body.append(container);\n }\n\n const root = createRoot(container);\n mountedRoots.set(root, container);\n\n const rerender = async (nextNode: ReactNode): Promise<void> => {\n await act(async () => {\n root.render(nextNode);\n });\n };\n\n const unmount = async (): Promise<void> => {\n if (!mountedRoots.has(root)) {\n return;\n }\n\n await act(async () => {\n root.unmount();\n });\n container.remove();\n mountedRoots.delete(root);\n };\n\n await rerender(node);\n\n return {\n container,\n root,\n rerender,\n unmount,\n };\n};\n"],"mappings":";;;;AAWA,IAAM,oBAAe,IAAI,KAA2B,EAEhD,GACA,IAAU,IAID,IAAuB,YAA2B;CAC7D,IAAM,IAAQ,CAAC,GAAG,EAAa,MAAM,CAAC;CACtC,KAAK,IAAM,KAAQ,GAOjB,AANA,MAAM,EAAI,YAAY;EACpB,EAAK,SAAS;GACd,EAGF,EAD+B,IAAI,EACnC,EAAW,QAAQ,EACnB,EAAa,OAAO,EAAK;CAG3B,SAAS,KAAK,YAAY;GAGf,UAAiC;CACxC,MAIJ,IAAU,IACV,IAAmC,OAAO,yBACxC,YACA,2BACD,EAED,OAAO,eAAe,YAAY,4BAA4B;EAC5D,OAAO;EACP,cAAc;EACf,CAAC,EAEF,EAAU,YAAY;EACpB,MAAM,GAAsB;GAC5B,EAEF,QAAe;EACb,IAAI,KAAoC,MAAM;GAC5C,QAAQ,eAAe,YAAY,2BAA2B;GAC9D;;EAGF,OAAO,eACL,YACA,4BACA,EACD;GACD;GAGS,IAAiB,OAC5B,GACA,MAGkC;CAClC,IAAM,IAAY,GAAS,aAAa,SAAS,cAAc,MAAM;CACrE,AAAK,SAAS,KAAK,SAAS,EAAU,IACpC,SAAS,KAAK,OAAO,EAAU;CAGjC,IAAM,IAAO,EAAW,EAAU;CAClC,EAAa,IAAI,GAAM,EAAU;CAEjC,IAAM,IAAW,OAAO,MAAuC;EAC7D,MAAM,EAAI,YAAY;GACpB,EAAK,OAAO,EAAS;IACrB;;CAiBJ,OAFA,MAAM,EAAS,EAAK,EAEb;EACL;EACA;EACA;EACA,qBAlByC;GACpC,EAAa,IAAI,EAAK,KAI3B,MAAM,EAAI,YAAY;IACpB,EAAK,SAAS;KACd,EACF,EAAU,QAAQ,EAClB,EAAa,OAAO,EAAK;;EAU1B"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/* empty css */
|
|
2
2
|
/* empty css */
|
|
3
|
-
/* empty css */
|
|
4
3
|
//#region src/atomic/molecules/markdown/components/MarkdownTable.css.ts
|
|
5
4
|
var e = "tr18yy0 txvbqb196b txvbqb17h txvbqb2gm txvbqb2et txvbqb1uy txvbqbn8h txvbqbusr txvbqbuvn", t = "tr18yy2 tr18yy1 txvbqbbl8 txvbqbana txvbqbtqh txvbqb17w0";
|
|
6
5
|
//#endregion
|
|
@@ -1,30 +1,12 @@
|
|
|
1
1
|
import { vars as e } from "../../theme/themeContract.js";
|
|
2
2
|
import { chartContainer as t, emptyState as n, tooltip as r, tooltipDate as i, tooltipRow as a, tooltipRowLabel as o, tooltipSwatch as s } from "./metricHistoryChart.css.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { formatAxisTimestamp as c, formatDefaultTimestamp as l, formatDefaultValue as u } from "../../internal/charts/metricHistoryChartHelpers.js";
|
|
4
|
+
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
5
|
+
import { ResponsiveLine as p } from "@nivo/line";
|
|
5
6
|
//#region src/components/charts/MetricHistoryChart.tsx
|
|
6
|
-
|
|
7
|
-
let n = new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 }).format(e);
|
|
8
|
-
return t == null || t.length === 0 ? n : `${n} ${t}`;
|
|
9
|
-
}
|
|
10
|
-
function f(e) {
|
|
11
|
-
let t = new Date(e);
|
|
12
|
-
return Number.isNaN(t.getTime()) ? e : t.toLocaleString(void 0, {
|
|
13
|
-
month: "short",
|
|
14
|
-
day: "2-digit",
|
|
15
|
-
hour: "2-digit",
|
|
16
|
-
minute: "2-digit"
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
function p(e) {
|
|
20
|
-
return e.toLocaleTimeString(void 0, {
|
|
21
|
-
hour: "2-digit",
|
|
22
|
-
minute: "2-digit"
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, formatValue: _ = d, series: v }) => {
|
|
7
|
+
var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = l, formatValue: _ = u, series: v }) => {
|
|
26
8
|
let y = v.filter((e) => e.data.length > 0);
|
|
27
|
-
if (y.length === 0) return /* @__PURE__ */
|
|
9
|
+
if (y.length === 0) return /* @__PURE__ */ d("div", {
|
|
28
10
|
className: n,
|
|
29
11
|
children: h
|
|
30
12
|
});
|
|
@@ -33,9 +15,9 @@ var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, fo
|
|
|
33
15
|
label: e.label,
|
|
34
16
|
unit: e.unit
|
|
35
17
|
}]));
|
|
36
|
-
return /* @__PURE__ */
|
|
18
|
+
return /* @__PURE__ */ d("div", {
|
|
37
19
|
className: t,
|
|
38
|
-
children: /* @__PURE__ */
|
|
20
|
+
children: /* @__PURE__ */ d(p, {
|
|
39
21
|
data: y.map((e) => ({
|
|
40
22
|
id: e.id,
|
|
41
23
|
data: e.data.map((e) => ({
|
|
@@ -77,7 +59,7 @@ var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, fo
|
|
|
77
59
|
axisTop: null,
|
|
78
60
|
axisRight: null,
|
|
79
61
|
axisBottom: {
|
|
80
|
-
format: (e) => e instanceof Date ?
|
|
62
|
+
format: (e) => e instanceof Date ? c(e) : "",
|
|
81
63
|
tickSize: 0,
|
|
82
64
|
tickPadding: 10,
|
|
83
65
|
tickValues: "every 15 minutes"
|
|
@@ -129,7 +111,7 @@ var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, fo
|
|
|
129
111
|
sliceTooltip: ({ slice: e }) => {
|
|
130
112
|
let t = e.points[0], n = String(e.id);
|
|
131
113
|
t?.data.x instanceof Date && (n = t.data.x.toISOString());
|
|
132
|
-
let
|
|
114
|
+
let c = [...e.points].map((e) => {
|
|
133
115
|
let t = Number(e.data.y);
|
|
134
116
|
if (typeof e.data.y == "number" && (t = e.data.y), Number.isNaN(t)) return null;
|
|
135
117
|
let n = String(e.seriesId), r = b[n];
|
|
@@ -141,21 +123,21 @@ var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, fo
|
|
|
141
123
|
unit: r?.unit
|
|
142
124
|
};
|
|
143
125
|
}).filter((e) => e != null);
|
|
144
|
-
return /* @__PURE__ */
|
|
126
|
+
return /* @__PURE__ */ f("div", {
|
|
145
127
|
className: r,
|
|
146
|
-
children: [/* @__PURE__ */
|
|
128
|
+
children: [/* @__PURE__ */ d("p", {
|
|
147
129
|
className: i,
|
|
148
130
|
children: g(n)
|
|
149
|
-
}),
|
|
131
|
+
}), c.map((e) => /* @__PURE__ */ f("div", {
|
|
150
132
|
className: a,
|
|
151
|
-
children: [/* @__PURE__ */
|
|
133
|
+
children: [/* @__PURE__ */ f("span", {
|
|
152
134
|
className: o,
|
|
153
|
-
children: [/* @__PURE__ */
|
|
135
|
+
children: [/* @__PURE__ */ d("span", {
|
|
154
136
|
className: s,
|
|
155
137
|
style: { backgroundColor: e.color },
|
|
156
138
|
"aria-hidden": !0
|
|
157
|
-
}), /* @__PURE__ */
|
|
158
|
-
}), /* @__PURE__ */
|
|
139
|
+
}), /* @__PURE__ */ d("span", { children: e.label })]
|
|
140
|
+
}), /* @__PURE__ */ d("strong", { children: _(e.value, e.unit) })]
|
|
159
141
|
}, `${e.seriesId}-${n}`))]
|
|
160
142
|
});
|
|
161
143
|
},
|
|
@@ -164,12 +146,8 @@ var m = ({ ariaLabel: m, emptyMessage: h = "No data", formatTimestamp: g = f, fo
|
|
|
164
146
|
ariaLabel: m
|
|
165
147
|
})
|
|
166
148
|
});
|
|
167
|
-
}, h = {
|
|
168
|
-
formatDefaultValue: d,
|
|
169
|
-
formatDefaultTimestamp: f,
|
|
170
|
-
formatAxisTimestamp: p
|
|
171
149
|
};
|
|
172
150
|
//#endregion
|
|
173
|
-
export { m as MetricHistoryChart, m as default
|
|
151
|
+
export { m as MetricHistoryChart, m as default };
|
|
174
152
|
|
|
175
153
|
//# sourceMappingURL=MetricHistoryChart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MetricHistoryChart.js","names":[],"sources":["../../../../src/components/charts/MetricHistoryChart.tsx"],"sourcesContent":["import { ResponsiveLine, type SliceTooltipProps } from '@nivo/line';\nimport type { JSX } from 'react';\n\nimport * as styles from './metricHistoryChart.css.js';\nimport { vars } from '../../theme/themeContract.js';\n\nexport type MetricHistoryChartPoint = {\n x: string;\n y: number;\n};\n\nexport type MetricHistoryChartSerie = {\n id: string;\n label: string;\n color: string;\n unit?: string;\n data: readonly MetricHistoryChartPoint[];\n};\n\ntype SlicePointPayload = {\n seriesId: string;\n label: string;\n value: number;\n color: string;\n unit?: string;\n};\n\nexport type MetricHistoryChartProps = {\n series: readonly MetricHistoryChartSerie[];\n ariaLabel: string;\n formatValue?: (value: number, unit?: string) => string;\n formatTimestamp?: (value: string) => string;\n emptyMessage?: string;\n};\n\n/**\n * Formats metric values with an optional unit suffix.\n */\nfunction formatDefaultValue(value: number, unit?: string): string {\n const formatted = new Intl.NumberFormat(undefined, {\n maximumFractionDigits: 2,\n }).format(value);\n\n if (unit == null || unit.length === 0) {\n return formatted;\n }\n\n return `${formatted} ${unit}`;\n}\n\n/**\n * Formats an ISO timestamp for tooltip display.\n */\nfunction formatDefaultTimestamp(value: string): string {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n return value;\n }\n\n return parsed.toLocaleString(undefined, {\n month: 'short',\n day: '2-digit',\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\n/**\n * Formats chart axis ticks as localized times.\n */\nfunction formatAxisTimestamp(value: Date): string {\n return value.toLocaleTimeString(undefined, {\n hour: '2-digit',\n minute: '2-digit',\n });\n}\n\nexport const MetricHistoryChart = ({\n ariaLabel,\n emptyMessage = 'No data',\n formatTimestamp = formatDefaultTimestamp,\n formatValue = formatDefaultValue,\n series,\n}: MetricHistoryChartProps): JSX.Element => {\n const visibleSeries = series.filter((serie) => {\n return serie.data.length > 0;\n });\n\n if (visibleSeries.length === 0) {\n return <div className={styles.emptyState}>{emptyMessage}</div>;\n }\n\n const metadataById = Object.fromEntries(\n visibleSeries.map((serie) => {\n return [\n serie.id,\n {\n color: serie.color,\n label: serie.label,\n unit: serie.unit,\n },\n ];\n }),\n );\n\n const data = visibleSeries.map((serie) => {\n return {\n id: serie.id,\n data: serie.data.map((point) => {\n return {\n x: new Date(point.x),\n y: point.y,\n };\n }),\n };\n });\n\n const legends = [\n {\n anchor: 'bottom' as const,\n direction: 'row' as const,\n translateY: 56,\n itemWidth: 110,\n itemHeight: 16,\n itemsSpacing: 8,\n symbolSize: 10,\n symbolShape: 'circle' as const,\n itemTextColor: vars.colors.textSecondary,\n data: visibleSeries.map((serie) => {\n return {\n id: serie.id,\n label: serie.label,\n color: serie.color,\n };\n }),\n },\n ];\n\n const sliceTooltip = ({\n slice,\n }: SliceTooltipProps<(typeof data)[number]>): JSX.Element => {\n const firstPoint = slice.points[0];\n let timestampValue = String(slice.id);\n if (firstPoint?.data.x instanceof Date) {\n timestampValue = firstPoint.data.x.toISOString();\n }\n\n const points = [...slice.points]\n .map((point): SlicePointPayload | null => {\n let value = Number(point.data.y);\n if (typeof point.data.y === 'number') {\n value = point.data.y;\n }\n\n if (Number.isNaN(value)) {\n return null;\n }\n\n const seriesId = String(point.seriesId);\n const metadata = metadataById[seriesId];\n\n return {\n seriesId,\n label: metadata?.label ?? seriesId,\n value,\n color: point.seriesColor,\n unit: metadata?.unit,\n };\n })\n .filter((point): point is SlicePointPayload => {\n return point != null;\n });\n\n return (\n <div className={styles.tooltip}>\n <p className={styles.tooltipDate}>{formatTimestamp(timestampValue)}</p>\n {points.map((point) => {\n return (\n <div\n key={`${point.seriesId}-${timestampValue}`}\n className={styles.tooltipRow}\n >\n <span className={styles.tooltipRowLabel}>\n <span\n className={styles.tooltipSwatch}\n style={{ backgroundColor: point.color }}\n aria-hidden\n />\n <span>{point.label}</span>\n </span>\n <strong>{formatValue(point.value, point.unit)}</strong>\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className={styles.chartContainer}>\n <ResponsiveLine\n data={data}\n margin={{ top: 14, right: 16, bottom: 74, left: 52 }}\n colors={(serie) => {\n return metadataById[String(serie.id)]?.color ?? vars.colors.primary;\n }}\n xScale={{\n type: 'time',\n format: 'native',\n precision: 'minute',\n useUTC: false,\n }}\n xFormat=\"time:%Y-%m-%dT%H:%M:%S.%LZ\"\n yScale={{ type: 'linear', min: 'auto', max: 'auto' }}\n curve=\"monotoneX\"\n lineWidth={2.5}\n pointSize={4}\n pointBorderWidth={2}\n pointBorderColor={{ from: 'seriesColor', modifiers: [['darker', 0.2]] }}\n enableArea\n areaOpacity={0.1}\n enableGridX={false}\n enableGridY\n axisTop={null}\n axisRight={null}\n axisBottom={{\n format: (value) => {\n if (!(value instanceof Date)) {\n return '';\n }\n\n return formatAxisTimestamp(value);\n },\n tickSize: 0,\n tickPadding: 10,\n tickValues: 'every 15 minutes',\n }}\n axisLeft={{\n tickSize: 0,\n tickPadding: 8,\n tickValues: 5,\n format: (value) => {\n if (typeof value !== 'number') {\n return '';\n }\n\n return new Intl.NumberFormat(undefined, {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n },\n }}\n enablePoints\n useMesh\n legends={legends}\n theme={{\n grid: {\n line: {\n stroke: vars.colors.borderLight,\n },\n },\n axis: {\n ticks: {\n text: {\n fill: vars.colors.textMuted,\n fontSize: 12,\n },\n },\n },\n crosshair: {\n line: {\n stroke: vars.colors.border,\n strokeWidth: 1,\n strokeDasharray: '4 4',\n },\n },\n tooltip: {\n container: {\n background: 'transparent',\n boxShadow: 'none',\n padding: 0,\n },\n },\n }}\n sliceTooltip={sliceTooltip}\n enableSlices=\"x\"\n role=\"img\"\n ariaLabel={ariaLabel}\n />\n </div>\n );\n};\n\nexport default MetricHistoryChart;\n\nexport const __test = {\n formatDefaultValue,\n formatDefaultTimestamp,\n formatAxisTimestamp,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MetricHistoryChart.js","names":[],"sources":["../../../../src/components/charts/MetricHistoryChart.tsx"],"sourcesContent":["import { ResponsiveLine, type SliceTooltipProps } from '@nivo/line';\nimport type { JSX } from 'react';\n\nimport * as styles from './metricHistoryChart.css.js';\nimport {\n formatAxisTimestamp,\n formatDefaultTimestamp,\n formatDefaultValue,\n} from '../../internal/charts/metricHistoryChartHelpers.js';\nimport { vars } from '../../theme/themeContract.js';\n\nexport type MetricHistoryChartPoint = {\n x: string;\n y: number;\n};\n\nexport type MetricHistoryChartSerie = {\n id: string;\n label: string;\n color: string;\n unit?: string;\n data: readonly MetricHistoryChartPoint[];\n};\n\ntype SlicePointPayload = {\n seriesId: string;\n label: string;\n value: number;\n color: string;\n unit?: string;\n};\n\nexport type MetricHistoryChartProps = {\n series: readonly MetricHistoryChartSerie[];\n ariaLabel: string;\n formatValue?: (value: number, unit?: string) => string;\n formatTimestamp?: (value: string) => string;\n emptyMessage?: string;\n};\n\nexport const MetricHistoryChart = ({\n ariaLabel,\n emptyMessage = 'No data',\n formatTimestamp = formatDefaultTimestamp,\n formatValue = formatDefaultValue,\n series,\n}: MetricHistoryChartProps): JSX.Element => {\n const visibleSeries = series.filter((serie) => {\n return serie.data.length > 0;\n });\n\n if (visibleSeries.length === 0) {\n return <div className={styles.emptyState}>{emptyMessage}</div>;\n }\n\n const metadataById = Object.fromEntries(\n visibleSeries.map((serie) => {\n return [\n serie.id,\n {\n color: serie.color,\n label: serie.label,\n unit: serie.unit,\n },\n ];\n }),\n );\n\n const data = visibleSeries.map((serie) => {\n return {\n id: serie.id,\n data: serie.data.map((point) => {\n return {\n x: new Date(point.x),\n y: point.y,\n };\n }),\n };\n });\n\n const legends = [\n {\n anchor: 'bottom' as const,\n direction: 'row' as const,\n translateY: 56,\n itemWidth: 110,\n itemHeight: 16,\n itemsSpacing: 8,\n symbolSize: 10,\n symbolShape: 'circle' as const,\n itemTextColor: vars.colors.textSecondary,\n data: visibleSeries.map((serie) => {\n return {\n id: serie.id,\n label: serie.label,\n color: serie.color,\n };\n }),\n },\n ];\n\n const sliceTooltip = ({\n slice,\n }: SliceTooltipProps<(typeof data)[number]>): JSX.Element => {\n const firstPoint = slice.points[0];\n let timestampValue = String(slice.id);\n if (firstPoint?.data.x instanceof Date) {\n timestampValue = firstPoint.data.x.toISOString();\n }\n\n const points = [...slice.points]\n .map((point): SlicePointPayload | null => {\n let value = Number(point.data.y);\n if (typeof point.data.y === 'number') {\n value = point.data.y;\n }\n\n if (Number.isNaN(value)) {\n return null;\n }\n\n const seriesId = String(point.seriesId);\n const metadata = metadataById[seriesId];\n\n return {\n seriesId,\n label: metadata?.label ?? seriesId,\n value,\n color: point.seriesColor,\n unit: metadata?.unit,\n };\n })\n .filter((point): point is SlicePointPayload => {\n return point != null;\n });\n\n return (\n <div className={styles.tooltip}>\n <p className={styles.tooltipDate}>{formatTimestamp(timestampValue)}</p>\n {points.map((point) => {\n return (\n <div\n key={`${point.seriesId}-${timestampValue}`}\n className={styles.tooltipRow}\n >\n <span className={styles.tooltipRowLabel}>\n <span\n className={styles.tooltipSwatch}\n style={{ backgroundColor: point.color }}\n aria-hidden\n />\n <span>{point.label}</span>\n </span>\n <strong>{formatValue(point.value, point.unit)}</strong>\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className={styles.chartContainer}>\n <ResponsiveLine\n data={data}\n margin={{ top: 14, right: 16, bottom: 74, left: 52 }}\n colors={(serie) => {\n return metadataById[String(serie.id)]?.color ?? vars.colors.primary;\n }}\n xScale={{\n type: 'time',\n format: 'native',\n precision: 'minute',\n useUTC: false,\n }}\n xFormat=\"time:%Y-%m-%dT%H:%M:%S.%LZ\"\n yScale={{ type: 'linear', min: 'auto', max: 'auto' }}\n curve=\"monotoneX\"\n lineWidth={2.5}\n pointSize={4}\n pointBorderWidth={2}\n pointBorderColor={{ from: 'seriesColor', modifiers: [['darker', 0.2]] }}\n enableArea\n areaOpacity={0.1}\n enableGridX={false}\n enableGridY\n axisTop={null}\n axisRight={null}\n axisBottom={{\n format: (value) => {\n if (!(value instanceof Date)) {\n return '';\n }\n\n return formatAxisTimestamp(value);\n },\n tickSize: 0,\n tickPadding: 10,\n tickValues: 'every 15 minutes',\n }}\n axisLeft={{\n tickSize: 0,\n tickPadding: 8,\n tickValues: 5,\n format: (value) => {\n if (typeof value !== 'number') {\n return '';\n }\n\n return new Intl.NumberFormat(undefined, {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n },\n }}\n enablePoints\n useMesh\n legends={legends}\n theme={{\n grid: {\n line: {\n stroke: vars.colors.borderLight,\n },\n },\n axis: {\n ticks: {\n text: {\n fill: vars.colors.textMuted,\n fontSize: 12,\n },\n },\n },\n crosshair: {\n line: {\n stroke: vars.colors.border,\n strokeWidth: 1,\n strokeDasharray: '4 4',\n },\n },\n tooltip: {\n container: {\n background: 'transparent',\n boxShadow: 'none',\n padding: 0,\n },\n },\n }}\n sliceTooltip={sliceTooltip}\n enableSlices=\"x\"\n role=\"img\"\n ariaLabel={ariaLabel}\n />\n </div>\n );\n};\n\nexport default MetricHistoryChart;\n"],"mappings":"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"}
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
import { vars as e } from "../../theme/themeContract.js";
|
|
2
2
|
import { chartContainer as t, tooltip as n, tooltipDate as r, tooltipRow as i, tooltipRowLabel as a, tooltipSwatch as o } from "./timeSeriesLineChart.css.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { formatDayTick as s, getVisibleDayTicks as c } from "../../internal/charts/timeSeriesLineChartHelpers.js";
|
|
4
|
+
import { jsx as l, jsxs as u } from "react/jsx-runtime";
|
|
5
|
+
import { ResponsiveLine as d } from "@nivo/line";
|
|
5
6
|
//#region src/components/charts/TimeSeriesLineChart.tsx
|
|
6
|
-
var
|
|
7
|
-
|
|
8
|
-
let t = e[0];
|
|
9
|
-
if (t == null || t.data.length <= u) return t == null ? [] : t.data.map((e) => e.x);
|
|
10
|
-
let n = Math.ceil(t.data.length / u), r = t.data.filter((e, t) => t % n === 0).map((e) => e.x), i = t.data.at(-1);
|
|
11
|
-
return i != null && r.at(-1) !== i.x && r.push(i.x), r;
|
|
12
|
-
}
|
|
13
|
-
function f(e) {
|
|
14
|
-
return (/* @__PURE__ */ new Date(`${e}T00:00:00Z`)).toLocaleDateString(void 0, {
|
|
15
|
-
month: "short",
|
|
16
|
-
day: "2-digit"
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
var p = (u) => {
|
|
20
|
-
let { ariaLabel: p, categoryColorById: m, categoryLabel: h, categoryOrder: g, formatValue: _, series: v } = u, y = d(v), b = g, x = (e) => b.includes(e), S = [{
|
|
7
|
+
var f = (f) => {
|
|
8
|
+
let { ariaLabel: p, categoryColorById: m, categoryLabel: h, categoryOrder: g, formatValue: _, series: v } = f, y = c(v), b = g, x = (e) => b.includes(e), S = [{
|
|
21
9
|
anchor: "bottom",
|
|
22
10
|
direction: "row",
|
|
23
11
|
translateY: 56,
|
|
@@ -33,9 +21,9 @@ var p = (u) => {
|
|
|
33
21
|
color: m[e]
|
|
34
22
|
}))
|
|
35
23
|
}];
|
|
36
|
-
return /* @__PURE__ */
|
|
24
|
+
return /* @__PURE__ */ l("div", {
|
|
37
25
|
className: t,
|
|
38
|
-
children: /* @__PURE__ */
|
|
26
|
+
children: /* @__PURE__ */ l(d, {
|
|
39
27
|
data: v,
|
|
40
28
|
margin: {
|
|
41
29
|
top: 14,
|
|
@@ -66,7 +54,7 @@ var p = (u) => {
|
|
|
66
54
|
axisRight: null,
|
|
67
55
|
axisBottom: {
|
|
68
56
|
tickValues: y,
|
|
69
|
-
format: (e) =>
|
|
57
|
+
format: (e) => s(String(e)),
|
|
70
58
|
tickSize: 0,
|
|
71
59
|
tickPadding: 10
|
|
72
60
|
},
|
|
@@ -100,31 +88,31 @@ var p = (u) => {
|
|
|
100
88
|
} }
|
|
101
89
|
},
|
|
102
90
|
sliceTooltip: ({ slice: e }) => {
|
|
103
|
-
let t = String(e.id),
|
|
91
|
+
let t = String(e.id), c = g[0] ?? null, d = [...e.points].map((e) => {
|
|
104
92
|
let t = 0;
|
|
105
93
|
typeof e.data.y == "number" && (t = e.data.y);
|
|
106
|
-
let n =
|
|
94
|
+
let n = c;
|
|
107
95
|
return typeof e.seriesId == "string" && x(e.seriesId) && (n = e.seriesId), n == null ? null : {
|
|
108
96
|
seriesId: n,
|
|
109
97
|
data: { y: t },
|
|
110
98
|
color: e.seriesColor
|
|
111
99
|
};
|
|
112
100
|
}).filter((e) => e != null).sort((e, t) => g.indexOf(e.seriesId) - g.indexOf(t.seriesId));
|
|
113
|
-
return /* @__PURE__ */
|
|
101
|
+
return /* @__PURE__ */ u("div", {
|
|
114
102
|
className: n,
|
|
115
|
-
children: [/* @__PURE__ */
|
|
103
|
+
children: [/* @__PURE__ */ l("p", {
|
|
116
104
|
className: r,
|
|
117
|
-
children:
|
|
118
|
-
}),
|
|
105
|
+
children: s(t)
|
|
106
|
+
}), d.map((e) => /* @__PURE__ */ u("div", {
|
|
119
107
|
className: i,
|
|
120
|
-
children: [/* @__PURE__ */
|
|
108
|
+
children: [/* @__PURE__ */ u("span", {
|
|
121
109
|
className: a,
|
|
122
|
-
children: [/* @__PURE__ */
|
|
110
|
+
children: [/* @__PURE__ */ l("span", {
|
|
123
111
|
className: o,
|
|
124
112
|
style: { backgroundColor: e.color },
|
|
125
113
|
"aria-hidden": !0
|
|
126
|
-
}), /* @__PURE__ */
|
|
127
|
-
}), /* @__PURE__ */
|
|
114
|
+
}), /* @__PURE__ */ l("span", { children: h(e.seriesId) })]
|
|
115
|
+
}), /* @__PURE__ */ l("strong", { children: _(e.data.y) })]
|
|
128
116
|
}, `${t}-${e.seriesId}`))]
|
|
129
117
|
});
|
|
130
118
|
},
|
|
@@ -133,8 +121,8 @@ var p = (u) => {
|
|
|
133
121
|
ariaLabel: p
|
|
134
122
|
})
|
|
135
123
|
});
|
|
136
|
-
}
|
|
124
|
+
};
|
|
137
125
|
//#endregion
|
|
138
|
-
export {
|
|
126
|
+
export { f as TimeSeriesLineChart, f as default };
|
|
139
127
|
|
|
140
128
|
//# sourceMappingURL=TimeSeriesLineChart.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimeSeriesLineChart.js","names":[],"sources":["../../../../src/components/charts/TimeSeriesLineChart.tsx"],"sourcesContent":["import { ResponsiveLine, type SliceTooltipProps } from '@nivo/line';\nimport type { JSX } from 'react';\n\nimport * as styles from './timeSeriesLineChart.css.js';\nimport { vars } from '../../theme/themeContract.js';\n\nexport type TimeSeriesLineChartPoint = {\n x: string;\n y: number;\n};\n\nexport type TimeSeriesLineChartSerie<Category extends string> = {\n id: Category;\n data: readonly TimeSeriesLineChartPoint[];\n};\n\ntype SlicePointPayload<Category extends string> = {\n seriesId: Category;\n data: {\n y: number;\n };\n color: string;\n};\n\nexport type TimeSeriesLineChartProps<Category extends string> = {\n series: readonly TimeSeriesLineChartSerie<Category>[];\n categoryOrder: readonly Category[];\n categoryColorById: Readonly<Record<Category, string>>;\n categoryLabel: (category: Category) => string;\n formatValue: (value: number) => string;\n ariaLabel: string;\n};\n\nconst MAX_X_TICKS = 6;\n\n/**\n * Limits the number of visible day ticks while always keeping the last point.\n */\nfunction getVisibleDayTicks<Category extends string>(\n series: readonly TimeSeriesLineChartSerie<Category>[],\n): readonly string[] {\n const firstSerie = series[0];\n if (firstSerie == null || firstSerie.data.length <= MAX_X_TICKS) {\n if (firstSerie == null) {\n return [];\n }\n\n return firstSerie.data.map((point) => {\n return point.x;\n });\n }\n\n const step = Math.ceil(firstSerie.data.length / MAX_X_TICKS);\n const visibleTicks = firstSerie.data\n .filter((_, index) => {\n return index % step === 0;\n })\n .map((point) => {\n return point.x;\n });\n\n const lastPoint = firstSerie.data.at(-1);\n if (lastPoint != null && visibleTicks.at(-1) !== lastPoint.x) {\n visibleTicks.push(lastPoint.x);\n }\n\n return visibleTicks;\n}\n\n/**\n * Formats a `YYYY-MM-DD` key into a short month/day label for the x-axis.\n */\nfunction formatDayTick(dayKey: string): string {\n const parsed = new Date(`${dayKey}T00:00:00Z`);\n return parsed.toLocaleDateString(undefined, {\n month: 'short',\n day: '2-digit',\n });\n}\n\nexport const TimeSeriesLineChart = <Category extends string>(\n props: TimeSeriesLineChartProps<Category>,\n): JSX.Element => {\n const {\n ariaLabel,\n categoryColorById,\n categoryLabel,\n categoryOrder,\n formatValue,\n series,\n } = props;\n\n const visibleTicks = getVisibleDayTicks(series);\n const categoryOrderString = categoryOrder as readonly string[];\n const isCategory = (value: string): value is Category => {\n return categoryOrderString.includes(value);\n };\n\n const legends = [\n {\n anchor: 'bottom' as const,\n direction: 'row' as const,\n translateY: 56,\n itemWidth: 90,\n itemHeight: 16,\n itemsSpacing: 8,\n symbolSize: 10,\n symbolShape: 'circle' as const,\n itemTextColor: vars.colors.textSecondary,\n data: categoryOrder.map((category) => {\n return {\n id: category,\n label: categoryLabel(category),\n color: categoryColorById[category],\n };\n }),\n },\n ];\n\n const colorById = (serie: { id: string | number }): string => {\n if (typeof serie.id !== 'string' || !isCategory(serie.id)) {\n return vars.colors.primary;\n }\n\n return categoryColorById[serie.id];\n };\n\n const sliceTooltip = ({\n slice,\n }: SliceTooltipProps<TimeSeriesLineChartSerie<Category>>): JSX.Element => {\n const dayKey = String(slice.id);\n const fallbackCategory = categoryOrder[0] ?? null;\n const points = [...slice.points]\n .map((point): SlicePointPayload<Category> | null => {\n let credits = 0;\n if (typeof point.data.y === 'number') {\n credits = point.data.y;\n }\n\n let seriesId = fallbackCategory;\n if (typeof point.seriesId === 'string' && isCategory(point.seriesId)) {\n seriesId = point.seriesId;\n }\n if (seriesId == null) {\n return null;\n }\n\n return {\n seriesId,\n data: { y: credits },\n color: point.seriesColor,\n };\n })\n .filter((point): point is SlicePointPayload<Category> => {\n return point != null;\n })\n .sort((left, right) => {\n const leftIndex = categoryOrder.indexOf(left.seriesId);\n const rightIndex = categoryOrder.indexOf(right.seriesId);\n\n return leftIndex - rightIndex;\n });\n\n return (\n <div className={styles.tooltip}>\n <p className={styles.tooltipDate}>{formatDayTick(dayKey)}</p>\n {points.map((point) => {\n return (\n <div\n key={`${dayKey}-${point.seriesId}`}\n className={styles.tooltipRow}\n >\n <span className={styles.tooltipRowLabel}>\n <span\n className={styles.tooltipSwatch}\n style={{ backgroundColor: point.color }}\n aria-hidden\n />\n <span>{categoryLabel(point.seriesId)}</span>\n </span>\n <strong>{formatValue(point.data.y)}</strong>\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className={styles.chartContainer}>\n <ResponsiveLine\n data={series}\n margin={{ top: 14, right: 16, bottom: 74, left: 52 }}\n colors={colorById}\n xScale={{ type: 'point' }}\n yScale={{ type: 'linear', min: 0, max: 'auto' }}\n curve=\"monotoneX\"\n lineWidth={2.5}\n pointSize={4}\n pointBorderWidth={2}\n pointBorderColor={{ from: 'seriesColor', modifiers: [['darker', 0.2]] }}\n enableArea\n areaOpacity={0.1}\n enableGridX={false}\n enableGridY\n axisTop={null}\n axisRight={null}\n axisBottom={{\n tickValues: visibleTicks,\n format: (value) => {\n return formatDayTick(String(value));\n },\n tickSize: 0,\n tickPadding: 10,\n }}\n axisLeft={{\n tickSize: 0,\n tickPadding: 8,\n tickValues: 5,\n format: (value) => {\n if (typeof value !== 'number') {\n return '';\n }\n\n return new Intl.NumberFormat('en-US', {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n },\n }}\n enablePoints\n useMesh\n legends={legends}\n theme={{\n grid: {\n line: {\n stroke: vars.colors.borderLight,\n },\n },\n axis: {\n ticks: {\n text: {\n fill: vars.colors.textMuted,\n fontSize: 12,\n },\n },\n },\n crosshair: {\n line: {\n stroke: vars.colors.border,\n strokeWidth: 1,\n strokeDasharray: '4 4',\n },\n },\n tooltip: {\n container: {\n background: 'transparent',\n boxShadow: 'none',\n padding: 0,\n },\n },\n }}\n sliceTooltip={sliceTooltip}\n enableSlices=\"x\"\n role=\"img\"\n ariaLabel={ariaLabel}\n />\n </div>\n );\n};\n\nexport default TimeSeriesLineChart;\n\nexport const __test = {\n formatDayTick,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"TimeSeriesLineChart.js","names":[],"sources":["../../../../src/components/charts/TimeSeriesLineChart.tsx"],"sourcesContent":["import { ResponsiveLine, type SliceTooltipProps } from '@nivo/line';\nimport type { JSX } from 'react';\n\nimport * as styles from './timeSeriesLineChart.css.js';\nimport {\n formatDayTick,\n getVisibleDayTicks,\n} from '../../internal/charts/timeSeriesLineChartHelpers.js';\nimport { vars } from '../../theme/themeContract.js';\n\nexport type TimeSeriesLineChartPoint = {\n x: string;\n y: number;\n};\n\nexport type TimeSeriesLineChartSerie<Category extends string> = {\n id: Category;\n data: readonly TimeSeriesLineChartPoint[];\n};\n\ntype SlicePointPayload<Category extends string> = {\n seriesId: Category;\n data: {\n y: number;\n };\n color: string;\n};\n\nexport type TimeSeriesLineChartProps<Category extends string> = {\n series: readonly TimeSeriesLineChartSerie<Category>[];\n categoryOrder: readonly Category[];\n categoryColorById: Readonly<Record<Category, string>>;\n categoryLabel: (category: Category) => string;\n formatValue: (value: number) => string;\n ariaLabel: string;\n};\n\nexport const TimeSeriesLineChart = <Category extends string>(\n props: TimeSeriesLineChartProps<Category>,\n): JSX.Element => {\n const {\n ariaLabel,\n categoryColorById,\n categoryLabel,\n categoryOrder,\n formatValue,\n series,\n } = props;\n\n const visibleTicks = getVisibleDayTicks(series);\n const categoryOrderString = categoryOrder as readonly string[];\n const isCategory = (value: string): value is Category => {\n return categoryOrderString.includes(value);\n };\n\n const legends = [\n {\n anchor: 'bottom' as const,\n direction: 'row' as const,\n translateY: 56,\n itemWidth: 90,\n itemHeight: 16,\n itemsSpacing: 8,\n symbolSize: 10,\n symbolShape: 'circle' as const,\n itemTextColor: vars.colors.textSecondary,\n data: categoryOrder.map((category) => {\n return {\n id: category,\n label: categoryLabel(category),\n color: categoryColorById[category],\n };\n }),\n },\n ];\n\n const colorById = (serie: { id: string | number }): string => {\n if (typeof serie.id !== 'string' || !isCategory(serie.id)) {\n return vars.colors.primary;\n }\n\n return categoryColorById[serie.id];\n };\n\n const sliceTooltip = ({\n slice,\n }: SliceTooltipProps<TimeSeriesLineChartSerie<Category>>): JSX.Element => {\n const dayKey = String(slice.id);\n const fallbackCategory = categoryOrder[0] ?? null;\n const points = [...slice.points]\n .map((point): SlicePointPayload<Category> | null => {\n let credits = 0;\n if (typeof point.data.y === 'number') {\n credits = point.data.y;\n }\n\n let seriesId = fallbackCategory;\n if (typeof point.seriesId === 'string' && isCategory(point.seriesId)) {\n seriesId = point.seriesId;\n }\n if (seriesId == null) {\n return null;\n }\n\n return {\n seriesId,\n data: { y: credits },\n color: point.seriesColor,\n };\n })\n .filter((point): point is SlicePointPayload<Category> => {\n return point != null;\n })\n .sort((left, right) => {\n const leftIndex = categoryOrder.indexOf(left.seriesId);\n const rightIndex = categoryOrder.indexOf(right.seriesId);\n\n return leftIndex - rightIndex;\n });\n\n return (\n <div className={styles.tooltip}>\n <p className={styles.tooltipDate}>{formatDayTick(dayKey)}</p>\n {points.map((point) => {\n return (\n <div\n key={`${dayKey}-${point.seriesId}`}\n className={styles.tooltipRow}\n >\n <span className={styles.tooltipRowLabel}>\n <span\n className={styles.tooltipSwatch}\n style={{ backgroundColor: point.color }}\n aria-hidden\n />\n <span>{categoryLabel(point.seriesId)}</span>\n </span>\n <strong>{formatValue(point.data.y)}</strong>\n </div>\n );\n })}\n </div>\n );\n };\n\n return (\n <div className={styles.chartContainer}>\n <ResponsiveLine\n data={series}\n margin={{ top: 14, right: 16, bottom: 74, left: 52 }}\n colors={colorById}\n xScale={{ type: 'point' }}\n yScale={{ type: 'linear', min: 0, max: 'auto' }}\n curve=\"monotoneX\"\n lineWidth={2.5}\n pointSize={4}\n pointBorderWidth={2}\n pointBorderColor={{ from: 'seriesColor', modifiers: [['darker', 0.2]] }}\n enableArea\n areaOpacity={0.1}\n enableGridX={false}\n enableGridY\n axisTop={null}\n axisRight={null}\n axisBottom={{\n tickValues: visibleTicks,\n format: (value) => {\n return formatDayTick(String(value));\n },\n tickSize: 0,\n tickPadding: 10,\n }}\n axisLeft={{\n tickSize: 0,\n tickPadding: 8,\n tickValues: 5,\n format: (value) => {\n if (typeof value !== 'number') {\n return '';\n }\n\n return new Intl.NumberFormat('en-US', {\n notation: 'compact',\n maximumFractionDigits: 1,\n }).format(value);\n },\n }}\n enablePoints\n useMesh\n legends={legends}\n theme={{\n grid: {\n line: {\n stroke: vars.colors.borderLight,\n },\n },\n axis: {\n ticks: {\n text: {\n fill: vars.colors.textMuted,\n fontSize: 12,\n },\n },\n },\n crosshair: {\n line: {\n stroke: vars.colors.border,\n strokeWidth: 1,\n strokeDasharray: '4 4',\n },\n },\n tooltip: {\n container: {\n background: 'transparent',\n boxShadow: 'none',\n padding: 0,\n },\n },\n }}\n sliceTooltip={sliceTooltip}\n enableSlices=\"x\"\n role=\"img\"\n ariaLabel={ariaLabel}\n />\n </div>\n );\n};\n\nexport default TimeSeriesLineChart;\n"],"mappings":"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"}
|
|
@@ -1,47 +1,48 @@
|
|
|
1
1
|
import { cx as e } from "../../theme/tools.js";
|
|
2
2
|
import { useUiTranslation as t } from "../../i18n/useUiTranslation.js";
|
|
3
|
-
import { alignRecipe as n, body as r, bodyContained as i, cell as a, container as o, containerWithContainedBody as s, densityRecipe as
|
|
4
|
-
import {
|
|
3
|
+
import { alignRecipe as n, body as r, bodyContained as i, cell as a, container as o, containerWithContainedBody as s, densityRecipe as ee, emptyCell as te, emptyRow as ne, header as re, headerCell as c, headerRow as l, hideBelowRecipe as u, primaryCell as d, primaryHeaderCell as f, row as p, rowEven as m, rowOdd as h, rowStateRecipe as g, stickyHeader as _ } from "./DataTable.css.js";
|
|
4
|
+
import { buildDataTableInlineTemplate as v } from "../../internal/data-table/layout.js";
|
|
5
|
+
import { Fragment as y, jsx as b, jsxs as x } from "react/jsx-runtime";
|
|
5
6
|
//#region src/components/data-table/DataTable.tsx
|
|
6
|
-
var
|
|
7
|
+
var S = (e) => e == null ? null : u({ minVisibleAt: e }), C = ({ columns: u, rows: C, getRowId: ie, emptyState: w, className: T, headerClassName: E, bodyClassName: D, rowClassName: O, gridTemplateClassName: k, gridTemplateColumns: A, kind: j, density: M, headerBehavior: N, bodyScrollMode: P = "page", rowState: F, classes: I, ariaLabel: L, ariaLabelledBy: R, bodyFooterNode: z }) => {
|
|
7
8
|
let { t: B } = t(), V = j ?? "default", H = L ?? B("common.table.label");
|
|
8
9
|
R != null && (H = void 0);
|
|
9
|
-
let U = /* @__PURE__ */
|
|
10
|
-
className: e(
|
|
10
|
+
let U = /* @__PURE__ */ b("div", {
|
|
11
|
+
className: e(te, I?.emptyCell),
|
|
11
12
|
children: B("common.table.empty")
|
|
12
|
-
}), W =
|
|
13
|
-
k ?? (q =
|
|
13
|
+
}), W = w ?? U, G = C.length === 0, K = P === "contained", q;
|
|
14
|
+
k ?? (q = v(u.length, A));
|
|
14
15
|
let J = null;
|
|
15
|
-
N?.sticky === !0 && (J =
|
|
16
|
+
N?.sticky === !0 && (J = _);
|
|
16
17
|
let Y;
|
|
17
18
|
N?.offsetTop != null && (Y = { top: N.offsetTop });
|
|
18
|
-
let X = [
|
|
19
|
+
let X = [ee({ density: M ?? "default" })];
|
|
19
20
|
k != null && X.push(k);
|
|
20
21
|
let Z;
|
|
21
|
-
Z = G ? /* @__PURE__ */
|
|
22
|
-
className: e(
|
|
22
|
+
Z = G ? /* @__PURE__ */ b("div", {
|
|
23
|
+
className: e(ne, I?.emptyRow),
|
|
23
24
|
role: "row",
|
|
24
|
-
children: /* @__PURE__ */
|
|
25
|
+
children: /* @__PURE__ */ b("div", {
|
|
25
26
|
role: "cell",
|
|
26
27
|
children: W
|
|
27
28
|
})
|
|
28
|
-
}) : /* @__PURE__ */
|
|
29
|
-
let i =
|
|
30
|
-
s != null && o.push(
|
|
29
|
+
}) : /* @__PURE__ */ b(y, { children: C.map((t, r) => {
|
|
30
|
+
let i = ie(t, r), o = [p({ kind: V }), I?.row], s = F?.(t, r);
|
|
31
|
+
s != null && o.push(g({ state: s })), r % 2 == 0 ? o.push(m({ kind: V }), I?.rowEven) : o.push(h({ kind: V }), I?.rowOdd);
|
|
31
32
|
for (let e of X) o.push(e);
|
|
32
33
|
if (O != null) {
|
|
33
34
|
let e = O(t, r);
|
|
34
35
|
e != null && o.push(e);
|
|
35
36
|
}
|
|
36
|
-
return /* @__PURE__ */
|
|
37
|
+
return /* @__PURE__ */ b("div", {
|
|
37
38
|
role: "row",
|
|
38
39
|
className: e(...o),
|
|
39
40
|
style: q,
|
|
40
|
-
children:
|
|
41
|
-
let i = [a({ kind: V }), I?.cell], o =
|
|
42
|
-
o != null && i.push(o), r.className != null && i.push(r.className), r.isPrimary && i.push(
|
|
41
|
+
children: u.map((r) => {
|
|
42
|
+
let i = [a({ kind: V }), I?.cell], o = S(r.minVisibleAt);
|
|
43
|
+
o != null && i.push(o), r.className != null && i.push(r.className), r.isPrimary && i.push(d, I?.primaryCell), r.align != null && i.push(n({ align: r.align }));
|
|
43
44
|
let s = r.cell(t);
|
|
44
|
-
return /* @__PURE__ */
|
|
45
|
+
return /* @__PURE__ */ b("div", {
|
|
45
46
|
role: "cell",
|
|
46
47
|
className: e(...i),
|
|
47
48
|
children: s
|
|
@@ -50,41 +51,38 @@ var C = "minmax(0, 1fr)", w = (e) => e == null ? null : m({ minVisibleAt: e }),
|
|
|
50
51
|
}, i);
|
|
51
52
|
}) });
|
|
52
53
|
let Q = null, $ = null;
|
|
53
|
-
return K && (Q = s, $ = i), /* @__PURE__ */
|
|
54
|
-
className: e(o({ kind: V }), Q, I?.container,
|
|
54
|
+
return K && (Q = s, $ = i), /* @__PURE__ */ x("div", {
|
|
55
|
+
className: e(o({ kind: V }), Q, I?.container, T),
|
|
55
56
|
role: "table",
|
|
56
57
|
"aria-label": H,
|
|
57
58
|
"aria-labelledby": R,
|
|
58
59
|
"data-scroll-mode": P,
|
|
59
|
-
children: [/* @__PURE__ */
|
|
60
|
-
className: e(
|
|
60
|
+
children: [/* @__PURE__ */ b("div", {
|
|
61
|
+
className: e(re({ kind: V }), J, I?.header, E),
|
|
61
62
|
style: Y,
|
|
62
63
|
role: "rowgroup",
|
|
63
|
-
children: /* @__PURE__ */
|
|
64
|
-
className: e(
|
|
64
|
+
children: /* @__PURE__ */ b("div", {
|
|
65
|
+
className: e(l, I?.headerRow, ...X),
|
|
65
66
|
role: "row",
|
|
66
67
|
style: q,
|
|
67
|
-
children:
|
|
68
|
-
let r = [
|
|
69
|
-
return i != null && r.push(i), t.className != null && r.push(t.className), t.isPrimary && r.push(
|
|
68
|
+
children: u.map((t) => {
|
|
69
|
+
let r = [c({ kind: V }), I?.headerCell], i = S(t.minVisibleAt);
|
|
70
|
+
return i != null && r.push(i), t.className != null && r.push(t.className), t.isPrimary && r.push(f, I?.primaryHeaderCell), t.align != null && r.push(n({ align: t.align })), /* @__PURE__ */ b("div", {
|
|
70
71
|
role: "columnheader",
|
|
71
72
|
className: e(...r),
|
|
72
73
|
children: t.header
|
|
73
74
|
}, t.id);
|
|
74
75
|
})
|
|
75
76
|
})
|
|
76
|
-
}), /* @__PURE__ */
|
|
77
|
-
className: e(r({ kind: V }), $, I?.body,
|
|
77
|
+
}), /* @__PURE__ */ x("div", {
|
|
78
|
+
className: e(r({ kind: V }), $, I?.body, D),
|
|
78
79
|
role: "rowgroup",
|
|
79
80
|
"data-scroll-mode": P,
|
|
80
81
|
children: [Z, z]
|
|
81
82
|
})]
|
|
82
83
|
});
|
|
83
|
-
}, D = {
|
|
84
|
-
getVisibilityClass: w,
|
|
85
|
-
buildInlineTemplate: T
|
|
86
84
|
};
|
|
87
85
|
//#endregion
|
|
88
|
-
export {
|
|
86
|
+
export { C as DataTable };
|
|
89
87
|
|
|
90
88
|
//# sourceMappingURL=DataTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.js","names":[],"sources":["../../../../src/components/data-table/DataTable.tsx"],"sourcesContent":["import { type CSSProperties, type JSX, type ReactNode } from 'react';\n\nimport * as styles from './DataTable.css.js';\nimport type { DataTableBreakpoint } from './tableBreakpoints.js';\nimport { cx } from '../../theme/tools.js';\nimport { useUiTranslation } from '../../i18n/useUiTranslation.js';\nimport type { SlotClasses } from '../../styles/slots.js';\n\nexport type DataTableColumn<Row> = {\n id: string;\n header: JSX.Element | string;\n cell: (row: Row) => JSX.Element | string | null;\n minVisibleAt?: DataTableBreakpoint;\n className?: string;\n isPrimary?: boolean;\n align?: 'left' | 'center' | 'right';\n priority?: 'primary' | 'important' | 'secondary' | 'debug';\n mobileRole?:\n | 'title'\n | 'subtitle'\n | 'meta'\n | 'badge'\n | 'status'\n | 'action'\n | 'hidden';\n};\n\nexport type GetRowId<Row> = (row: Row, index: number) => string;\n\nexport type DataTableKind = NonNullable<\n Parameters<typeof styles.container>[0]\n>['kind'];\n\nexport type DataTableDensity = NonNullable<\n Parameters<typeof styles.densityRecipe>[0]\n>['density'];\n\nexport type DataTableRowState = NonNullable<\n Parameters<typeof styles.rowStateRecipe>[0]\n>['state'];\n\nexport type DataTableHeaderBehavior = {\n sticky?: boolean;\n offsetTop?: number;\n};\n\nexport type DataTableBodyScrollMode = 'page' | 'contained';\n\ntype DataTableSlot =\n | 'container'\n | 'header'\n | 'headerRow'\n | 'headerCell'\n | 'primaryHeaderCell'\n | 'body'\n | 'row'\n | 'rowEven'\n | 'rowOdd'\n | 'cell'\n | 'primaryCell'\n | 'emptyRow'\n | 'emptyCell';\n\nexport type DataTableProps<Row> = {\n columns: readonly DataTableColumn<Row>[];\n rows: readonly Row[];\n getRowId: GetRowId<Row>;\n emptyState?: JSX.Element;\n className?: string;\n headerClassName?: string;\n bodyClassName?: string;\n rowClassName?: (row: Row, index: number) => string | null | undefined;\n gridTemplateClassName?: string;\n gridTemplateColumns?: string;\n kind?: DataTableKind;\n density?: DataTableDensity;\n headerBehavior?: DataTableHeaderBehavior;\n bodyScrollMode?: DataTableBodyScrollMode;\n rowState?: (row: Row, index: number) => DataTableRowState;\n classes?: SlotClasses<DataTableSlot>;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n bodyFooterNode?: ReactNode;\n};\n\nconst DEFAULT_TEMPLATE_CELL = 'minmax(0, 1fr)';\n\nconst getVisibilityClass = (minVisibleAt?: DataTableBreakpoint) => {\n if (minVisibleAt == null) {\n return null;\n }\n\n return styles.hideBelowRecipe({ minVisibleAt });\n};\n\nconst buildInlineTemplate = (\n columnCount: number,\n gridTemplateColumns?: string,\n): CSSProperties => {\n if (typeof gridTemplateColumns === 'string' && gridTemplateColumns !== '') {\n return { gridTemplateColumns };\n }\n return {\n gridTemplateColumns: `repeat(${columnCount}, ${DEFAULT_TEMPLATE_CELL})`,\n };\n};\n\n/**\n * Generic responsive data table component.\n */\nexport const DataTable = <Row,>({\n columns,\n rows,\n getRowId,\n emptyState,\n className,\n headerClassName,\n bodyClassName,\n rowClassName,\n gridTemplateClassName,\n gridTemplateColumns,\n kind,\n density,\n headerBehavior,\n bodyScrollMode = 'page',\n rowState,\n classes,\n ariaLabel,\n ariaLabelledBy,\n bodyFooterNode,\n}: DataTableProps<Row>): JSX.Element => {\n const { t } = useUiTranslation();\n const resolvedKind: DataTableKind = kind ?? 'default';\n const resolvedAriaLabel = ariaLabel ?? t('common.table.label');\n let tableAriaLabel: string | undefined = resolvedAriaLabel;\n if (ariaLabelledBy != null) {\n tableAriaLabel = undefined;\n }\n const defaultEmptyState = (\n <div className={cx(styles.emptyCell, classes?.emptyCell)}>\n {t('common.table.empty')}\n </div>\n ) as JSX.Element;\n const resolvedEmptyState = emptyState ?? defaultEmptyState;\n const showEmpty = rows.length === 0;\n const hasContainedBodyScroll = bodyScrollMode === 'contained';\n\n let inlineTemplateStyle: CSSProperties | undefined;\n if (gridTemplateClassName == null) {\n inlineTemplateStyle = buildInlineTemplate(\n columns.length,\n gridTemplateColumns,\n );\n }\n let headerStickyClass: string | null = null;\n if (headerBehavior?.sticky === true) {\n headerStickyClass = styles.stickyHeader;\n }\n let headerStyle: CSSProperties | undefined;\n if (headerBehavior?.offsetTop != null) {\n headerStyle = { top: headerBehavior.offsetTop };\n }\n\n const resolvedDensity: DataTableDensity = density ?? 'default';\n const sharedRowClasses: string[] = [\n styles.densityRecipe({ density: resolvedDensity }),\n ];\n if (gridTemplateClassName != null) {\n sharedRowClasses.push(gridTemplateClassName);\n }\n\n let rowsContent: JSX.Element;\n if (showEmpty) {\n rowsContent = (\n <div className={cx(styles.emptyRow, classes?.emptyRow)} role=\"row\">\n <div role=\"cell\">{resolvedEmptyState}</div>\n </div>\n );\n } else {\n rowsContent = (\n <>\n {rows.map((row, index) => {\n const rowId = getRowId(row, index);\n const rowClasses = [styles.row({ kind: resolvedKind }), classes?.row];\n const state = rowState?.(row, index);\n if (state != null) {\n rowClasses.push(styles.rowStateRecipe({ state }));\n }\n if (index % 2 === 0) {\n rowClasses.push(\n styles.rowEven({ kind: resolvedKind }),\n classes?.rowEven,\n );\n } else {\n rowClasses.push(\n styles.rowOdd({ kind: resolvedKind }),\n classes?.rowOdd,\n );\n }\n for (const sharedClass of sharedRowClasses) {\n rowClasses.push(sharedClass);\n }\n\n if (rowClassName != null) {\n const customClass = rowClassName(row, index);\n if (customClass != null) {\n rowClasses.push(customClass);\n }\n }\n\n return (\n <div\n key={rowId}\n role=\"row\"\n className={cx(...rowClasses)}\n style={inlineTemplateStyle}\n >\n {columns.map((column) => {\n const cellClasses = [\n styles.cell({ kind: resolvedKind }),\n classes?.cell,\n ];\n const visibilityClass = getVisibilityClass(column.minVisibleAt);\n\n if (visibilityClass != null) {\n cellClasses.push(visibilityClass);\n }\n\n if (column.className != null) {\n cellClasses.push(column.className);\n }\n if (column.isPrimary) {\n cellClasses.push(styles.primaryCell, classes?.primaryCell);\n }\n if (column.align != null) {\n cellClasses.push(styles.alignRecipe({ align: column.align }));\n }\n\n const content = column.cell(row);\n\n return (\n <div\n key={column.id}\n role=\"cell\"\n className={cx(...cellClasses)}\n >\n {content}\n </div>\n );\n })}\n </div>\n );\n })}\n </>\n );\n }\n\n let containedContainerClassName: string | null = null;\n let containedBodyClassName: string | null = null;\n if (hasContainedBodyScroll) {\n containedContainerClassName = styles.containerWithContainedBody;\n containedBodyClassName = styles.bodyContained;\n }\n\n return (\n <div\n className={cx(\n styles.container({ kind: resolvedKind }),\n containedContainerClassName,\n classes?.container,\n className,\n )}\n role=\"table\"\n aria-label={tableAriaLabel}\n aria-labelledby={ariaLabelledBy}\n data-scroll-mode={bodyScrollMode}\n >\n <div\n className={cx(\n styles.header({ kind: resolvedKind }),\n headerStickyClass,\n classes?.header,\n headerClassName,\n )}\n style={headerStyle}\n role=\"rowgroup\"\n >\n <div\n className={cx(\n styles.headerRow,\n classes?.headerRow,\n ...sharedRowClasses,\n )}\n role=\"row\"\n style={inlineTemplateStyle}\n >\n {columns.map((column) => {\n const headerClasses = [\n styles.headerCell({ kind: resolvedKind }),\n classes?.headerCell,\n ];\n const visibilityClass = getVisibilityClass(column.minVisibleAt);\n if (visibilityClass != null) {\n headerClasses.push(visibilityClass);\n }\n\n if (column.className != null) {\n headerClasses.push(column.className);\n }\n if (column.isPrimary) {\n headerClasses.push(\n styles.primaryHeaderCell,\n classes?.primaryHeaderCell,\n );\n }\n if (column.align != null) {\n headerClasses.push(styles.alignRecipe({ align: column.align }));\n }\n\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n className={cx(...headerClasses)}\n >\n {column.header}\n </div>\n );\n })}\n </div>\n </div>\n\n <div\n className={cx(\n styles.body({ kind: resolvedKind }),\n containedBodyClassName,\n classes?.body,\n bodyClassName,\n )}\n role=\"rowgroup\"\n data-scroll-mode={bodyScrollMode}\n >\n {rowsContent}\n {bodyFooterNode}\n </div>\n </div>\n );\n};\n\nexport const __test = {\n getVisibilityClass,\n buildInlineTemplate,\n} as const;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.js","names":[],"sources":["../../../../src/components/data-table/DataTable.tsx"],"sourcesContent":["import { type CSSProperties, type JSX, type ReactNode } from 'react';\n\nimport * as styles from './DataTable.css.js';\nimport type { DataTableBreakpoint } from './tableBreakpoints.js';\nimport { buildDataTableInlineTemplate } from '../../internal/data-table/layout.js';\nimport { cx } from '../../theme/tools.js';\nimport { useUiTranslation } from '../../i18n/useUiTranslation.js';\nimport type { SlotClasses } from '../../styles/slots.js';\n\nexport type DataTableColumn<Row> = {\n id: string;\n header: JSX.Element | string;\n cell: (row: Row) => JSX.Element | string | null;\n minVisibleAt?: DataTableBreakpoint;\n className?: string;\n isPrimary?: boolean;\n align?: 'left' | 'center' | 'right';\n priority?: 'primary' | 'important' | 'secondary' | 'debug';\n mobileRole?:\n | 'title'\n | 'subtitle'\n | 'meta'\n | 'badge'\n | 'status'\n | 'action'\n | 'hidden';\n};\n\nexport type GetRowId<Row> = (row: Row, index: number) => string;\n\nexport type DataTableKind = NonNullable<\n Parameters<typeof styles.container>[0]\n>['kind'];\n\nexport type DataTableDensity = NonNullable<\n Parameters<typeof styles.densityRecipe>[0]\n>['density'];\n\nexport type DataTableRowState = NonNullable<\n Parameters<typeof styles.rowStateRecipe>[0]\n>['state'];\n\nexport type DataTableHeaderBehavior = {\n sticky?: boolean;\n offsetTop?: number;\n};\n\nexport type DataTableBodyScrollMode = 'page' | 'contained';\n\ntype DataTableSlot =\n | 'container'\n | 'header'\n | 'headerRow'\n | 'headerCell'\n | 'primaryHeaderCell'\n | 'body'\n | 'row'\n | 'rowEven'\n | 'rowOdd'\n | 'cell'\n | 'primaryCell'\n | 'emptyRow'\n | 'emptyCell';\n\nexport type DataTableProps<Row> = {\n columns: readonly DataTableColumn<Row>[];\n rows: readonly Row[];\n getRowId: GetRowId<Row>;\n emptyState?: JSX.Element;\n className?: string;\n headerClassName?: string;\n bodyClassName?: string;\n rowClassName?: (row: Row, index: number) => string | null | undefined;\n gridTemplateClassName?: string;\n gridTemplateColumns?: string;\n kind?: DataTableKind;\n density?: DataTableDensity;\n headerBehavior?: DataTableHeaderBehavior;\n bodyScrollMode?: DataTableBodyScrollMode;\n rowState?: (row: Row, index: number) => DataTableRowState;\n classes?: SlotClasses<DataTableSlot>;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n bodyFooterNode?: ReactNode;\n};\n\nconst getVisibilityClass = (minVisibleAt?: DataTableBreakpoint) => {\n if (minVisibleAt == null) {\n return null;\n }\n\n return styles.hideBelowRecipe({ minVisibleAt });\n};\n\n/**\n * Generic responsive data table component.\n */\nexport const DataTable = <Row,>({\n columns,\n rows,\n getRowId,\n emptyState,\n className,\n headerClassName,\n bodyClassName,\n rowClassName,\n gridTemplateClassName,\n gridTemplateColumns,\n kind,\n density,\n headerBehavior,\n bodyScrollMode = 'page',\n rowState,\n classes,\n ariaLabel,\n ariaLabelledBy,\n bodyFooterNode,\n}: DataTableProps<Row>): JSX.Element => {\n const { t } = useUiTranslation();\n const resolvedKind: DataTableKind = kind ?? 'default';\n const resolvedAriaLabel = ariaLabel ?? t('common.table.label');\n let tableAriaLabel: string | undefined = resolvedAriaLabel;\n if (ariaLabelledBy != null) {\n tableAriaLabel = undefined;\n }\n const defaultEmptyState = (\n <div className={cx(styles.emptyCell, classes?.emptyCell)}>\n {t('common.table.empty')}\n </div>\n ) as JSX.Element;\n const resolvedEmptyState = emptyState ?? defaultEmptyState;\n const showEmpty = rows.length === 0;\n const hasContainedBodyScroll = bodyScrollMode === 'contained';\n\n let inlineTemplateStyle: CSSProperties | undefined;\n if (gridTemplateClassName == null) {\n inlineTemplateStyle = buildDataTableInlineTemplate(\n columns.length,\n gridTemplateColumns,\n );\n }\n let headerStickyClass: string | null = null;\n if (headerBehavior?.sticky === true) {\n headerStickyClass = styles.stickyHeader;\n }\n let headerStyle: CSSProperties | undefined;\n if (headerBehavior?.offsetTop != null) {\n headerStyle = { top: headerBehavior.offsetTop };\n }\n\n const resolvedDensity: DataTableDensity = density ?? 'default';\n const sharedRowClasses: string[] = [\n styles.densityRecipe({ density: resolvedDensity }),\n ];\n if (gridTemplateClassName != null) {\n sharedRowClasses.push(gridTemplateClassName);\n }\n\n let rowsContent: JSX.Element;\n if (showEmpty) {\n rowsContent = (\n <div className={cx(styles.emptyRow, classes?.emptyRow)} role=\"row\">\n <div role=\"cell\">{resolvedEmptyState}</div>\n </div>\n );\n } else {\n rowsContent = (\n <>\n {rows.map((row, index) => {\n const rowId = getRowId(row, index);\n const rowClasses = [styles.row({ kind: resolvedKind }), classes?.row];\n const state = rowState?.(row, index);\n if (state != null) {\n rowClasses.push(styles.rowStateRecipe({ state }));\n }\n if (index % 2 === 0) {\n rowClasses.push(\n styles.rowEven({ kind: resolvedKind }),\n classes?.rowEven,\n );\n } else {\n rowClasses.push(\n styles.rowOdd({ kind: resolvedKind }),\n classes?.rowOdd,\n );\n }\n for (const sharedClass of sharedRowClasses) {\n rowClasses.push(sharedClass);\n }\n\n if (rowClassName != null) {\n const customClass = rowClassName(row, index);\n if (customClass != null) {\n rowClasses.push(customClass);\n }\n }\n\n return (\n <div\n key={rowId}\n role=\"row\"\n className={cx(...rowClasses)}\n style={inlineTemplateStyle}\n >\n {columns.map((column) => {\n const cellClasses = [\n styles.cell({ kind: resolvedKind }),\n classes?.cell,\n ];\n const visibilityClass = getVisibilityClass(column.minVisibleAt);\n\n if (visibilityClass != null) {\n cellClasses.push(visibilityClass);\n }\n\n if (column.className != null) {\n cellClasses.push(column.className);\n }\n if (column.isPrimary) {\n cellClasses.push(styles.primaryCell, classes?.primaryCell);\n }\n if (column.align != null) {\n cellClasses.push(styles.alignRecipe({ align: column.align }));\n }\n\n const content = column.cell(row);\n\n return (\n <div\n key={column.id}\n role=\"cell\"\n className={cx(...cellClasses)}\n >\n {content}\n </div>\n );\n })}\n </div>\n );\n })}\n </>\n );\n }\n\n let containedContainerClassName: string | null = null;\n let containedBodyClassName: string | null = null;\n if (hasContainedBodyScroll) {\n containedContainerClassName = styles.containerWithContainedBody;\n containedBodyClassName = styles.bodyContained;\n }\n\n return (\n <div\n className={cx(\n styles.container({ kind: resolvedKind }),\n containedContainerClassName,\n classes?.container,\n className,\n )}\n role=\"table\"\n aria-label={tableAriaLabel}\n aria-labelledby={ariaLabelledBy}\n data-scroll-mode={bodyScrollMode}\n >\n <div\n className={cx(\n styles.header({ kind: resolvedKind }),\n headerStickyClass,\n classes?.header,\n headerClassName,\n )}\n style={headerStyle}\n role=\"rowgroup\"\n >\n <div\n className={cx(\n styles.headerRow,\n classes?.headerRow,\n ...sharedRowClasses,\n )}\n role=\"row\"\n style={inlineTemplateStyle}\n >\n {columns.map((column) => {\n const headerClasses = [\n styles.headerCell({ kind: resolvedKind }),\n classes?.headerCell,\n ];\n const visibilityClass = getVisibilityClass(column.minVisibleAt);\n if (visibilityClass != null) {\n headerClasses.push(visibilityClass);\n }\n\n if (column.className != null) {\n headerClasses.push(column.className);\n }\n if (column.isPrimary) {\n headerClasses.push(\n styles.primaryHeaderCell,\n classes?.primaryHeaderCell,\n );\n }\n if (column.align != null) {\n headerClasses.push(styles.alignRecipe({ align: column.align }));\n }\n\n return (\n <div\n key={column.id}\n role=\"columnheader\"\n className={cx(...headerClasses)}\n >\n {column.header}\n </div>\n );\n })}\n </div>\n </div>\n\n <div\n className={cx(\n styles.body({ kind: resolvedKind }),\n containedBodyClassName,\n classes?.body,\n bodyClassName,\n )}\n role=\"rowgroup\"\n data-scroll-mode={bodyScrollMode}\n >\n {rowsContent}\n {bodyFooterNode}\n </div>\n </div>\n );\n};\n"],"mappings":"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"}
|