@burdenoff/microfe-timecampus 2026.710.1 → 2026.713.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/index.js +2 -1
  2. package/dist/services/createSandboxAssistantTransport.d.ts +8 -3
  3. package/dist/services/createSandboxAssistantTransport.d.ts.map +1 -1
  4. package/dist/services/createSandboxAssistantTransport.js +12 -0
  5. package/dist/services/createSandboxAssistantTransport.js.map +1 -0
  6. package/dist/timecampus/components/DataTable.js +1 -0
  7. package/dist/timecampus/components/FilterBar.js +1 -0
  8. package/dist/timecampus/components/charts/BalanceWheel.js +38 -43
  9. package/dist/timecampus/components/charts/BalanceWheel.js.map +1 -1
  10. package/dist/timecampus/components/charts/BarsChart.js +24 -31
  11. package/dist/timecampus/components/charts/BarsChart.js.map +1 -1
  12. package/dist/timecampus/components/charts/DonutChart.js +36 -40
  13. package/dist/timecampus/components/charts/DonutChart.js.map +1 -1
  14. package/dist/timecampus/components/charts/RadialGauge.js +14 -17
  15. package/dist/timecampus/components/charts/RadialGauge.js.map +1 -1
  16. package/dist/timecampus/components/charts/Sparkline.js +2 -0
  17. package/dist/timecampus/components/charts/TrendChart.js +47 -57
  18. package/dist/timecampus/components/charts/TrendChart.js.map +1 -1
  19. package/dist/timecampus/index.d.ts +1 -0
  20. package/dist/timecampus/index.d.ts.map +1 -1
  21. package/dist/timecampus/index.js +1 -0
  22. package/dist/timecampus/providers/TimeCampusProvider.js +32 -32
  23. package/dist/timecampus/utils/helpers.js +2 -2
  24. package/package.json +2 -2
  25. package/dist/_virtual/_rolldown/runtime.js +0 -20
  26. package/dist/services/assistantApi.d.ts +0 -49
  27. package/dist/services/assistantApi.d.ts.map +0 -1
@@ -1,42 +1,38 @@
1
1
  import { cn as e } from "../../utils/helpers.js";
2
- import { Tooltip as t } from "../../../node_modules/recharts/es6/component/Tooltip.js";
3
- import { ResponsiveContainer as n } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
4
- import { Cell as r } from "../../../node_modules/recharts/es6/component/Cell.js";
5
- import { Pie as i } from "../../../node_modules/recharts/es6/polar/Pie.js";
6
- import { PieChart as a } from "../../../node_modules/recharts/es6/chart/PieChart.js";
7
- import { chartTokens as o, formatNumber as s, renderValue as c, seriesColor as l, usePrefersReducedMotion as u } from "./chartTheme.js";
8
- import { ChartEmpty as d, ChartTooltip as f, srOnlyStyle as p } from "./ChartParts.js";
9
- import { jsx as m, jsxs as h } from "react/jsx-runtime";
2
+ import { chartTokens as t, formatNumber as n, renderValue as r, seriesColor as i, usePrefersReducedMotion as a } from "./chartTheme.js";
3
+ import { ChartEmpty as o, ChartTooltip as s, srOnlyStyle as c } from "./ChartParts.js";
4
+ import { jsx as l, jsxs as u } from "react/jsx-runtime";
5
+ import { Cell as d, Pie as f, PieChart as p, ResponsiveContainer as m, Tooltip as h } from "recharts";
10
6
  //#region src/timecampus/components/charts/DonutChart.tsx
11
- function g({ data: g, centerLabel: _, centerValue: v, height: y = 240, thickness: b = .42, valueFormat: x = s, showLegend: S = !0, emptyLabel: C, ariaLabel: w, className: T }) {
12
- let E = u(), D = g.filter((e) => typeof e.value == "number" && Number.isFinite(e.value) && e.value > 0).map((e, t) => ({
7
+ function g({ data: g, centerLabel: _, centerValue: v, height: y = 240, thickness: b = .42, valueFormat: x = n, showLegend: S = !0, emptyLabel: C, ariaLabel: w, className: T }) {
8
+ let E = a(), D = g.filter((e) => typeof e.value == "number" && Number.isFinite(e.value) && e.value > 0).map((e, t) => ({
13
9
  ...e,
14
- color: e.color ?? l(t)
10
+ color: e.color ?? i(t)
15
11
  })), O = D.reduce((e, t) => e + t.value, 0);
16
- if (D.length === 0 || O <= 0) return /* @__PURE__ */ m(d, {
12
+ if (D.length === 0 || O <= 0) return /* @__PURE__ */ l(o, {
17
13
  height: y,
18
14
  label: C,
19
15
  className: T
20
16
  });
21
- let k = w ?? `${_ ?? "Distribution"}: ${D.map((e) => e.name).join(", ")}`, A = Math.max(0, Math.round(82 * (1 - b))), j = _ !== void 0 || v !== void 0, M = v === void 0 ? x(O) : c(v, x);
22
- return /* @__PURE__ */ h("figure", {
17
+ let k = w ?? `${_ ?? "Distribution"}: ${D.map((e) => e.name).join(", ")}`, A = Math.max(0, Math.round(82 * (1 - b))), j = _ !== void 0 || v !== void 0, M = v === void 0 ? x(O) : r(v, x);
18
+ return /* @__PURE__ */ u("figure", {
23
19
  role: "img",
24
20
  "aria-label": k,
25
21
  className: e("w-full", T),
26
22
  children: [
27
- /* @__PURE__ */ h("div", {
23
+ /* @__PURE__ */ u("div", {
28
24
  className: "relative mx-auto",
29
25
  style: { height: y },
30
- children: [/* @__PURE__ */ m(n, {
26
+ children: [/* @__PURE__ */ l(m, {
31
27
  width: "100%",
32
28
  height: "100%",
33
- children: /* @__PURE__ */ h(a, { children: [/* @__PURE__ */ m(t, {
29
+ children: /* @__PURE__ */ u(p, { children: [/* @__PURE__ */ l(h, {
34
30
  cursor: !1,
35
- content: /* @__PURE__ */ m(f, {
31
+ content: /* @__PURE__ */ l(s, {
36
32
  valueFormat: x,
37
33
  hideLabel: !0
38
34
  })
39
- }), /* @__PURE__ */ m(i, {
35
+ }), /* @__PURE__ */ l(f, {
40
36
  data: D,
41
37
  dataKey: "value",
42
38
  nameKey: "name",
@@ -45,65 +41,65 @@ function g({ data: g, centerLabel: _, centerValue: v, height: y = 240, thickness
45
41
  innerRadius: `${A}%`,
46
42
  outerRadius: "82%",
47
43
  paddingAngle: 1.5,
48
- stroke: o.surface,
44
+ stroke: t.surface,
49
45
  strokeWidth: 2,
50
46
  isAnimationActive: !E,
51
- children: D.map((e) => /* @__PURE__ */ m(r, { fill: e.color }, e.name))
47
+ children: D.map((e) => /* @__PURE__ */ l(d, { fill: e.color }, e.name))
52
48
  })] })
53
- }), j ? /* @__PURE__ */ h("div", {
49
+ }), j ? /* @__PURE__ */ u("div", {
54
50
  className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center",
55
- children: [/* @__PURE__ */ m("span", {
51
+ children: [/* @__PURE__ */ l("span", {
56
52
  className: "text-2xl font-bold text-text-primary",
57
53
  children: M
58
- }), _ ? /* @__PURE__ */ m("span", {
54
+ }), _ ? /* @__PURE__ */ l("span", {
59
55
  className: "mt-0.5 max-w-[70%] text-xs text-text-secondary",
60
56
  children: _
61
57
  }) : null]
62
58
  }) : null]
63
59
  }),
64
- S ? /* @__PURE__ */ m("ul", {
60
+ S ? /* @__PURE__ */ l("ul", {
65
61
  className: "mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5",
66
- children: D.map((e) => /* @__PURE__ */ h("li", {
62
+ children: D.map((e) => /* @__PURE__ */ u("li", {
67
63
  className: "flex items-center gap-1.5 text-xs text-text-secondary",
68
64
  children: [
69
- /* @__PURE__ */ m("span", {
65
+ /* @__PURE__ */ l("span", {
70
66
  "aria-hidden": "true",
71
67
  className: "h-2.5 w-2.5 rounded-[3px]",
72
68
  style: { backgroundColor: e.color }
73
69
  }),
74
- /* @__PURE__ */ m("span", { children: e.name }),
75
- /* @__PURE__ */ h("span", {
70
+ /* @__PURE__ */ l("span", { children: e.name }),
71
+ /* @__PURE__ */ u("span", {
76
72
  className: "tabular-nums text-text-muted",
77
73
  children: [Math.round(e.value / O * 100), "%"]
78
74
  })
79
75
  ]
80
76
  }, e.name))
81
77
  }) : null,
82
- /* @__PURE__ */ h("table", {
83
- style: p,
78
+ /* @__PURE__ */ u("table", {
79
+ style: c,
84
80
  children: [
85
- /* @__PURE__ */ m("caption", { children: k }),
86
- /* @__PURE__ */ m("thead", { children: /* @__PURE__ */ h("tr", { children: [
87
- /* @__PURE__ */ m("th", {
81
+ /* @__PURE__ */ l("caption", { children: k }),
82
+ /* @__PURE__ */ l("thead", { children: /* @__PURE__ */ u("tr", { children: [
83
+ /* @__PURE__ */ l("th", {
88
84
  scope: "col",
89
85
  children: "Category"
90
86
  }),
91
- /* @__PURE__ */ m("th", {
87
+ /* @__PURE__ */ l("th", {
92
88
  scope: "col",
93
89
  children: "Value"
94
90
  }),
95
- /* @__PURE__ */ m("th", {
91
+ /* @__PURE__ */ l("th", {
96
92
  scope: "col",
97
93
  children: "Share"
98
94
  })
99
95
  ] }) }),
100
- /* @__PURE__ */ m("tbody", { children: D.map((e) => /* @__PURE__ */ h("tr", { children: [
101
- /* @__PURE__ */ m("th", {
96
+ /* @__PURE__ */ l("tbody", { children: D.map((e) => /* @__PURE__ */ u("tr", { children: [
97
+ /* @__PURE__ */ l("th", {
102
98
  scope: "row",
103
99
  children: e.name
104
100
  }),
105
- /* @__PURE__ */ m("td", { children: x(e.value) }),
106
- /* @__PURE__ */ h("td", { children: [Math.round(e.value / O * 100), "%"] })
101
+ /* @__PURE__ */ l("td", { children: x(e.value) }),
102
+ /* @__PURE__ */ u("td", { children: [Math.round(e.value / O * 100), "%"] })
107
103
  ] }, e.name)) })
108
104
  ]
109
105
  })
@@ -1 +1 @@
1
- {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/DonutChart.tsx"],"sourcesContent":["import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from \"recharts\";\nimport { cn } from \"../../utils/helpers\";\nimport {\n chartTokens,\n formatNumber,\n renderValue,\n seriesColor,\n usePrefersReducedMotion,\n type DonutSlice,\n type ValueFormatter,\n} from \"./chartTheme\";\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from \"./ChartParts\";\n\nexport interface DonutChartProps {\n /** Slices `{ name, value, color? }`. */\n data: DonutSlice[];\n /** Small caption under the centre value (e.g. \"Total assets\"). */\n centerLabel?: string;\n /**\n * Big centre value. If omitted while `centerLabel` is set, the summed total is\n * shown. A number is run through `valueFormat`.\n */\n centerValue?: string | number;\n /** Pixel height of the ring. Default 240. */\n height?: number;\n /** Ring thickness as a fraction of the radius (0–1). Default 0.42. */\n thickness?: number;\n /** Formats slice + centre values. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Show the legend list under the ring. Default true. */\n showLegend?: boolean;\n /** Message shown when there are no slices (or all zero). */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * DonutChart — a category/status mix as a ring with a center total. Slices take\n * the categorical ramp in fixed order, identity is carried by an always-present\n * legend (never colour alone), and hover reveals a token-styled tooltip.\n * Renders an empty state — never a fake ring — when there is nothing to show.\n */\nexport function DonutChart({\n data,\n centerLabel,\n centerValue,\n height = 240,\n thickness = 0.42,\n valueFormat = formatNumber,\n showLegend = true,\n emptyLabel,\n ariaLabel,\n className,\n}: DonutChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const slices = data\n .filter(\n (slice) =>\n typeof slice.value === \"number\" &&\n Number.isFinite(slice.value) &&\n slice.value > 0,\n )\n .map((slice, index) => ({\n ...slice,\n color: slice.color ?? seriesColor(index),\n }));\n\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n\n if (slices.length === 0 || total <= 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const label =\n ariaLabel ??\n `${centerLabel ?? \"Distribution\"}: ${slices.map((s) => s.name).join(\", \")}`;\n const outerPct = 82;\n const innerPct = Math.max(0, Math.round(outerPct * (1 - thickness)));\n const showCenter = centerLabel !== undefined || centerValue !== undefined;\n const resolvedCenter =\n centerValue !== undefined\n ? renderValue(centerValue, valueFormat)\n : valueFormat(total);\n\n return (\n <figure role=\"img\" aria-label={label} className={cn(\"w-full\", className)}>\n <div className=\"relative mx-auto\" style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={valueFormat} hideLabel />}\n />\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={`${innerPct}%`}\n outerRadius={`${outerPct}%`}\n paddingAngle={1.5}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n >\n {slices.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n\n {showCenter ? (\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-2xl font-bold text-text-primary\">\n {resolvedCenter}\n </span>\n {centerLabel ? (\n <span className=\"mt-0.5 max-w-[70%] text-xs text-text-secondary\">\n {centerLabel}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {showLegend ? (\n <ul className=\"mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5\">\n {slices.map((slice) => (\n <li\n key={slice.name}\n className=\"flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: slice.color }}\n />\n <span>{slice.name}</span>\n <span className=\"tabular-nums text-text-muted\">\n {Math.round((slice.value / total) * 100)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {slices.map((slice) => (\n <tr key={slice.name}>\n <th scope=\"row\">{slice.name}</th>\n <td>{valueFormat(slice.value)}</td>\n <td>{Math.round((slice.value / total) * 100)}%</td>\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DonutChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/DonutChart.tsx"],"sourcesContent":["import { Cell, Pie, PieChart, ResponsiveContainer, Tooltip } from \"recharts\";\nimport { cn } from \"../../utils/helpers\";\nimport {\n chartTokens,\n formatNumber,\n renderValue,\n seriesColor,\n usePrefersReducedMotion,\n type DonutSlice,\n type ValueFormatter,\n} from \"./chartTheme\";\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from \"./ChartParts\";\n\nexport interface DonutChartProps {\n /** Slices `{ name, value, color? }`. */\n data: DonutSlice[];\n /** Small caption under the centre value (e.g. \"Total assets\"). */\n centerLabel?: string;\n /**\n * Big centre value. If omitted while `centerLabel` is set, the summed total is\n * shown. A number is run through `valueFormat`.\n */\n centerValue?: string | number;\n /** Pixel height of the ring. Default 240. */\n height?: number;\n /** Ring thickness as a fraction of the radius (0–1). Default 0.42. */\n thickness?: number;\n /** Formats slice + centre values. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Show the legend list under the ring. Default true. */\n showLegend?: boolean;\n /** Message shown when there are no slices (or all zero). */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * DonutChart — a category/status mix as a ring with a center total. Slices take\n * the categorical ramp in fixed order, identity is carried by an always-present\n * legend (never colour alone), and hover reveals a token-styled tooltip.\n * Renders an empty state — never a fake ring — when there is nothing to show.\n */\nexport function DonutChart({\n data,\n centerLabel,\n centerValue,\n height = 240,\n thickness = 0.42,\n valueFormat = formatNumber,\n showLegend = true,\n emptyLabel,\n ariaLabel,\n className,\n}: DonutChartProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const slices = data\n .filter(\n (slice) =>\n typeof slice.value === \"number\" &&\n Number.isFinite(slice.value) &&\n slice.value > 0,\n )\n .map((slice, index) => ({\n ...slice,\n color: slice.color ?? seriesColor(index),\n }));\n\n const total = slices.reduce((sum, slice) => sum + slice.value, 0);\n\n if (slices.length === 0 || total <= 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const label =\n ariaLabel ??\n `${centerLabel ?? \"Distribution\"}: ${slices.map((s) => s.name).join(\", \")}`;\n const outerPct = 82;\n const innerPct = Math.max(0, Math.round(outerPct * (1 - thickness)));\n const showCenter = centerLabel !== undefined || centerValue !== undefined;\n const resolvedCenter =\n centerValue !== undefined\n ? renderValue(centerValue, valueFormat)\n : valueFormat(total);\n\n return (\n <figure role=\"img\" aria-label={label} className={cn(\"w-full\", className)}>\n <div className=\"relative mx-auto\" style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <PieChart>\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={valueFormat} hideLabel />}\n />\n <Pie\n data={slices}\n dataKey=\"value\"\n nameKey=\"name\"\n cx=\"50%\"\n cy=\"50%\"\n innerRadius={`${innerPct}%`}\n outerRadius={`${outerPct}%`}\n paddingAngle={1.5}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n >\n {slices.map((slice) => (\n <Cell key={slice.name} fill={slice.color} />\n ))}\n </Pie>\n </PieChart>\n </ResponsiveContainer>\n\n {showCenter ? (\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-2xl font-bold text-text-primary\">\n {resolvedCenter}\n </span>\n {centerLabel ? (\n <span className=\"mt-0.5 max-w-[70%] text-xs text-text-secondary\">\n {centerLabel}\n </span>\n ) : null}\n </div>\n ) : null}\n </div>\n\n {showLegend ? (\n <ul className=\"mt-3 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5\">\n {slices.map((slice) => (\n <li\n key={slice.name}\n className=\"flex items-center gap-1.5 text-xs text-text-secondary\"\n >\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: slice.color }}\n />\n <span>{slice.name}</span>\n <span className=\"tabular-nums text-text-muted\">\n {Math.round((slice.value / total) * 100)}%\n </span>\n </li>\n ))}\n </ul>\n ) : null}\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Category</th>\n <th scope=\"col\">Value</th>\n <th scope=\"col\">Share</th>\n </tr>\n </thead>\n <tbody>\n {slices.map((slice) => (\n <tr key={slice.name}>\n <th scope=\"row\">{slice.name}</th>\n <td>{valueFormat(slice.value)}</td>\n <td>{Math.round((slice.value / total) * 100)}%</td>\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"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"}
@@ -1,58 +1,55 @@
1
1
  import { cn as e } from "../../utils/helpers.js";
2
- import { ResponsiveContainer as t } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
3
- import { PolarAngleAxis as n } from "../../../node_modules/recharts/es6/polar/PolarAngleAxis.js";
4
- import { RadialBar as r } from "../../../node_modules/recharts/es6/polar/RadialBar.js";
5
- import { RadialBarChart as i } from "../../../node_modules/recharts/es6/chart/RadialBarChart.js";
6
- import { chartTokens as a, toneColor as o, usePrefersReducedMotion as s } from "./chartTheme.js";
7
- import { jsx as c, jsxs as l } from "react/jsx-runtime";
2
+ import { chartTokens as t, toneColor as n, usePrefersReducedMotion as r } from "./chartTheme.js";
3
+ import { jsx as i, jsxs as a } from "react/jsx-runtime";
4
+ import { PolarAngleAxis as o, RadialBar as s, RadialBarChart as c, ResponsiveContainer as l } from "recharts";
8
5
  //#region src/timecampus/components/charts/RadialGauge.tsx
9
6
  var u = (e, t, n) => Math.min(n, Math.max(t, e));
10
7
  function d({ value: d, min: f = 0, max: p = 100, label: m, sublabel: h, thresholds: g, higherIsBetter: _ = !0, tone: v, color: y, height: b = 200, format: x = (e) => Math.round(e).toString(), ariaLabel: S, className: C }) {
11
- let w = s(), T = p - f || 1, E = u(d, f, p), D = g?.warning ?? (_ ? f + T * .8 : f + T * .5), O = g?.danger ?? (_ ? f + T * .5 : f + T * .8), k = y ?? o(v ?? (_ ? d >= D ? "success" : d >= O ? "warning" : "danger" : d <= D ? "success" : d <= O ? "warning" : "danger")), A = [{
8
+ let w = r(), T = p - f || 1, E = u(d, f, p), D = g?.warning ?? (_ ? f + T * .8 : f + T * .5), O = g?.danger ?? (_ ? f + T * .5 : f + T * .8), k = y ?? n(v ?? (_ ? d >= D ? "success" : d >= O ? "warning" : "danger" : d <= D ? "success" : d <= O ? "warning" : "danger")), A = [{
12
9
  name: m ?? "value",
13
10
  value: E
14
11
  }];
15
- return /* @__PURE__ */ l("figure", {
12
+ return /* @__PURE__ */ a("figure", {
16
13
  role: "img",
17
14
  "aria-label": S ?? `${m ? `${m}: ` : ""}${x(d)}`,
18
15
  className: e("relative w-full", C),
19
16
  style: { height: b },
20
- children: [/* @__PURE__ */ c(t, {
17
+ children: [/* @__PURE__ */ i(l, {
21
18
  width: "100%",
22
19
  height: "100%",
23
- children: /* @__PURE__ */ l(i, {
20
+ children: /* @__PURE__ */ a(c, {
24
21
  data: A,
25
22
  innerRadius: "72%",
26
23
  outerRadius: "100%",
27
24
  barSize: 14,
28
25
  startAngle: 225,
29
26
  endAngle: -45,
30
- children: [/* @__PURE__ */ c(n, {
27
+ children: [/* @__PURE__ */ i(o, {
31
28
  type: "number",
32
29
  domain: [f, p],
33
30
  angleAxisId: 0,
34
31
  tick: !1
35
- }), /* @__PURE__ */ c(r, {
32
+ }), /* @__PURE__ */ i(s, {
36
33
  dataKey: "value",
37
34
  angleAxisId: 0,
38
- background: { fill: a.track },
35
+ background: { fill: t.track },
39
36
  cornerRadius: 999,
40
37
  fill: k,
41
38
  isAnimationActive: !w
42
39
  })]
43
40
  })
44
- }), /* @__PURE__ */ l("div", {
41
+ }), /* @__PURE__ */ a("div", {
45
42
  className: "pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center",
46
43
  children: [
47
- /* @__PURE__ */ c("span", {
44
+ /* @__PURE__ */ i("span", {
48
45
  className: "text-3xl font-bold leading-none text-text-primary",
49
46
  children: x(d)
50
47
  }),
51
- m ? /* @__PURE__ */ c("span", {
48
+ m ? /* @__PURE__ */ i("span", {
52
49
  className: "mt-1 text-sm font-medium text-text-secondary",
53
50
  children: m
54
51
  }) : null,
55
- h ? /* @__PURE__ */ c("span", {
52
+ h ? /* @__PURE__ */ i("span", {
56
53
  className: "text-xs text-text-muted",
57
54
  children: h
58
55
  }) : null
@@ -1 +1 @@
1
- {"version":3,"file":"RadialGauge.js","names":[],"sources":["../../../../src/timecampus/components/charts/RadialGauge.tsx"],"sourcesContent":["import {\n PolarAngleAxis,\n RadialBar,\n RadialBarChart,\n ResponsiveContainer,\n} from \"recharts\";\nimport { cn } from \"../../utils/helpers\";\nimport {\n chartTokens,\n toneColor,\n usePrefersReducedMotion,\n type MeterTone,\n type ValueFormatter,\n} from \"./chartTheme\";\n\nexport interface RadialGaugeProps {\n /** The measured value. */\n value: number;\n /** Scale minimum. Default 0. */\n min?: number;\n /** Scale maximum. Default 100. */\n max?: number;\n /** Big centre caption (e.g. \"Compliance\"). */\n label?: string;\n /** Small caption under the value. */\n sublabel?: string;\n /**\n * Severity thresholds in value units. With `higherIsBetter` (default) pass\n * `warning > danger` (e.g. `{ warning: 80, danger: 50 }` → ≥80 good, 50–79\n * warning, <50 danger). Defaults derive from the range.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a higher value is better (compliance/health) or worse (risk). Default true. */\n higherIsBetter?: boolean;\n /** Force a tone, bypassing threshold logic. */\n tone?: MeterTone;\n /** Force an explicit colour, bypassing tone + thresholds. */\n color?: string;\n /** Pixel height. Default 200. */\n height?: number;\n /** Formats the centre value. Default rounds to an integer. */\n format?: ValueFormatter;\n /** Accessible name. Default derived from label + value. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(max, Math.max(min, value));\n\n/**\n * RadialGauge — a single value on a 270° arc (compliance score, asset health,\n * risk). The arc colour follows severity thresholds (good → warning → danger)\n * using reserved status tokens, over a muted track. Center shows the value and\n * label; respects `prefers-reduced-motion`.\n */\nexport function RadialGauge({\n value,\n min = 0,\n max = 100,\n label,\n sublabel,\n thresholds,\n higherIsBetter = true,\n tone,\n color,\n height = 200,\n format = (v) => Math.round(v).toString(),\n ariaLabel,\n className,\n}: RadialGaugeProps) {\n const reducedMotion = usePrefersReducedMotion();\n const range = max - min || 1;\n const clamped = clamp(value, min, max);\n\n const warning =\n thresholds?.warning ??\n (higherIsBetter ? min + range * 0.8 : min + range * 0.5);\n const danger =\n thresholds?.danger ??\n (higherIsBetter ? min + range * 0.5 : min + range * 0.8);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsBetter\n ? value >= warning\n ? \"success\"\n : value >= danger\n ? \"warning\"\n : \"danger\"\n : value <= warning\n ? \"success\"\n : value <= danger\n ? \"warning\"\n : \"danger\");\n\n const arcColor = color ?? toneColor(resolvedTone);\n const data = [{ name: label ?? \"value\", value: clamped }];\n const accessibleName =\n ariaLabel ?? `${label ? `${label}: ` : \"\"}${format(value)}`;\n\n return (\n <figure\n role=\"img\"\n aria-label={accessibleName}\n className={cn(\"relative w-full\", className)}\n style={{ height }}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadialBarChart\n data={data}\n innerRadius=\"72%\"\n outerRadius=\"100%\"\n barSize={14}\n startAngle={225}\n endAngle={-45}\n >\n <PolarAngleAxis\n type=\"number\"\n domain={[min, max]}\n angleAxisId={0}\n tick={false}\n />\n <RadialBar\n dataKey=\"value\"\n angleAxisId={0}\n background={{ fill: chartTokens.track }}\n cornerRadius={999}\n fill={arcColor}\n isAnimationActive={!reducedMotion}\n />\n </RadialBarChart>\n </ResponsiveContainer>\n\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">\n {format(value)}\n </span>\n {label ? (\n <span className=\"mt-1 text-sm font-medium text-text-secondary\">\n {label}\n </span>\n ) : null}\n {sublabel ? (\n <span className=\"text-xs text-text-muted\">{sublabel}</span>\n ) : null}\n </div>\n </figure>\n );\n}\n"],"mappings":";;;;;;;;AA+CA,IAAM,KAAS,GAAe,GAAa,MACzC,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,EAAM,CAAC;AAQrC,SAAgB,EAAY,EAC1B,UACA,SAAM,GACN,SAAM,KACN,UACA,aACA,eACA,oBAAiB,IACjB,SACA,UACA,YAAS,KACT,aAAU,MAAM,KAAK,MAAM,EAAE,CAAC,UAAU,EACxC,cACA,gBACmB;CACnB,IAAM,IAAgB,GAAyB,EACzC,IAAQ,IAAM,KAAO,GACrB,IAAU,EAAM,GAAO,GAAK,EAAI,EAEhC,IACJ,GAAY,YACX,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAChD,IACJ,GAAY,WACX,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAgBhD,IAAW,KAAS,EAbxB,MACC,IACG,KAAS,IACP,YACA,KAAS,IACP,YACA,WACJ,KAAS,IACP,YACA,KAAS,IACP,YACA,UAEuC,EAC3C,IAAO,CAAC;EAAE,MAAM,KAAS;EAAS,OAAO;EAAS,CAAC;AAIzD,QACE,kBAAC,UAAD;EACE,MAAK;EACL,cALF,KAAa,GAAG,IAAQ,GAAG,EAAM,MAAM,KAAK,EAAO,EAAM;EAMvD,WAAW,EAAG,mBAAmB,EAAU;EAC3C,OAAO,EAAE,WAAQ;YAJnB,CAME,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAAC,GAAD;IACQ;IACN,aAAY;IACZ,aAAY;IACZ,SAAS;IACT,YAAY;IACZ,UAAU;cANZ,CAQE,kBAAC,GAAD;KACE,MAAK;KACL,QAAQ,CAAC,GAAK,EAAI;KAClB,aAAa;KACb,MAAM;KACN,CAAA,EACF,kBAAC,GAAD;KACE,SAAQ;KACR,aAAa;KACb,YAAY,EAAE,MAAM,EAAY,OAAO;KACvC,cAAc;KACd,MAAM;KACN,mBAAmB,CAAC;KACpB,CAAA,CACa;;GACG,CAAA,EAEtB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,QAAD;KAAM,WAAU;eACb,EAAO,EAAM;KACT,CAAA;IACN,IACC,kBAAC,QAAD;KAAM,WAAU;eACb;KACI,CAAA,GACL;IACH,IACC,kBAAC,QAAD;KAAM,WAAU;eAA2B;KAAgB,CAAA,GACzD;IACA;KACC"}
1
+ {"version":3,"file":"RadialGauge.js","names":[],"sources":["../../../../src/timecampus/components/charts/RadialGauge.tsx"],"sourcesContent":["import {\n PolarAngleAxis,\n RadialBar,\n RadialBarChart,\n ResponsiveContainer,\n} from \"recharts\";\nimport { cn } from \"../../utils/helpers\";\nimport {\n chartTokens,\n toneColor,\n usePrefersReducedMotion,\n type MeterTone,\n type ValueFormatter,\n} from \"./chartTheme\";\n\nexport interface RadialGaugeProps {\n /** The measured value. */\n value: number;\n /** Scale minimum. Default 0. */\n min?: number;\n /** Scale maximum. Default 100. */\n max?: number;\n /** Big centre caption (e.g. \"Compliance\"). */\n label?: string;\n /** Small caption under the value. */\n sublabel?: string;\n /**\n * Severity thresholds in value units. With `higherIsBetter` (default) pass\n * `warning > danger` (e.g. `{ warning: 80, danger: 50 }` → ≥80 good, 50–79\n * warning, <50 danger). Defaults derive from the range.\n */\n thresholds?: { warning: number; danger: number };\n /** Whether a higher value is better (compliance/health) or worse (risk). Default true. */\n higherIsBetter?: boolean;\n /** Force a tone, bypassing threshold logic. */\n tone?: MeterTone;\n /** Force an explicit colour, bypassing tone + thresholds. */\n color?: string;\n /** Pixel height. Default 200. */\n height?: number;\n /** Formats the centre value. Default rounds to an integer. */\n format?: ValueFormatter;\n /** Accessible name. Default derived from label + value. */\n ariaLabel?: string;\n className?: string;\n}\n\nconst clamp = (value: number, min: number, max: number): number =>\n Math.min(max, Math.max(min, value));\n\n/**\n * RadialGauge — a single value on a 270° arc (compliance score, asset health,\n * risk). The arc colour follows severity thresholds (good → warning → danger)\n * using reserved status tokens, over a muted track. Center shows the value and\n * label; respects `prefers-reduced-motion`.\n */\nexport function RadialGauge({\n value,\n min = 0,\n max = 100,\n label,\n sublabel,\n thresholds,\n higherIsBetter = true,\n tone,\n color,\n height = 200,\n format = (v) => Math.round(v).toString(),\n ariaLabel,\n className,\n}: RadialGaugeProps) {\n const reducedMotion = usePrefersReducedMotion();\n const range = max - min || 1;\n const clamped = clamp(value, min, max);\n\n const warning =\n thresholds?.warning ??\n (higherIsBetter ? min + range * 0.8 : min + range * 0.5);\n const danger =\n thresholds?.danger ??\n (higherIsBetter ? min + range * 0.5 : min + range * 0.8);\n\n const resolvedTone: MeterTone =\n tone ??\n (higherIsBetter\n ? value >= warning\n ? \"success\"\n : value >= danger\n ? \"warning\"\n : \"danger\"\n : value <= warning\n ? \"success\"\n : value <= danger\n ? \"warning\"\n : \"danger\");\n\n const arcColor = color ?? toneColor(resolvedTone);\n const data = [{ name: label ?? \"value\", value: clamped }];\n const accessibleName =\n ariaLabel ?? `${label ? `${label}: ` : \"\"}${format(value)}`;\n\n return (\n <figure\n role=\"img\"\n aria-label={accessibleName}\n className={cn(\"relative w-full\", className)}\n style={{ height }}\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadialBarChart\n data={data}\n innerRadius=\"72%\"\n outerRadius=\"100%\"\n barSize={14}\n startAngle={225}\n endAngle={-45}\n >\n <PolarAngleAxis\n type=\"number\"\n domain={[min, max]}\n angleAxisId={0}\n tick={false}\n />\n <RadialBar\n dataKey=\"value\"\n angleAxisId={0}\n background={{ fill: chartTokens.track }}\n cornerRadius={999}\n fill={arcColor}\n isAnimationActive={!reducedMotion}\n />\n </RadialBarChart>\n </ResponsiveContainer>\n\n <div className=\"pointer-events-none absolute inset-0 flex flex-col items-center justify-center text-center\">\n <span className=\"text-3xl font-bold leading-none text-text-primary\">\n {format(value)}\n </span>\n {label ? (\n <span className=\"mt-1 text-sm font-medium text-text-secondary\">\n {label}\n </span>\n ) : null}\n {sublabel ? (\n <span className=\"text-xs text-text-muted\">{sublabel}</span>\n ) : null}\n </div>\n </figure>\n );\n}\n"],"mappings":";;;;;AA+CA,IAAM,KAAS,GAAe,GAAa,MACzC,KAAK,IAAI,GAAK,KAAK,IAAI,GAAK,EAAM,CAAC;AAQrC,SAAgB,EAAY,EAC1B,UACA,SAAM,GACN,SAAM,KACN,UACA,aACA,eACA,oBAAiB,IACjB,SACA,UACA,YAAS,KACT,aAAU,MAAM,KAAK,MAAM,EAAE,CAAC,UAAU,EACxC,cACA,gBACmB;CACnB,IAAM,IAAgB,GAAyB,EACzC,IAAQ,IAAM,KAAO,GACrB,IAAU,EAAM,GAAO,GAAK,EAAI,EAEhC,IACJ,GAAY,YACX,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAChD,IACJ,GAAY,WACX,IAAiB,IAAM,IAAQ,KAAM,IAAM,IAAQ,KAgBhD,IAAW,KAAS,EAbxB,MACC,IACG,KAAS,IACP,YACA,KAAS,IACP,YACA,WACJ,KAAS,IACP,YACA,KAAS,IACP,YACA,UAEuC,EAC3C,IAAO,CAAC;EAAE,MAAM,KAAS;EAAS,OAAO;EAAS,CAAC;AAIzD,QACE,kBAAC,UAAD;EACE,MAAK;EACL,cALF,KAAa,GAAG,IAAQ,GAAG,EAAM,MAAM,KAAK,EAAO,EAAM;EAMvD,WAAW,EAAG,mBAAmB,EAAU;EAC3C,OAAO,EAAE,WAAQ;YAJnB,CAME,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAAC,GAAD;IACQ;IACN,aAAY;IACZ,aAAY;IACZ,SAAS;IACT,YAAY;IACZ,UAAU;cANZ,CAQE,kBAAC,GAAD;KACE,MAAK;KACL,QAAQ,CAAC,GAAK,EAAI;KAClB,aAAa;KACb,MAAM;KACN,CAAA,EACF,kBAAC,GAAD;KACE,SAAQ;KACR,aAAa;KACb,YAAY,EAAE,MAAM,EAAY,OAAO;KACvC,cAAc;KACd,MAAM;KACN,mBAAmB,CAAC;KACpB,CAAA,CACa;;GACG,CAAA,EAEtB,kBAAC,OAAD;GAAK,WAAU;aAAf;IACE,kBAAC,QAAD;KAAM,WAAU;eACb,EAAO,EAAM;KACT,CAAA;IACN,IACC,kBAAC,QAAD;KAAM,WAAU;eACb;KACI,CAAA,GACL;IACH,IACC,kBAAC,QAAD;KAAM,WAAU;eAA2B;KAAgB,CAAA,GACzD;IACA;KACC"}
@@ -1,3 +1,5 @@
1
+ import "../../utils/helpers.js";
1
2
  import "./chartTheme.js";
2
3
  import "react";
3
4
  import "react/jsx-runtime";
5
+ import "recharts";
@@ -1,32 +1,22 @@
1
- import { Legend as e } from "../../../node_modules/recharts/es6/component/Legend.js";
2
- import { Tooltip as t } from "../../../node_modules/recharts/es6/component/Tooltip.js";
3
- import { ResponsiveContainer as n } from "../../../node_modules/recharts/es6/component/ResponsiveContainer.js";
4
- import { ReferenceDot as r } from "../../../node_modules/recharts/es6/cartesian/ReferenceDot.js";
5
- import { CartesianGrid as i } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
6
- import { Line as a } from "../../../node_modules/recharts/es6/cartesian/Line.js";
7
- import { Area as o } from "../../../node_modules/recharts/es6/cartesian/Area.js";
8
- import { XAxis as s } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
9
- import { YAxis as c } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
10
- import { LineChart as l } from "../../../node_modules/recharts/es6/chart/LineChart.js";
11
- import { AreaChart as u } from "../../../node_modules/recharts/es6/chart/AreaChart.js";
12
- import { chartTokens as d, defaultSeriesColor as f, formatNumber as p, usePrefersReducedMotion as m } from "./chartTheme.js";
13
- import { ChartDataTable as h, ChartEmpty as g, ChartFigure as _, ChartLegend as v, ChartTooltip as y } from "./ChartParts.js";
14
- import { useId as b } from "react";
15
- import { jsx as x, jsxs as S } from "react/jsx-runtime";
1
+ import { chartTokens as e, defaultSeriesColor as t, formatNumber as n, usePrefersReducedMotion as r } from "./chartTheme.js";
2
+ import { ChartDataTable as i, ChartEmpty as a, ChartFigure as o, ChartLegend as s, ChartTooltip as c } from "./ChartParts.js";
3
+ import { useId as l } from "react";
4
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
5
+ import { Area as f, AreaChart as p, CartesianGrid as m, Legend as h, Line as g, LineChart as _, ReferenceDot as v, ResponsiveContainer as y, Tooltip as b, XAxis as x, YAxis as S } from "recharts";
16
6
  //#region src/timecampus/components/charts/TrendChart.tsx
17
- function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, valueFormat: O = p, xTickFormat: k, showGrid: A = !0, showLegend: j, showEndDots: M = !0, emptyLabel: N, ariaLabel: P, className: F }) {
18
- let I = b(), L = m(), R = T.map((e, t) => ({
7
+ function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, valueFormat: O = n, xTickFormat: k, showGrid: A = !0, showLegend: j, showEndDots: M = !0, emptyLabel: N, ariaLabel: P, className: F }) {
8
+ let I = l(), L = r(), R = T.map((e, n) => ({
19
9
  ...e,
20
10
  label: e.label ?? e.key,
21
- color: e.color ?? f(t, T.length)
11
+ color: e.color ?? t(n, T.length)
22
12
  })), z = P ?? `Trend of ${R.map((e) => e.label).join(", ")}`;
23
- if (C.length === 0) return /* @__PURE__ */ x(g, {
13
+ if (C.length === 0) return /* @__PURE__ */ u(a, {
24
14
  height: D,
25
15
  label: N,
26
16
  className: F
27
17
  });
28
18
  let B = j ?? R.length > 1, V = {
29
- fill: d.textMuted,
19
+ fill: e.textMuted,
30
20
  fontSize: 12
31
21
  }, H = (e) => {
32
22
  for (let t = C.length - 1; t >= 0; --t) {
@@ -35,11 +25,11 @@ function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, val
35
25
  }
36
26
  return -1;
37
27
  };
38
- return /* @__PURE__ */ x(_, {
28
+ return /* @__PURE__ */ u(o, {
39
29
  ariaLabel: z,
40
30
  height: D,
41
31
  className: F,
42
- a11y: /* @__PURE__ */ x(h, {
32
+ a11y: /* @__PURE__ */ u(i, {
43
33
  caption: z,
44
34
  xLabel: w,
45
35
  xKey: w,
@@ -47,10 +37,10 @@ function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, val
47
37
  series: R,
48
38
  valueFormat: O
49
39
  }),
50
- children: /* @__PURE__ */ x(n, {
40
+ children: /* @__PURE__ */ u(y, {
51
41
  width: "100%",
52
42
  height: "100%",
53
- children: /* @__PURE__ */ S(E === "area" ? u : l, {
43
+ children: /* @__PURE__ */ d(E === "area" ? p : _, {
54
44
  data: C,
55
45
  margin: {
56
46
  top: 12,
@@ -59,28 +49,28 @@ function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, val
59
49
  left: 4
60
50
  },
61
51
  children: [
62
- /* @__PURE__ */ x("defs", { children: R.map((e, t) => /* @__PURE__ */ S("linearGradient", {
52
+ /* @__PURE__ */ u("defs", { children: R.map((e, t) => /* @__PURE__ */ d("linearGradient", {
63
53
  id: `${I}-${t}`,
64
54
  x1: "0",
65
55
  y1: "0",
66
56
  x2: "0",
67
57
  y2: "1",
68
- children: [/* @__PURE__ */ x("stop", {
58
+ children: [/* @__PURE__ */ u("stop", {
69
59
  offset: "0%",
70
60
  stopColor: e.color,
71
61
  stopOpacity: .24
72
- }), /* @__PURE__ */ x("stop", {
62
+ }), /* @__PURE__ */ u("stop", {
73
63
  offset: "95%",
74
64
  stopColor: e.color,
75
65
  stopOpacity: .02
76
66
  })]
77
67
  }, e.key)) }),
78
- A ? /* @__PURE__ */ x(i, {
68
+ A ? /* @__PURE__ */ u(m, {
79
69
  vertical: !1,
80
- stroke: d.grid,
70
+ stroke: e.grid,
81
71
  strokeWidth: 1
82
72
  }) : null,
83
- /* @__PURE__ */ x(s, {
73
+ /* @__PURE__ */ u(x, {
84
74
  dataKey: w,
85
75
  tickLine: !1,
86
76
  axisLine: !1,
@@ -89,66 +79,66 @@ function C({ data: C, xKey: w, series: T, type: E = "area", height: D = 260, val
89
79
  minTickGap: 16,
90
80
  tickFormatter: k ? (e) => k(e) : void 0
91
81
  }),
92
- /* @__PURE__ */ x(c, {
82
+ /* @__PURE__ */ u(S, {
93
83
  tickLine: !1,
94
84
  axisLine: !1,
95
85
  tick: V,
96
86
  width: 48,
97
87
  tickFormatter: (e) => O(Number(e))
98
88
  }),
99
- /* @__PURE__ */ x(t, {
89
+ /* @__PURE__ */ u(b, {
100
90
  cursor: {
101
- stroke: d.axis,
91
+ stroke: e.axis,
102
92
  strokeWidth: 1
103
93
  },
104
- content: /* @__PURE__ */ x(y, {
94
+ content: /* @__PURE__ */ u(c, {
105
95
  valueFormat: O,
106
96
  labelFormat: k,
107
97
  hideLabel: !1
108
98
  })
109
99
  }),
110
- B ? /* @__PURE__ */ x(e, { content: /* @__PURE__ */ x(v, {}) }) : null,
111
- R.map((e, t) => E === "area" ? /* @__PURE__ */ x(o, {
100
+ B ? /* @__PURE__ */ u(h, { content: /* @__PURE__ */ u(s, {}) }) : null,
101
+ R.map((t, n) => E === "area" ? /* @__PURE__ */ u(f, {
112
102
  type: "monotone",
113
- dataKey: e.key,
114
- name: e.label,
115
- stroke: e.color,
103
+ dataKey: t.key,
104
+ name: t.label,
105
+ stroke: t.color,
116
106
  strokeWidth: 2,
117
- fill: `url(#${I}-${t})`,
107
+ fill: `url(#${I}-${n})`,
118
108
  isAnimationActive: !L,
119
109
  dot: !1,
120
110
  activeDot: {
121
111
  r: 4,
122
112
  strokeWidth: 2,
123
- stroke: d.surface,
124
- fill: e.color
113
+ stroke: e.surface,
114
+ fill: t.color
125
115
  }
126
- }, e.key) : /* @__PURE__ */ x(a, {
116
+ }, t.key) : /* @__PURE__ */ u(g, {
127
117
  type: "monotone",
128
- dataKey: e.key,
129
- name: e.label,
130
- stroke: e.color,
118
+ dataKey: t.key,
119
+ name: t.label,
120
+ stroke: t.color,
131
121
  strokeWidth: 2,
132
122
  isAnimationActive: !L,
133
123
  dot: !1,
134
124
  activeDot: {
135
125
  r: 4,
136
126
  strokeWidth: 2,
137
- stroke: d.surface,
138
- fill: e.color
127
+ stroke: e.surface,
128
+ fill: t.color
139
129
  }
140
- }, e.key)),
141
- M ? R.map((e) => {
142
- let t = H(e.key);
143
- return t < 0 ? null : /* @__PURE__ */ x(r, {
144
- x: C[t][w],
145
- y: C[t][e.key],
130
+ }, t.key)),
131
+ M ? R.map((t) => {
132
+ let n = H(t.key);
133
+ return n < 0 ? null : /* @__PURE__ */ u(v, {
134
+ x: C[n][w],
135
+ y: C[n][t.key],
146
136
  r: 4,
147
- fill: e.color,
148
- stroke: d.surface,
137
+ fill: t.color,
138
+ stroke: e.surface,
149
139
  strokeWidth: 2,
150
140
  isFront: !0
151
- }, `end-${e.key}`);
141
+ }, `end-${t.key}`);
152
142
  }) : null
153
143
  ]
154
144
  })
@@ -1 +1 @@
1
- {"version":3,"file":"TrendChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/TrendChart.tsx"],"sourcesContent":["import { useId } from \"react\";\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from \"./chartTheme\";\nimport {\n ChartDataTable,\n ChartEmpty,\n ChartFigure,\n ChartLegend,\n ChartTooltip,\n} from \"./ChartParts\";\n\nexport interface TrendChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the x-axis category/time value. */\n xKey: string;\n /** One or more numeric series. Single series reads on-brand. */\n series: ChartSeries[];\n /** Line, or gradient-filled area. Default `area`. */\n type?: \"line\" | \"area\";\n /** Pixel height of the plot. Default 260. */\n height?: number;\n /** Formats y values in the axis and tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats x tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the horizontal grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Emphasise each series' final point with a ringed dot. Default true. */\n showEndDots?: boolean;\n /** Message shown when `data` is empty — never fabricate a shape. */\n emptyLabel?: string;\n /** Accessible name for the figure. Default derived from the series labels. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * TrendChart — value-over-time as a line or gradient area (asset value,\n * emissions, depreciation). Theme-aware tokens, a hairline grid, a crosshair\n * tooltip, emphasised endpoints, a legend for multi-series, an empty state and\n * a screen-reader data table. Respects `prefers-reduced-motion`.\n */\nexport function TrendChart({\n data,\n xKey,\n series,\n type = \"area\",\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n showEndDots = true,\n emptyLabel,\n ariaLabel,\n className,\n}: TrendChartProps) {\n const gradientBase = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label =\n ariaLabel ?? `Trend of ${resolved.map((s) => s.label).join(\", \")}`;\n\n if (data.length === 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n\n const lastFiniteIndex = (key: string): number => {\n for (let i = data.length - 1; i >= 0; i -= 1) {\n const value = data[i][key];\n if (typeof value === \"number\" && Number.isFinite(value)) return i;\n }\n return -1;\n };\n\n const Chart = type === \"area\" ? AreaChart : LineChart;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <Chart data={data} margin={{ top: 12, right: 16, bottom: 4, left: 4 }}>\n <defs>\n {resolved.map((s, index) => (\n <linearGradient\n key={s.key}\n id={`${gradientBase}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={s.color} stopOpacity={0.24} />\n <stop offset=\"95%\" stopColor={s.color} stopOpacity={0.02} />\n </linearGradient>\n ))}\n </defs>\n\n {showGrid ? (\n <CartesianGrid\n vertical={false}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n <XAxis\n dataKey={xKey}\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n minTickGap={16}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n\n <Tooltip\n cursor={{ stroke: chartTokens.axis, strokeWidth: 1 }}\n content={\n <ChartTooltip\n valueFormat={valueFormat}\n labelFormat={xTickFormat}\n hideLabel={false}\n />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) =>\n type === \"area\" ? (\n <Area\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n fill={`url(#${gradientBase}-${index})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{\n r: 4,\n strokeWidth: 2,\n stroke: chartTokens.surface,\n fill: s.color,\n }}\n />\n ) : (\n <Line\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{\n r: 4,\n strokeWidth: 2,\n stroke: chartTokens.surface,\n fill: s.color,\n }}\n />\n ),\n )}\n\n {showEndDots\n ? resolved.map((s) => {\n const index = lastFiniteIndex(s.key);\n if (index < 0) return null;\n return (\n <ReferenceDot\n key={`end-${s.key}`}\n x={data[index][xKey] as string | number}\n y={data[index][s.key] as number}\n r={4}\n fill={s.color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n );\n })\n : null}\n </Chart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"TrendChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/TrendChart.tsx"],"sourcesContent":["import { useId } from \"react\";\nimport {\n Area,\n AreaChart,\n CartesianGrid,\n Legend,\n Line,\n LineChart,\n ReferenceDot,\n ResponsiveContainer,\n Tooltip,\n XAxis,\n YAxis,\n} from \"recharts\";\nimport {\n chartTokens,\n defaultSeriesColor,\n formatNumber,\n usePrefersReducedMotion,\n type ChartDatum,\n type ChartSeries,\n type ValueFormatter,\n} from \"./chartTheme\";\nimport {\n ChartDataTable,\n ChartEmpty,\n ChartFigure,\n ChartLegend,\n ChartTooltip,\n} from \"./ChartParts\";\n\nexport interface TrendChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the x-axis category/time value. */\n xKey: string;\n /** One or more numeric series. Single series reads on-brand. */\n series: ChartSeries[];\n /** Line, or gradient-filled area. Default `area`. */\n type?: \"line\" | \"area\";\n /** Pixel height of the plot. Default 260. */\n height?: number;\n /** Formats y values in the axis and tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats x tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the horizontal grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Emphasise each series' final point with a ringed dot. Default true. */\n showEndDots?: boolean;\n /** Message shown when `data` is empty — never fabricate a shape. */\n emptyLabel?: string;\n /** Accessible name for the figure. Default derived from the series labels. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * TrendChart — value-over-time as a line or gradient area (asset value,\n * emissions, depreciation). Theme-aware tokens, a hairline grid, a crosshair\n * tooltip, emphasised endpoints, a legend for multi-series, an empty state and\n * a screen-reader data table. Respects `prefers-reduced-motion`.\n */\nexport function TrendChart({\n data,\n xKey,\n series,\n type = \"area\",\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n showEndDots = true,\n emptyLabel,\n ariaLabel,\n className,\n}: TrendChartProps) {\n const gradientBase = useId();\n const reducedMotion = usePrefersReducedMotion();\n\n const resolved = series.map((s, index) => ({\n ...s,\n label: s.label ?? s.key,\n color: s.color ?? defaultSeriesColor(index, series.length),\n }));\n const label =\n ariaLabel ?? `Trend of ${resolved.map((s) => s.label).join(\", \")}`;\n\n if (data.length === 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n\n const lastFiniteIndex = (key: string): number => {\n for (let i = data.length - 1; i >= 0; i -= 1) {\n const value = data[i][key];\n if (typeof value === \"number\" && Number.isFinite(value)) return i;\n }\n return -1;\n };\n\n const Chart = type === \"area\" ? AreaChart : LineChart;\n\n return (\n <ChartFigure\n ariaLabel={label}\n height={height}\n className={className}\n a11y={\n <ChartDataTable\n caption={label}\n xLabel={xKey}\n xKey={xKey}\n data={data}\n series={resolved}\n valueFormat={valueFormat}\n />\n }\n >\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <Chart data={data} margin={{ top: 12, right: 16, bottom: 4, left: 4 }}>\n <defs>\n {resolved.map((s, index) => (\n <linearGradient\n key={s.key}\n id={`${gradientBase}-${index}`}\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"0%\" stopColor={s.color} stopOpacity={0.24} />\n <stop offset=\"95%\" stopColor={s.color} stopOpacity={0.02} />\n </linearGradient>\n ))}\n </defs>\n\n {showGrid ? (\n <CartesianGrid\n vertical={false}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n <XAxis\n dataKey={xKey}\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n minTickGap={16}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n <YAxis\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n\n <Tooltip\n cursor={{ stroke: chartTokens.axis, strokeWidth: 1 }}\n content={\n <ChartTooltip\n valueFormat={valueFormat}\n labelFormat={xTickFormat}\n hideLabel={false}\n />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) =>\n type === \"area\" ? (\n <Area\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n fill={`url(#${gradientBase}-${index})`}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{\n r: 4,\n strokeWidth: 2,\n stroke: chartTokens.surface,\n fill: s.color,\n }}\n />\n ) : (\n <Line\n key={s.key}\n type=\"monotone\"\n dataKey={s.key}\n name={s.label}\n stroke={s.color}\n strokeWidth={2}\n isAnimationActive={!reducedMotion}\n dot={false}\n activeDot={{\n r: 4,\n strokeWidth: 2,\n stroke: chartTokens.surface,\n fill: s.color,\n }}\n />\n ),\n )}\n\n {showEndDots\n ? resolved.map((s) => {\n const index = lastFiniteIndex(s.key);\n if (index < 0) return null;\n return (\n <ReferenceDot\n key={`end-${s.key}`}\n x={data[index][xKey] as string | number}\n y={data[index][s.key] as number}\n r={4}\n fill={s.color}\n stroke={chartTokens.surface}\n strokeWidth={2}\n isFront\n />\n );\n })\n : null}\n </Chart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":";;;;;;AAiEA,SAAgB,EAAW,EACzB,SACA,SACA,WACA,UAAO,QACP,YAAS,KACT,iBAAc,GACd,gBACA,cAAW,IACX,eACA,iBAAc,IACd,eACA,cACA,gBACkB;CAClB,IAAM,IAAe,GAAO,EACtB,IAAgB,GAAyB,EAEzC,IAAW,EAAO,KAAK,GAAG,OAAW;EACzC,GAAG;EACH,OAAO,EAAE,SAAS,EAAE;EACpB,OAAO,EAAE,SAAS,EAAmB,GAAO,EAAO,OAAO;EAC3D,EAAE,EACG,IACJ,KAAa,YAAY,EAAS,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK;AAElE,KAAI,EAAK,WAAW,EAClB,QACE,kBAAC,GAAD;EAAoB;EAAQ,OAAO;EAAuB;EAAa,CAAA;CAI3E,IAAM,IAAa,KAAc,EAAS,SAAS,GAC7C,IAAW;EAAE,MAAM,EAAY;EAAW,UAAU;EAAI,EAExD,KAAmB,MAAwB;AAC/C,OAAK,IAAI,IAAI,EAAK,SAAS,GAAG,KAAK,GAAG,KAAQ;GAC5C,IAAM,IAAQ,EAAK,GAAG;AACtB,OAAI,OAAO,KAAU,YAAY,OAAO,SAAS,EAAM,CAAE,QAAO;;AAElE,SAAO;;AAKT,QACE,kBAAC,GAAD;EACE,WAAW;EACH;EACG;EACX,MACE,kBAAC,GAAD;GACE,SAAS;GACT,QAAQ;GACF;GACA;GACN,QAAQ;GACK;GACb,CAAA;YAGJ,kBAAC,GAAD;GAAqB,OAAM;GAAO,QAAO;aACvC,kBAnBQ,MAAS,SAAS,IAAY,GAmBtC;IAAa;IAAM,QAAQ;KAAE,KAAK;KAAI,OAAO;KAAI,QAAQ;KAAG,MAAM;KAAG;cAArE;KACE,kBAAC,QAAD,EAAA,UACG,EAAS,KAAK,GAAG,MAChB,kBAAC,kBAAD;MAEE,IAAI,GAAG,EAAa,GAAG;MACvB,IAAG;MACH,IAAG;MACH,IAAG;MACH,IAAG;gBANL,CAQE,kBAAC,QAAD;OAAM,QAAO;OAAK,WAAW,EAAE;OAAO,aAAa;OAAQ,CAAA,EAC3D,kBAAC,QAAD;OAAM,QAAO;OAAM,WAAW,EAAE;OAAO,aAAa;OAAQ,CAAA,CAC7C;QATV,EAAE,IASQ,CACjB,EACG,CAAA;KAEN,IACC,kBAAC,GAAD;MACE,UAAU;MACV,QAAQ,EAAY;MACpB,aAAa;MACb,CAAA,GACA;KAEJ,kBAAC,GAAD;MACE,SAAS;MACT,UAAU;MACV,UAAU;MACV,MAAM;MACN,YAAY;MACZ,YAAY;MACZ,eACE,KACK,MAAU,EAAY,EAAyB,GAChD,KAAA;MAEN,CAAA;KACF,kBAAC,GAAD;MACE,UAAU;MACV,UAAU;MACV,MAAM;MACN,OAAO;MACP,gBAAgB,MAAU,EAAY,OAAO,EAAM,CAAC;MACpD,CAAA;KAEF,kBAAC,GAAD;MACE,QAAQ;OAAE,QAAQ,EAAY;OAAM,aAAa;OAAG;MACpD,SACE,kBAAC,GAAD;OACe;OACb,aAAa;OACb,WAAW;OACX,CAAA;MAEJ,CAAA;KAED,IAAa,kBAAC,GAAD,EAAQ,SAAS,kBAAC,GAAD,EAAe,CAAA,EAAI,CAAA,GAAG;KAEpD,EAAS,KAAK,GAAG,MAChB,MAAS,SACP,kBAAC,GAAD;MAEE,MAAK;MACL,SAAS,EAAE;MACX,MAAM,EAAE;MACR,QAAQ,EAAE;MACV,aAAa;MACb,MAAM,QAAQ,EAAa,GAAG,EAAM;MACpC,mBAAmB,CAAC;MACpB,KAAK;MACL,WAAW;OACT,GAAG;OACH,aAAa;OACb,QAAQ,EAAY;OACpB,MAAM,EAAE;OACT;MACD,EAfK,EAAE,IAeP,GAEF,kBAAC,GAAD;MAEE,MAAK;MACL,SAAS,EAAE;MACX,MAAM,EAAE;MACR,QAAQ,EAAE;MACV,aAAa;MACb,mBAAmB,CAAC;MACpB,KAAK;MACL,WAAW;OACT,GAAG;OACH,aAAa;OACb,QAAQ,EAAY;OACpB,MAAM,EAAE;OACT;MACD,EAdK,EAAE,IAcP,CAEL;KAEA,IACG,EAAS,KAAK,MAAM;MAClB,IAAM,IAAQ,EAAgB,EAAE,IAAI;AAEpC,aADI,IAAQ,IAAU,OAEpB,kBAAC,GAAD;OAEE,GAAG,EAAK,GAAO;OACf,GAAG,EAAK,GAAO,EAAE;OACjB,GAAG;OACH,MAAM,EAAE;OACR,QAAQ,EAAY;OACpB,aAAa;OACb,SAAA;OACA,EARK,OAAO,EAAE,MAQd;OAEJ,GACF;KACE;;GACY,CAAA;EACV,CAAA"}
@@ -6,5 +6,6 @@ export { TimeCampusRoot } from './TimeCampusRoot';
6
6
  export type { TimeCampusRootProps, NavItem, FooterItem } from './types';
7
7
  export { useTimeCampus, useTimeCampusNavigate, } from './providers/TimeCampusProvider';
8
8
  export { useTimeCampusStore } from './store/timecampusStore';
9
+ export * from '../services/createSandboxAssistantTransport';
9
10
  export * from '../generated/wspace-operations';
10
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/timecampus/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,YAAY,EAAE,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGxE,OAAO,EACL,aAAa,EACb,qBAAqB,GACtB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,cAAc,gCAAgC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/timecampus/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGlD,YAAY,EAAE,mBAAmB,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAGxE,OAAO,EACL,aAAa,EACb,qBAAqB,GACtB,MAAM,gCAAgC,CAAC;AAGxC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAO7D,cAAc,6CAA6C,CAAC;AAG5D,cAAc,gCAAgC,CAAC"}
@@ -2,3 +2,4 @@ import "./providers/TimeCampusProvider.js";
2
2
  import "../generated/wspace-operations.js";
3
3
  import "./TimeCampusRoot.js";
4
4
  import "./store/timecampusStore.js";
5
+ import "../services/createSandboxAssistantTransport.js";