@plumile/ui 0.1.122 → 0.1.130

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/lib/esm/__tests__/reactDomTestUtils.js +48 -0
  2. package/lib/esm/__tests__/reactDomTestUtils.js.map +1 -0
  3. package/lib/esm/admin/organisms/admin_sidebar/adminSidebar.css.js +0 -1
  4. package/lib/esm/admin/theme/adminSurface.css.js +1 -0
  5. package/lib/esm/atomic/molecules/markdown/components/MarkdownTable.css.js +0 -1
  6. package/lib/esm/atomic/molecules/markdown/markdownVars.css.js +1 -0
  7. package/lib/esm/backoffice/atoms/tag/Tag.js +9 -8
  8. package/lib/esm/backoffice/atoms/tag/Tag.js.map +1 -1
  9. package/lib/esm/components/charts/MetricHistoryChart.js +17 -39
  10. package/lib/esm/components/charts/MetricHistoryChart.js.map +1 -1
  11. package/lib/esm/components/charts/TimeSeriesLineChart.js +37 -49
  12. package/lib/esm/components/charts/TimeSeriesLineChart.js.map +1 -1
  13. package/lib/esm/components/data-table/DataTable.js +33 -35
  14. package/lib/esm/components/data-table/DataTable.js.map +1 -1
  15. package/lib/esm/components/data-table/VirtualizedConnectionTable.js +48 -60
  16. package/lib/esm/components/data-table/VirtualizedConnectionTable.js.map +1 -1
  17. package/lib/esm/index.js +107 -107
  18. package/lib/esm/internal/charts/metricHistoryChartHelpers.js +24 -0
  19. package/lib/esm/internal/charts/metricHistoryChartHelpers.js.map +1 -0
  20. package/lib/esm/internal/charts/timeSeriesLineChartHelpers.js +68 -0
  21. package/lib/esm/internal/charts/timeSeriesLineChartHelpers.js.map +1 -0
  22. package/lib/esm/internal/data-table/layout.js +6 -0
  23. package/lib/esm/internal/data-table/layout.js.map +1 -0
  24. package/lib/esm/internal/data-table/virtualization.js +12 -0
  25. package/lib/esm/internal/data-table/virtualization.js.map +1 -0
  26. package/lib/esm/node_modules/@vitest/pretty-format/dist/index.js +614 -0
  27. package/lib/esm/node_modules/@vitest/pretty-format/dist/index.js.map +1 -0
  28. package/lib/esm/node_modules/@vitest/runner/dist/chunk-artifact.js +909 -0
  29. package/lib/esm/node_modules/@vitest/runner/dist/chunk-artifact.js.map +1 -0
  30. package/lib/esm/node_modules/@vitest/runner/dist/index.js +1 -0
  31. package/lib/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js +50 -0
  32. package/lib/esm/node_modules/@vitest/utils/dist/chunk-pathe.M-eThtNZ.js.map +1 -0
  33. package/lib/esm/node_modules/@vitest/utils/dist/display.js +424 -0
  34. package/lib/esm/node_modules/@vitest/utils/dist/display.js.map +1 -0
  35. package/lib/esm/node_modules/@vitest/utils/dist/helpers.js +43 -0
  36. package/lib/esm/node_modules/@vitest/utils/dist/helpers.js.map +1 -0
  37. package/lib/esm/node_modules/@vitest/utils/dist/source-map.js +68 -0
  38. package/lib/esm/node_modules/@vitest/utils/dist/source-map.js.map +1 -0
  39. package/lib/esm/node_modules/@vitest/utils/dist/timers.js +19 -0
  40. package/lib/esm/node_modules/@vitest/utils/dist/timers.js.map +1 -0
  41. package/lib/esm/node_modules/tinyrainbow/dist/index.js +85 -0
  42. package/lib/esm/node_modules/tinyrainbow/dist/index.js.map +1 -0
  43. package/lib/esm/shared/currencyAmount.js +36 -23
  44. package/lib/esm/shared/currencyAmount.js.map +1 -1
  45. package/lib/types/backoffice/atoms/tag/Tag.d.ts +2 -1
  46. package/lib/types/backoffice/atoms/tag/Tag.d.ts.map +1 -1
  47. package/lib/types/components/charts/MetricHistoryChart.d.ts +0 -8
  48. package/lib/types/components/charts/MetricHistoryChart.d.ts.map +1 -1
  49. package/lib/types/components/charts/TimeSeriesLineChart.d.ts +2 -4
  50. package/lib/types/components/charts/TimeSeriesLineChart.d.ts.map +1 -1
  51. package/lib/types/components/data-table/DataTable.d.ts +1 -5
  52. package/lib/types/components/data-table/DataTable.d.ts.map +1 -1
  53. package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts +1 -34
  54. package/lib/types/components/data-table/VirtualizedConnectionTable.d.ts.map +1 -1
  55. package/lib/types/index.d.ts +1 -1
  56. package/lib/types/index.d.ts.map +1 -1
  57. package/lib/types/internal/charts/metricHistoryChartHelpers.d.ts +4 -0
  58. package/lib/types/internal/charts/metricHistoryChartHelpers.d.ts.map +1 -0
  59. package/lib/types/internal/charts/timeSeriesLineChartHelpers.d.ts +29 -0
  60. package/lib/types/internal/charts/timeSeriesLineChartHelpers.d.ts.map +1 -0
  61. package/lib/types/internal/data-table/layout.d.ts +4 -0
  62. package/lib/types/internal/data-table/layout.d.ts.map +1 -0
  63. package/lib/types/internal/data-table/virtualization.d.ts +29 -0
  64. package/lib/types/internal/data-table/virtualization.d.ts.map +1 -0
  65. package/lib/types/shared/currencyAmount.d.ts +5 -1
  66. package/lib/types/shared/currencyAmount.d.ts.map +1 -1
  67. package/package.json +3 -3
@@ -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"}
@@ -4,7 +4,6 @@
4
4
  /* empty css */
5
5
  /* empty css */
6
6
  /* empty css */
7
- /* empty css */
8
7
  /* empty css */
9
8
  import { createRuntimeFn as e } from "@vanilla-extract/recipes/createRuntimeFn";
10
9
  //#region src/admin/organisms/admin_sidebar/adminSidebar.css.ts
@@ -6,6 +6,7 @@
6
6
  /* empty css */
7
7
  /* empty css */
8
8
  /* empty css */
9
+ /* empty css */
9
10
  import { createRuntimeFn as e } from "@vanilla-extract/recipes/createRuntimeFn";
10
11
  //#region src/admin/theme/adminSurface.css.ts
11
12
  var t = e({
@@ -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,3 +1,4 @@
1
+ /* empty css */
1
2
  //#region src/atomic/molecules/markdown/markdownVars.css.ts
2
3
  var e = "var(--_1pjotr20)", t = "var(--_1pjotr21)", n = "var(--_1pjotr22)", r = "var(--_1pjotr23)", i = "var(--_1pjotr24)", a = "var(--_1pjotr25)";
3
4
  //#endregion
@@ -5,14 +5,14 @@ import { useId as i } from "react";
5
5
  import { jsx as a, jsxs as o } from "react/jsx-runtime";
6
6
  import { useTranslation as s } from "react-i18next";
7
7
  //#region src/backoffice/atoms/tag/Tag.tsx
8
- var c = ({ children: c, tone: l = "neutral", className: u, onRemove: d, removeLabel: f }) => {
9
- let { t: p } = s("ui", { useSuspense: !1 }), m = i(), h = typeof d == "function", g = f ?? p("backoffice.tag.remove", { defaultValue: "Remove" }), _ = null;
10
- return h && (_ = /* @__PURE__ */ a("button", {
8
+ var c = ({ children: c, tone: l = "neutral", className: u, title: d, onRemove: f, removeLabel: p }) => {
9
+ let { t: m } = s("ui", { useSuspense: !1 }), h = i(), g = typeof f == "function", _ = p ?? m("backoffice.tag.remove", { defaultValue: "Remove" }), v = null;
10
+ return g && (v = /* @__PURE__ */ a("button", {
11
11
  type: "button",
12
12
  className: n,
13
- onClick: d,
14
- "aria-label": g,
15
- "aria-describedby": m,
13
+ onClick: f,
14
+ "aria-label": _,
15
+ "aria-describedby": h,
16
16
  children: /* @__PURE__ */ a(t, {
17
17
  width: 14,
18
18
  height: 14,
@@ -20,10 +20,11 @@ var c = ({ children: c, tone: l = "neutral", className: u, onRemove: d, removeLa
20
20
  })
21
21
  })), /* @__PURE__ */ o("span", {
22
22
  className: e(r({ tone: l }), u),
23
+ title: d,
23
24
  children: [/* @__PURE__ */ a("span", {
24
- id: m,
25
+ id: h,
25
26
  children: c
26
- }), _]
27
+ }), v]
27
28
  });
28
29
  };
29
30
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"Tag.js","names":[],"sources":["../../../../../src/backoffice/atoms/tag/Tag.tsx"],"sourcesContent":["import { type JSX, type ReactNode, useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { RecipeVariants } from '@vanilla-extract/recipes';\n\nimport { ModalCloseSvg } from '../../../icons/ModalCloseSvg.js';\n\nimport * as styles from './tag.css.js';\nimport { cx } from '../../../theme/tools.js';\n\nexport type TagTone = NonNullable<\n NonNullable<RecipeVariants<typeof styles.rootRecipe>>['tone']\n>;\n\nexport type TagProps = {\n children: ReactNode;\n tone?: TagTone;\n className?: string;\n onRemove?: () => void;\n removeLabel?: string;\n};\n\nexport const Tag = ({\n children,\n tone = 'neutral',\n className,\n onRemove,\n removeLabel,\n}: TagProps): JSX.Element => {\n const { t } = useTranslation('ui', { useSuspense: false });\n const labelId = useId();\n const isRemovable = typeof onRemove === 'function';\n const resolvedRemoveLabel =\n removeLabel ?? t('backoffice.tag.remove', { defaultValue: 'Remove' });\n\n let removeButtonNode: JSX.Element | null = null;\n if (isRemovable) {\n removeButtonNode = (\n <button\n type=\"button\"\n className={styles.removeButton}\n onClick={onRemove}\n aria-label={resolvedRemoveLabel}\n aria-describedby={labelId}\n >\n <ModalCloseSvg width={14} height={14} aria-hidden=\"true\" />\n </button>\n );\n }\n\n return (\n <span className={cx(styles.rootRecipe({ tone }), className)}>\n <span id={labelId}>{children}</span>\n {removeButtonNode}\n </span>\n );\n};\n\nexport default Tag;\n"],"mappings":";;;;;;;AAqBA,IAAa,KAAO,EAClB,aACA,UAAO,WACP,cACA,aACA,qBAC2B;CAC3B,IAAM,EAAE,SAAM,EAAe,MAAM,EAAE,aAAa,IAAO,CAAC,EACpD,IAAU,GAAO,EACjB,IAAc,OAAO,KAAa,YAClC,IACJ,KAAe,EAAE,yBAAyB,EAAE,cAAc,UAAU,CAAC,EAEnE,IAAuC;CAe3C,OAdI,MACF,IACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAW;EACX,SAAS;EACT,cAAY;EACZ,oBAAkB;YAElB,kBAAC,GAAD;GAAe,OAAO;GAAI,QAAQ;GAAI,eAAY;GAAS,CAAA;EACpD,CAAA,GAKX,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAkB,EAAE,SAAM,CAAC,EAAE,EAAU;YAA3D,CACE,kBAAC,QAAD;GAAM,IAAI;GAAU;GAAgB,CAAA,EACnC,EACI"}
1
+ {"version":3,"file":"Tag.js","names":[],"sources":["../../../../../src/backoffice/atoms/tag/Tag.tsx"],"sourcesContent":["import { type JSX, type ReactNode, useId } from 'react';\nimport { useTranslation } from 'react-i18next';\nimport type { RecipeVariants } from '@vanilla-extract/recipes';\n\nimport { ModalCloseSvg } from '../../../icons/ModalCloseSvg.js';\n\nimport * as styles from './tag.css.js';\nimport { cx } from '../../../theme/tools.js';\n\nexport type TagTone = NonNullable<\n NonNullable<RecipeVariants<typeof styles.rootRecipe>>['tone']\n>;\n\nexport type TagProps = {\n children: ReactNode;\n tone?: TagTone;\n className?: string;\n title?: string;\n onRemove?: () => void;\n removeLabel?: string;\n};\n\nexport const Tag = ({\n children,\n tone = 'neutral',\n className,\n title,\n onRemove,\n removeLabel,\n}: TagProps): JSX.Element => {\n const { t } = useTranslation('ui', { useSuspense: false });\n const labelId = useId();\n const isRemovable = typeof onRemove === 'function';\n const resolvedRemoveLabel =\n removeLabel ?? t('backoffice.tag.remove', { defaultValue: 'Remove' });\n\n let removeButtonNode: JSX.Element | null = null;\n if (isRemovable) {\n removeButtonNode = (\n <button\n type=\"button\"\n className={styles.removeButton}\n onClick={onRemove}\n aria-label={resolvedRemoveLabel}\n aria-describedby={labelId}\n >\n <ModalCloseSvg width={14} height={14} aria-hidden=\"true\" />\n </button>\n );\n }\n\n return (\n <span className={cx(styles.rootRecipe({ tone }), className)} title={title}>\n <span id={labelId}>{children}</span>\n {removeButtonNode}\n </span>\n );\n};\n\nexport default Tag;\n"],"mappings":";;;;;;;AAsBA,IAAa,KAAO,EAClB,aACA,UAAO,WACP,cACA,UACA,aACA,qBAC2B;CAC3B,IAAM,EAAE,SAAM,EAAe,MAAM,EAAE,aAAa,IAAO,CAAC,EACpD,IAAU,GAAO,EACjB,IAAc,OAAO,KAAa,YAClC,IACJ,KAAe,EAAE,yBAAyB,EAAE,cAAc,UAAU,CAAC,EAEnE,IAAuC;CAe3C,OAdI,MACF,IACE,kBAAC,UAAD;EACE,MAAK;EACL,WAAW;EACX,SAAS;EACT,cAAY;EACZ,oBAAkB;YAElB,kBAAC,GAAD;GAAe,OAAO;GAAI,QAAQ;GAAI,eAAY;GAAS,CAAA;EACpD,CAAA,GAKX,kBAAC,QAAD;EAAM,WAAW,EAAG,EAAkB,EAAE,SAAM,CAAC,EAAE,EAAU;EAAS;YAApE,CACE,kBAAC,QAAD;GAAM,IAAI;GAAU;GAAgB,CAAA,EACnC,EACI"}
@@ -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 { jsx as c, jsxs as l } from "react/jsx-runtime";
4
- import { ResponsiveLine as u } from "@nivo/line";
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
- function d(e, t) {
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__ */ c("div", {
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__ */ c("div", {
18
+ return /* @__PURE__ */ d("div", {
37
19
  className: t,
38
- children: /* @__PURE__ */ c(u, {
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 ? p(e) : "",
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 u = [...e.points].map((e) => {
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__ */ l("div", {
126
+ return /* @__PURE__ */ f("div", {
145
127
  className: r,
146
- children: [/* @__PURE__ */ c("p", {
128
+ children: [/* @__PURE__ */ d("p", {
147
129
  className: i,
148
130
  children: g(n)
149
- }), u.map((e) => /* @__PURE__ */ l("div", {
131
+ }), c.map((e) => /* @__PURE__ */ f("div", {
150
132
  className: a,
151
- children: [/* @__PURE__ */ l("span", {
133
+ children: [/* @__PURE__ */ f("span", {
152
134
  className: o,
153
- children: [/* @__PURE__ */ c("span", {
135
+ children: [/* @__PURE__ */ d("span", {
154
136
  className: s,
155
137
  style: { backgroundColor: e.color },
156
138
  "aria-hidden": !0
157
- }), /* @__PURE__ */ c("span", { children: e.label })]
158
- }), /* @__PURE__ */ c("strong", { children: _(e.value, e.unit) })]
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, h as __test };
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":";;;;;;AAwCA,IAAa,KAAsB,EACjC,cACA,kBAAe,WACf,qBAAkB,GAClB,iBAAc,GACd,gBAC0C;CAC1C,IAAM,IAAgB,EAAO,QAAQ,MAC5B,EAAM,KAAK,SAAS,EAC3B;CAEF,IAAI,EAAc,WAAW,GAC3B,OAAO,kBAAC,OAAD;EAAK,WAAW;YAAoB;EAAmB,CAAA;CAGhE,IAAM,IAAe,OAAO,YAC1B,EAAc,KAAK,MACV,CACL,EAAM,IACN;EACE,OAAO,EAAM;EACb,OAAO,EAAM;EACb,MAAM,EAAM;EACb,CACF,CACD,CACH;CA+FD,OACE,kBAAC,OAAD;EAAK,WAAW;YACd,kBAAC,GAAD;GACQ,MAhGC,EAAc,KAAK,OACvB;IACL,IAAI,EAAM;IACV,MAAM,EAAM,KAAK,KAAK,OACb;KACL,GAAG,IAAI,KAAK,EAAM,EAAE;KACpB,GAAG,EAAM;KACV,EACD;IACH,EAuFS;GACN,QAAQ;IAAE,KAAK;IAAI,OAAO;IAAI,QAAQ;IAAI,MAAM;IAAI;GACpD,SAAS,MACA,EAAa,OAAO,EAAM,GAAG,GAAG,SAAS,EAAK,OAAO;GAE9D,QAAQ;IACN,MAAM;IACN,QAAQ;IACR,WAAW;IACX,QAAQ;IACT;GACD,SAAQ;GACR,QAAQ;IAAE,MAAM;IAAU,KAAK;IAAQ,KAAK;IAAQ;GACpD,OAAM;GACN,WAAW;GACX,WAAW;GACX,kBAAkB;GAClB,kBAAkB;IAAE,MAAM;IAAe,WAAW,CAAC,CAAC,UAAU,GAAI,CAAC;IAAE;GACvE,YAAA;GACA,aAAa;GACb,aAAa;GACb,aAAA;GACA,SAAS;GACT,WAAW;GACX,YAAY;IACV,SAAS,MACD,aAAiB,OAIhB,EAAoB,EAAM,GAHxB;IAKX,UAAU;IACV,aAAa;IACb,YAAY;IACb;GACD,UAAU;IACR,UAAU;IACV,aAAa;IACb,YAAY;IACZ,SAAS,MACH,OAAO,KAAU,WAId,IAAI,KAAK,aAAa,KAAA,GAAW;KACtC,UAAU;KACV,uBAAuB;KACxB,CAAC,CAAC,OAAO,EAAM,GANP;IAQZ;GACD,cAAA;GACA,SAAA;GACS,UAxIb;IACE,QAAQ;IACR,WAAW;IACX,YAAY;IACZ,WAAW;IACX,YAAY;IACZ,cAAc;IACd,YAAY;IACZ,aAAa;IACb,eAAe,EAAK,OAAO;IAC3B,MAAM,EAAc,KAAK,OAChB;KACL,IAAI,EAAM;KACV,OAAO,EAAM;KACb,OAAO,EAAM;KACd,EACD;IACH,CAuHY;GACT,OAAO;IACL,MAAM,EACJ,MAAM,EACJ,QAAQ,EAAK,OAAO,aACrB,EACF;IACD,MAAM,EACJ,OAAO,EACL,MAAM;KACJ,MAAM,EAAK,OAAO;KAClB,UAAU;KACX,EACF,EACF;IACD,WAAW,EACT,MAAM;KACJ,QAAQ,EAAK,OAAO;KACpB,aAAa;KACb,iBAAiB;KAClB,EACF;IACD,SAAS,EACP,WAAW;KACT,YAAY;KACZ,WAAW;KACX,SAAS;KACV,EACF;IACF;GACa,eAlJE,EACpB,eAC2D;IAC3D,IAAM,IAAa,EAAM,OAAO,IAC5B,IAAiB,OAAO,EAAM,GAAG;IACrC,AAAI,GAAY,KAAK,aAAa,SAChC,IAAiB,EAAW,KAAK,EAAE,aAAa;IAGlD,IAAM,IAAS,CAAC,GAAG,EAAM,OAAO,CAC7B,KAAK,MAAoC;KACxC,IAAI,IAAQ,OAAO,EAAM,KAAK,EAAE;KAKhC,IAJI,OAAO,EAAM,KAAK,KAAM,aAC1B,IAAQ,EAAM,KAAK,IAGjB,OAAO,MAAM,EAAM,EACrB,OAAO;KAGT,IAAM,IAAW,OAAO,EAAM,SAAS,EACjC,IAAW,EAAa;KAE9B,OAAO;MACL;MACA,OAAO,GAAU,SAAS;MAC1B;MACA,OAAO,EAAM;MACb,MAAM,GAAU;MACjB;MACD,CACD,QAAQ,MACA,KAAS,KAChB;IAEJ,OACE,kBAAC,OAAD;KAAK,WAAW;eAAhB,CACE,kBAAC,KAAD;MAAG,WAAW;gBAAqB,EAAgB,EAAe;MAAK,CAAA,EACtE,EAAO,KAAK,MAET,kBAAC,OAAD;MAEE,WAAW;gBAFb,CAIE,kBAAC,QAAD;OAAM,WAAW;iBAAjB,CACE,kBAAC,QAAD;QACE,WAAW;QACX,OAAO,EAAE,iBAAiB,EAAM,OAAO;QACvC,eAAA;QACA,CAAA,EACF,kBAAC,QAAD,EAAA,UAAO,EAAM,OAAa,CAAA,CACrB;UACP,kBAAC,UAAD,EAAA,UAAS,EAAY,EAAM,OAAO,EAAM,KAAK,EAAU,CAAA,CACnD;QAZC,GAAG,EAAM,SAAS,GAAG,IAYtB,CAER,CACE;;;GA2FJ,cAAa;GACb,MAAK;GACM;GACX,CAAA;EACE,CAAA"}
@@ -1,23 +1,13 @@
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 { jsx as s, jsxs as c } from "react/jsx-runtime";
4
- import { ResponsiveLine as l } from "@nivo/line";
3
+ import { formatDayTick as s, formatYAxisTick as c, getVisibleDayTicks as l, resolveYAxisState as u } from "../../internal/charts/timeSeriesLineChartHelpers.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/TimeSeriesLineChart.tsx
6
- var u = 6;
7
- function d(e) {
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 m = (m) => {
8
+ let { ariaLabel: h, categoryColorById: g, categoryLabel: _, categoryOrder: v, formatValue: y, series: b, yAxis: x } = m, S = l(b), C = null;
9
+ x != null && (C = u(b, x));
10
+ let w = v, T = (e) => w.includes(e), E = [{
21
11
  anchor: "bottom",
22
12
  direction: "row",
23
13
  translateY: 56,
@@ -27,28 +17,28 @@ var p = (u) => {
27
17
  symbolSize: 10,
28
18
  symbolShape: "circle",
29
19
  itemTextColor: e.colors.textSecondary,
30
- data: g.map((e) => ({
20
+ data: v.map((e) => ({
31
21
  id: e,
32
- label: h(e),
33
- color: m[e]
22
+ label: _(e),
23
+ color: g[e]
34
24
  }))
35
25
  }];
36
- return /* @__PURE__ */ s("div", {
26
+ return /* @__PURE__ */ d("div", {
37
27
  className: t,
38
- children: /* @__PURE__ */ s(l, {
39
- data: v,
28
+ children: /* @__PURE__ */ d(p, {
29
+ data: b,
40
30
  margin: {
41
31
  top: 14,
42
32
  right: 16,
43
33
  bottom: 74,
44
34
  left: 52
45
35
  },
46
- colors: (t) => typeof t.id != "string" || !x(t.id) ? e.colors.primary : m[t.id],
36
+ colors: (t) => typeof t.id != "string" || !T(t.id) ? e.colors.primary : g[t.id],
47
37
  xScale: { type: "point" },
48
38
  yScale: {
49
39
  type: "linear",
50
- min: 0,
51
- max: "auto"
40
+ min: C?.min ?? 0,
41
+ max: C?.max ?? "auto"
52
42
  },
53
43
  curve: "monotoneX",
54
44
  lineWidth: 2.5,
@@ -62,26 +52,24 @@ var p = (u) => {
62
52
  areaOpacity: .1,
63
53
  enableGridX: !1,
64
54
  enableGridY: !0,
55
+ gridYValues: C?.tickValues,
65
56
  axisTop: null,
66
57
  axisRight: null,
67
58
  axisBottom: {
68
- tickValues: y,
69
- format: (e) => f(String(e)),
59
+ tickValues: S,
60
+ format: (e) => s(String(e)),
70
61
  tickSize: 0,
71
62
  tickPadding: 10
72
63
  },
73
64
  axisLeft: {
74
65
  tickSize: 0,
75
66
  tickPadding: 8,
76
- tickValues: 5,
77
- format: (e) => typeof e == "number" ? new Intl.NumberFormat("en-US", {
78
- notation: "compact",
79
- maximumFractionDigits: 1
80
- }).format(e) : ""
67
+ tickValues: C?.tickValues ?? 5,
68
+ format: (e) => typeof e == "number" ? x?.formatValue?.(e) ?? c(e) : ""
81
69
  },
82
70
  enablePoints: !0,
83
71
  useMesh: !0,
84
- legends: S,
72
+ legends: E,
85
73
  theme: {
86
74
  grid: { line: { stroke: e.colors.borderLight } },
87
75
  axis: { ticks: { text: {
@@ -100,41 +88,41 @@ var p = (u) => {
100
88
  } }
101
89
  },
102
90
  sliceTooltip: ({ slice: e }) => {
103
- let t = String(e.id), l = g[0] ?? null, u = [...e.points].map((e) => {
91
+ let t = String(e.id), c = v[0] ?? null, l = [...e.points].map((e) => {
104
92
  let t = 0;
105
93
  typeof e.data.y == "number" && (t = e.data.y);
106
- let n = l;
107
- return typeof e.seriesId == "string" && x(e.seriesId) && (n = e.seriesId), n == null ? null : {
94
+ let n = c;
95
+ return typeof e.seriesId == "string" && T(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
- }).filter((e) => e != null).sort((e, t) => g.indexOf(e.seriesId) - g.indexOf(t.seriesId));
113
- return /* @__PURE__ */ c("div", {
100
+ }).filter((e) => e != null).sort((e, t) => v.indexOf(e.seriesId) - v.indexOf(t.seriesId));
101
+ return /* @__PURE__ */ f("div", {
114
102
  className: n,
115
- children: [/* @__PURE__ */ s("p", {
103
+ children: [/* @__PURE__ */ d("p", {
116
104
  className: r,
117
- children: f(t)
118
- }), u.map((e) => /* @__PURE__ */ c("div", {
105
+ children: s(t)
106
+ }), l.map((e) => /* @__PURE__ */ f("div", {
119
107
  className: i,
120
- children: [/* @__PURE__ */ c("span", {
108
+ children: [/* @__PURE__ */ f("span", {
121
109
  className: a,
122
- children: [/* @__PURE__ */ s("span", {
110
+ children: [/* @__PURE__ */ d("span", {
123
111
  className: o,
124
112
  style: { backgroundColor: e.color },
125
113
  "aria-hidden": !0
126
- }), /* @__PURE__ */ s("span", { children: h(e.seriesId) })]
127
- }), /* @__PURE__ */ s("strong", { children: _(e.data.y) })]
114
+ }), /* @__PURE__ */ d("span", { children: _(e.seriesId) })]
115
+ }), /* @__PURE__ */ d("strong", { children: y(e.data.y) })]
128
116
  }, `${t}-${e.seriesId}`))]
129
117
  });
130
118
  },
131
119
  enableSlices: "x",
132
120
  role: "img",
133
- ariaLabel: p
121
+ ariaLabel: h
134
122
  })
135
123
  });
136
- }, m = { formatDayTick: f };
124
+ };
137
125
  //#endregion
138
- export { p as TimeSeriesLineChart, p as default, m as __test };
126
+ export { m as TimeSeriesLineChart, m 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 formatYAxisTick,\n getVisibleDayTicks,\n resolveYAxisState,\n type TimeSeriesYAxisConfig,\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 yAxis?: TimeSeriesYAxisConfig;\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 yAxis,\n } = props;\n\n const visibleTicks = getVisibleDayTicks(series);\n let yAxisState = null;\n if (yAxis != null) {\n yAxisState = resolveYAxisState(series, yAxis);\n }\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={{\n type: 'linear',\n min: yAxisState?.min ?? 0,\n max: yAxisState?.max ?? 'auto',\n }}\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 gridYValues={yAxisState?.tickValues}\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: yAxisState?.tickValues ?? 5,\n format: (value) => {\n if (typeof value !== 'number') {\n return '';\n }\n\n return yAxis?.formatValue?.(value) ?? formatYAxisTick(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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"}