@burdenoff/microfe-timecampus 2026.710.1 → 2026.710.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +2 -1
- package/dist/services/assistantApi.js +248 -0
- package/dist/services/assistantApi.js.map +1 -0
- package/dist/services/createSandboxAssistantTransport.js +120 -0
- package/dist/services/createSandboxAssistantTransport.js.map +1 -0
- package/dist/timecampus/components/DataTable.js +1 -0
- package/dist/timecampus/components/FilterBar.js +1 -0
- package/dist/timecampus/components/charts/BalanceWheel.js +38 -43
- package/dist/timecampus/components/charts/BalanceWheel.js.map +1 -1
- package/dist/timecampus/components/charts/BarsChart.js +24 -31
- package/dist/timecampus/components/charts/BarsChart.js.map +1 -1
- package/dist/timecampus/components/charts/DonutChart.js +36 -40
- package/dist/timecampus/components/charts/DonutChart.js.map +1 -1
- package/dist/timecampus/components/charts/RadialGauge.js +14 -17
- package/dist/timecampus/components/charts/RadialGauge.js.map +1 -1
- package/dist/timecampus/components/charts/Sparkline.js +2 -0
- package/dist/timecampus/components/charts/TrendChart.js +47 -57
- package/dist/timecampus/components/charts/TrendChart.js.map +1 -1
- package/dist/timecampus/index.d.ts +1 -0
- package/dist/timecampus/index.d.ts.map +1 -1
- package/dist/timecampus/index.js +1 -0
- package/dist/timecampus/pages/expense-tracking/ExpenseTrackingPage.js +4 -4
- package/dist/timecampus/pages/time-approval/TimeApprovalPage.js +4 -4
- package/dist/timecampus/providers/TimeCampusProvider.js +32 -32
- package/dist/timecampus/utils/helpers.js +2 -2
- package/dist/utils/pageContext.js +52 -0
- package/dist/utils/pageContext.js.map +1 -0
- package/package.json +1 -1
- package/dist/_virtual/_rolldown/runtime.js +0 -20
|
@@ -1,16 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { PolarAngleAxis as
|
|
5
|
-
import { Radar as i } from "../../../node_modules/recharts/es6/polar/Radar.js";
|
|
6
|
-
import { RadarChart as a } from "../../../node_modules/recharts/es6/chart/RadarChart.js";
|
|
7
|
-
import { chartTokens as o, usePrefersReducedMotion as s } from "./chartTheme.js";
|
|
8
|
-
import { ChartEmpty as c, ChartTooltip as l, srOnlyStyle as u } from "./ChartParts.js";
|
|
9
|
-
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
1
|
+
import { chartTokens as e, usePrefersReducedMotion as t } from "./chartTheme.js";
|
|
2
|
+
import { ChartEmpty as n, ChartTooltip as r, srOnlyStyle as i } from "./ChartParts.js";
|
|
3
|
+
import { jsx as a, jsxs as o } from "react/jsx-runtime";
|
|
4
|
+
import { PolarAngleAxis as s, PolarGrid as c, Radar as l, RadarChart as u, ResponsiveContainer as d, Tooltip as f } from "recharts";
|
|
10
5
|
//#region src/timecampus/components/charts/BalanceWheel.tsx
|
|
11
6
|
function p({ data: p, height: m = 320, emptyLabel: h, ariaLabel: g, className: _ }) {
|
|
12
|
-
let v =
|
|
13
|
-
if (y.length === 0 || b <= 0) return /* @__PURE__ */
|
|
7
|
+
let v = t(), y = p.filter((e) => Number.isFinite(e.actualShare) && e.actualShare >= 0), b = y.reduce((e, t) => e + t.actualShare, 0), x = y.some((e) => typeof e.desiredShare == "number" && Number.isFinite(e.desiredShare));
|
|
8
|
+
if (y.length === 0 || b <= 0) return /* @__PURE__ */ a(n, {
|
|
14
9
|
height: m,
|
|
15
10
|
label: h,
|
|
16
11
|
className: _
|
|
@@ -20,47 +15,47 @@ function p({ data: p, height: m = 320, emptyLabel: h, ariaLabel: g, className: _
|
|
|
20
15
|
Actual: Math.round(e.actualShare * 1e3) / 10,
|
|
21
16
|
Desired: typeof e.desiredShare == "number" && Number.isFinite(e.desiredShare) ? Math.round(e.desiredShare * 1e3) / 10 : 0
|
|
22
17
|
})), C = g ?? `Life balance across ${y.map((e) => e.label).join(", ")}`;
|
|
23
|
-
return /* @__PURE__ */
|
|
18
|
+
return /* @__PURE__ */ o("figure", {
|
|
24
19
|
role: "img",
|
|
25
20
|
"aria-label": C,
|
|
26
21
|
className: _,
|
|
27
22
|
children: [
|
|
28
|
-
/* @__PURE__ */
|
|
23
|
+
/* @__PURE__ */ a("div", {
|
|
29
24
|
style: { height: m },
|
|
30
|
-
children: /* @__PURE__ */ d
|
|
25
|
+
children: /* @__PURE__ */ a(d, {
|
|
31
26
|
width: "100%",
|
|
32
27
|
height: "100%",
|
|
33
|
-
children: /* @__PURE__ */
|
|
28
|
+
children: /* @__PURE__ */ o(u, {
|
|
34
29
|
data: S,
|
|
35
30
|
outerRadius: "72%",
|
|
36
31
|
children: [
|
|
37
|
-
/* @__PURE__ */
|
|
38
|
-
/* @__PURE__ */
|
|
32
|
+
/* @__PURE__ */ a(c, { stroke: e.grid }),
|
|
33
|
+
/* @__PURE__ */ a(s, {
|
|
39
34
|
dataKey: "label",
|
|
40
35
|
tick: {
|
|
41
|
-
fill:
|
|
36
|
+
fill: e.textSecondary,
|
|
42
37
|
fontSize: 11
|
|
43
38
|
}
|
|
44
39
|
}),
|
|
45
|
-
/* @__PURE__ */
|
|
40
|
+
/* @__PURE__ */ a(f, {
|
|
46
41
|
cursor: !1,
|
|
47
|
-
content: /* @__PURE__ */
|
|
42
|
+
content: /* @__PURE__ */ a(r, { valueFormat: (e) => `${e}%` })
|
|
48
43
|
}),
|
|
49
|
-
x && /* @__PURE__ */
|
|
44
|
+
x && /* @__PURE__ */ a(l, {
|
|
50
45
|
name: "Desired",
|
|
51
46
|
dataKey: "Desired",
|
|
52
|
-
stroke:
|
|
47
|
+
stroke: e.textMuted,
|
|
53
48
|
strokeDasharray: "4 3",
|
|
54
49
|
strokeWidth: 1.5,
|
|
55
50
|
fill: "transparent",
|
|
56
51
|
isAnimationActive: !v
|
|
57
52
|
}),
|
|
58
|
-
/* @__PURE__ */
|
|
53
|
+
/* @__PURE__ */ a(l, {
|
|
59
54
|
name: "Actual",
|
|
60
55
|
dataKey: "Actual",
|
|
61
|
-
stroke:
|
|
56
|
+
stroke: e.brand,
|
|
62
57
|
strokeWidth: 2,
|
|
63
|
-
fill:
|
|
58
|
+
fill: e.brand,
|
|
64
59
|
fillOpacity: .28,
|
|
65
60
|
isAnimationActive: !v
|
|
66
61
|
})
|
|
@@ -68,49 +63,49 @@ function p({ data: p, height: m = 320, emptyLabel: h, ariaLabel: g, className: _
|
|
|
68
63
|
})
|
|
69
64
|
})
|
|
70
65
|
}),
|
|
71
|
-
/* @__PURE__ */
|
|
66
|
+
/* @__PURE__ */ o("ul", {
|
|
72
67
|
className: "mt-2 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 text-xs text-text-secondary",
|
|
73
|
-
children: [/* @__PURE__ */
|
|
68
|
+
children: [/* @__PURE__ */ o("li", {
|
|
74
69
|
className: "flex items-center gap-1.5",
|
|
75
|
-
children: [/* @__PURE__ */
|
|
70
|
+
children: [/* @__PURE__ */ a("span", {
|
|
76
71
|
"aria-hidden": "true",
|
|
77
72
|
className: "h-2.5 w-2.5 rounded-[3px]",
|
|
78
|
-
style: { backgroundColor:
|
|
73
|
+
style: { backgroundColor: e.brand }
|
|
79
74
|
}), "Actual"]
|
|
80
|
-
}), x && /* @__PURE__ */
|
|
75
|
+
}), x && /* @__PURE__ */ o("li", {
|
|
81
76
|
className: "flex items-center gap-1.5",
|
|
82
|
-
children: [/* @__PURE__ */
|
|
77
|
+
children: [/* @__PURE__ */ a("span", {
|
|
83
78
|
"aria-hidden": "true",
|
|
84
79
|
className: "h-0 w-3.5 border-t-2 border-dashed",
|
|
85
|
-
style: { borderColor:
|
|
80
|
+
style: { borderColor: e.textMuted }
|
|
86
81
|
}), "Desired"]
|
|
87
82
|
})]
|
|
88
83
|
}),
|
|
89
|
-
/* @__PURE__ */
|
|
90
|
-
style:
|
|
84
|
+
/* @__PURE__ */ o("table", {
|
|
85
|
+
style: i,
|
|
91
86
|
children: [
|
|
92
|
-
/* @__PURE__ */
|
|
93
|
-
/* @__PURE__ */
|
|
94
|
-
/* @__PURE__ */
|
|
87
|
+
/* @__PURE__ */ a("caption", { children: C }),
|
|
88
|
+
/* @__PURE__ */ a("thead", { children: /* @__PURE__ */ o("tr", { children: [
|
|
89
|
+
/* @__PURE__ */ a("th", {
|
|
95
90
|
scope: "col",
|
|
96
91
|
children: "Domain"
|
|
97
92
|
}),
|
|
98
|
-
/* @__PURE__ */
|
|
93
|
+
/* @__PURE__ */ a("th", {
|
|
99
94
|
scope: "col",
|
|
100
95
|
children: "Actual share"
|
|
101
96
|
}),
|
|
102
|
-
x && /* @__PURE__ */
|
|
97
|
+
x && /* @__PURE__ */ a("th", {
|
|
103
98
|
scope: "col",
|
|
104
99
|
children: "Desired share"
|
|
105
100
|
})
|
|
106
101
|
] }) }),
|
|
107
|
-
/* @__PURE__ */
|
|
108
|
-
/* @__PURE__ */
|
|
102
|
+
/* @__PURE__ */ a("tbody", { children: y.map((e) => /* @__PURE__ */ o("tr", { children: [
|
|
103
|
+
/* @__PURE__ */ a("th", {
|
|
109
104
|
scope: "row",
|
|
110
105
|
children: e.label
|
|
111
106
|
}),
|
|
112
|
-
/* @__PURE__ */
|
|
113
|
-
x && /* @__PURE__ */
|
|
107
|
+
/* @__PURE__ */ a("td", { children: `${Math.round(e.actualShare * 100)}%` }),
|
|
108
|
+
x && /* @__PURE__ */ a("td", { children: typeof e.desiredShare == "number" ? `${Math.round(e.desiredShare * 100)}%` : "—" })
|
|
114
109
|
] }, e.domain)) })
|
|
115
110
|
]
|
|
116
111
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BalanceWheel.js","names":[],"sources":["../../../../src/timecampus/components/charts/BalanceWheel.tsx"],"sourcesContent":["import {\n PolarAngleAxis,\n PolarGrid,\n Radar,\n RadarChart,\n ResponsiveContainer,\n Tooltip,\n} from \"recharts\";\nimport { chartTokens, usePrefersReducedMotion } from \"./chartTheme\";\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from \"./ChartParts\";\n\n/** One life-domain axis of the wheel: the actual vs the desired share of time. */\nexport interface BalanceWheelDatum {\n /** Stable domain key (e.g. \"FAMILY\"). */\n domain: string;\n /** Human label shown on the axis (e.g. \"Family\"). */\n label: string;\n /** Actual share of covered time, 0..1. */\n actualShare: number;\n /** Desired share the user declared, 0..1. Omit when no target is set. */\n desiredShare?: number | null;\n}\n\nexport interface BalanceWheelProps {\n data: BalanceWheelDatum[];\n /** Pixel height of the wheel. Default 320. */\n height?: number;\n /** Message when there is no covered time to plot. */\n emptyLabel?: string;\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BalanceWheel — the signature life-balance visual: a radar of how your finite\n * time actually splits across life domains (solid brand polygon) overlaid with\n * the balance you said you WANT (dashed muted polygon). The gap between the two\n * is the insight. Token-only, theme-aware, and renders an honest empty state —\n * never a fake polygon — when there is no covered time. Values are real shares\n * passed in by the page; this component never fabricates data.\n */\nexport function BalanceWheel({\n data,\n height = 320,\n emptyLabel,\n ariaLabel,\n className,\n}: BalanceWheelProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const rows = data.filter(\n (d) => Number.isFinite(d.actualShare) && d.actualShare >= 0,\n );\n const total = rows.reduce((sum, d) => sum + d.actualShare, 0);\n const hasDesired = rows.some(\n (d) =>\n typeof d.desiredShare === \"number\" && Number.isFinite(d.desiredShare),\n );\n\n if (rows.length === 0 || total <= 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const chartData = rows.map((d) => ({\n label: d.label,\n Actual: Math.round(d.actualShare * 1000) / 10,\n Desired:\n typeof d.desiredShare === \"number\" && Number.isFinite(d.desiredShare)\n ? Math.round(d.desiredShare * 1000) / 10\n : 0,\n }));\n\n const label =\n ariaLabel ?? `Life balance across ${rows.map((d) => d.label).join(\", \")}`;\n\n return (\n <figure role=\"img\" aria-label={label} className={className}>\n <div style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadarChart data={chartData} outerRadius=\"72%\">\n <PolarGrid stroke={chartTokens.grid} />\n <PolarAngleAxis\n dataKey=\"label\"\n tick={{ fill: chartTokens.textSecondary, fontSize: 11 }}\n />\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={(v) => `${v}%`} />}\n />\n {hasDesired && (\n <Radar\n name=\"Desired\"\n dataKey=\"Desired\"\n stroke={chartTokens.textMuted}\n strokeDasharray=\"4 3\"\n strokeWidth={1.5}\n fill=\"transparent\"\n isAnimationActive={!reducedMotion}\n />\n )}\n <Radar\n name=\"Actual\"\n dataKey=\"Actual\"\n stroke={chartTokens.brand}\n strokeWidth={2}\n fill={chartTokens.brand}\n fillOpacity={0.28}\n isAnimationActive={!reducedMotion}\n />\n </RadarChart>\n </ResponsiveContainer>\n </div>\n\n <ul className=\"mt-2 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: chartTokens.brand }}\n />\n Actual\n </li>\n {hasDesired && (\n <li className=\"flex items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-0 w-3.5 border-t-2 border-dashed\"\n style={{ borderColor: chartTokens.textMuted }}\n />\n Desired\n </li>\n )}\n </ul>\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Domain</th>\n <th scope=\"col\">Actual share</th>\n {hasDesired && <th scope=\"col\">Desired share</th>}\n </tr>\n </thead>\n <tbody>\n {rows.map((d) => (\n <tr key={d.domain}>\n <th scope=\"row\">{d.label}</th>\n <td>{`${Math.round(d.actualShare * 100)}%`}</td>\n {hasDesired && (\n <td>\n {typeof d.desiredShare === \"number\"\n ? `${Math.round(d.desiredShare * 100)}%`\n : \"—\"}\n </td>\n )}\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BalanceWheel.js","names":[],"sources":["../../../../src/timecampus/components/charts/BalanceWheel.tsx"],"sourcesContent":["import {\n PolarAngleAxis,\n PolarGrid,\n Radar,\n RadarChart,\n ResponsiveContainer,\n Tooltip,\n} from \"recharts\";\nimport { chartTokens, usePrefersReducedMotion } from \"./chartTheme\";\nimport { ChartEmpty, ChartTooltip, srOnlyStyle } from \"./ChartParts\";\n\n/** One life-domain axis of the wheel: the actual vs the desired share of time. */\nexport interface BalanceWheelDatum {\n /** Stable domain key (e.g. \"FAMILY\"). */\n domain: string;\n /** Human label shown on the axis (e.g. \"Family\"). */\n label: string;\n /** Actual share of covered time, 0..1. */\n actualShare: number;\n /** Desired share the user declared, 0..1. Omit when no target is set. */\n desiredShare?: number | null;\n}\n\nexport interface BalanceWheelProps {\n data: BalanceWheelDatum[];\n /** Pixel height of the wheel. Default 320. */\n height?: number;\n /** Message when there is no covered time to plot. */\n emptyLabel?: string;\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BalanceWheel — the signature life-balance visual: a radar of how your finite\n * time actually splits across life domains (solid brand polygon) overlaid with\n * the balance you said you WANT (dashed muted polygon). The gap between the two\n * is the insight. Token-only, theme-aware, and renders an honest empty state —\n * never a fake polygon — when there is no covered time. Values are real shares\n * passed in by the page; this component never fabricates data.\n */\nexport function BalanceWheel({\n data,\n height = 320,\n emptyLabel,\n ariaLabel,\n className,\n}: BalanceWheelProps) {\n const reducedMotion = usePrefersReducedMotion();\n\n const rows = data.filter(\n (d) => Number.isFinite(d.actualShare) && d.actualShare >= 0,\n );\n const total = rows.reduce((sum, d) => sum + d.actualShare, 0);\n const hasDesired = rows.some(\n (d) =>\n typeof d.desiredShare === \"number\" && Number.isFinite(d.desiredShare),\n );\n\n if (rows.length === 0 || total <= 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const chartData = rows.map((d) => ({\n label: d.label,\n Actual: Math.round(d.actualShare * 1000) / 10,\n Desired:\n typeof d.desiredShare === \"number\" && Number.isFinite(d.desiredShare)\n ? Math.round(d.desiredShare * 1000) / 10\n : 0,\n }));\n\n const label =\n ariaLabel ?? `Life balance across ${rows.map((d) => d.label).join(\", \")}`;\n\n return (\n <figure role=\"img\" aria-label={label} className={className}>\n <div style={{ height }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <RadarChart data={chartData} outerRadius=\"72%\">\n <PolarGrid stroke={chartTokens.grid} />\n <PolarAngleAxis\n dataKey=\"label\"\n tick={{ fill: chartTokens.textSecondary, fontSize: 11 }}\n />\n <Tooltip\n cursor={false}\n content={<ChartTooltip valueFormat={(v) => `${v}%`} />}\n />\n {hasDesired && (\n <Radar\n name=\"Desired\"\n dataKey=\"Desired\"\n stroke={chartTokens.textMuted}\n strokeDasharray=\"4 3\"\n strokeWidth={1.5}\n fill=\"transparent\"\n isAnimationActive={!reducedMotion}\n />\n )}\n <Radar\n name=\"Actual\"\n dataKey=\"Actual\"\n stroke={chartTokens.brand}\n strokeWidth={2}\n fill={chartTokens.brand}\n fillOpacity={0.28}\n isAnimationActive={!reducedMotion}\n />\n </RadarChart>\n </ResponsiveContainer>\n </div>\n\n <ul className=\"mt-2 flex flex-wrap items-center justify-center gap-x-4 gap-y-1.5 text-xs text-text-secondary\">\n <li className=\"flex items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-2.5 w-2.5 rounded-[3px]\"\n style={{ backgroundColor: chartTokens.brand }}\n />\n Actual\n </li>\n {hasDesired && (\n <li className=\"flex items-center gap-1.5\">\n <span\n aria-hidden=\"true\"\n className=\"h-0 w-3.5 border-t-2 border-dashed\"\n style={{ borderColor: chartTokens.textMuted }}\n />\n Desired\n </li>\n )}\n </ul>\n\n <table style={srOnlyStyle}>\n <caption>{label}</caption>\n <thead>\n <tr>\n <th scope=\"col\">Domain</th>\n <th scope=\"col\">Actual share</th>\n {hasDesired && <th scope=\"col\">Desired share</th>}\n </tr>\n </thead>\n <tbody>\n {rows.map((d) => (\n <tr key={d.domain}>\n <th scope=\"row\">{d.label}</th>\n <td>{`${Math.round(d.actualShare * 100)}%`}</td>\n {hasDesired && (\n <td>\n {typeof d.desiredShare === \"number\"\n ? `${Math.round(d.desiredShare * 100)}%`\n : \"—\"}\n </td>\n )}\n </tr>\n ))}\n </tbody>\n </table>\n </figure>\n );\n}\n"],"mappings":"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"}
|
|
@@ -1,28 +1,21 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { Bar as
|
|
5
|
-
import { CartesianGrid as i } from "../../../node_modules/recharts/es6/cartesian/CartesianGrid.js";
|
|
6
|
-
import { XAxis as a } from "../../../node_modules/recharts/es6/cartesian/XAxis.js";
|
|
7
|
-
import { YAxis as o } from "../../../node_modules/recharts/es6/cartesian/YAxis.js";
|
|
8
|
-
import { BarChart as s } from "../../../node_modules/recharts/es6/chart/BarChart.js";
|
|
9
|
-
import { chartTokens as c, defaultSeriesColor as l, formatNumber as u, usePrefersReducedMotion as d } from "./chartTheme.js";
|
|
10
|
-
import { ChartDataTable as f, ChartEmpty as p, ChartFigure as m, ChartLegend as h, ChartTooltip as g } from "./ChartParts.js";
|
|
11
|
-
import { Fragment as _, jsx as v, jsxs as y } 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 { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
4
|
+
import { Bar as f, BarChart as p, CartesianGrid as m, Legend as h, ResponsiveContainer as g, Tooltip as _, XAxis as v, YAxis as y } from "recharts";
|
|
12
5
|
//#region src/timecampus/components/charts/BarsChart.tsx
|
|
13
|
-
function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked: w = !1, height: T = 260, valueFormat: E =
|
|
14
|
-
let P =
|
|
6
|
+
function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked: w = !1, height: T = 260, valueFormat: E = n, xTickFormat: D, showGrid: O = !0, showLegend: k, categoryWidth: A = 96, emptyLabel: j, ariaLabel: M, className: N }) {
|
|
7
|
+
let P = r(), F = S.map((e, n) => ({
|
|
15
8
|
...e,
|
|
16
9
|
label: e.label ?? e.key,
|
|
17
|
-
color: e.color ??
|
|
10
|
+
color: e.color ?? t(n, S.length)
|
|
18
11
|
})), I = M ?? `${F.map((e) => e.label).join(", ")} by ${x}`;
|
|
19
|
-
if (b.length === 0) return /* @__PURE__ */
|
|
12
|
+
if (b.length === 0) return /* @__PURE__ */ u(a, {
|
|
20
13
|
height: T,
|
|
21
14
|
label: j,
|
|
22
15
|
className: N
|
|
23
16
|
});
|
|
24
17
|
let L = C === "vertical", R = k ?? F.length > 1, z = {
|
|
25
|
-
fill:
|
|
18
|
+
fill: e.textMuted,
|
|
26
19
|
fontSize: 12
|
|
27
20
|
}, B = F.length - 1, V = (e) => !w || e === B ? L ? [
|
|
28
21
|
4,
|
|
@@ -40,11 +33,11 @@ function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked:
|
|
|
40
33
|
0,
|
|
41
34
|
0
|
|
42
35
|
], H = w ? "stack" : void 0;
|
|
43
|
-
return /* @__PURE__ */
|
|
36
|
+
return /* @__PURE__ */ u(o, {
|
|
44
37
|
ariaLabel: I,
|
|
45
38
|
height: T,
|
|
46
39
|
className: N,
|
|
47
|
-
a11y: /* @__PURE__ */
|
|
40
|
+
a11y: /* @__PURE__ */ u(i, {
|
|
48
41
|
caption: I,
|
|
49
42
|
xLabel: x,
|
|
50
43
|
xKey: x,
|
|
@@ -52,10 +45,10 @@ function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked:
|
|
|
52
45
|
series: F,
|
|
53
46
|
valueFormat: E
|
|
54
47
|
}),
|
|
55
|
-
children: /* @__PURE__ */
|
|
48
|
+
children: /* @__PURE__ */ u(g, {
|
|
56
49
|
width: "100%",
|
|
57
50
|
height: "100%",
|
|
58
|
-
children: /* @__PURE__ */
|
|
51
|
+
children: /* @__PURE__ */ d(p, {
|
|
59
52
|
data: b,
|
|
60
53
|
layout: L ? "horizontal" : "vertical",
|
|
61
54
|
margin: {
|
|
@@ -66,13 +59,13 @@ function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked:
|
|
|
66
59
|
},
|
|
67
60
|
barCategoryGap: L ? "24%" : "28%",
|
|
68
61
|
children: [
|
|
69
|
-
O ? /* @__PURE__ */
|
|
62
|
+
O ? /* @__PURE__ */ u(m, {
|
|
70
63
|
vertical: !L,
|
|
71
64
|
horizontal: L,
|
|
72
|
-
stroke:
|
|
65
|
+
stroke: e.grid,
|
|
73
66
|
strokeWidth: 1
|
|
74
67
|
}) : null,
|
|
75
|
-
L ? /* @__PURE__ */
|
|
68
|
+
L ? /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ u(v, {
|
|
76
69
|
dataKey: x,
|
|
77
70
|
type: "category",
|
|
78
71
|
tickLine: !1,
|
|
@@ -80,20 +73,20 @@ function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked:
|
|
|
80
73
|
tick: z,
|
|
81
74
|
tickMargin: 8,
|
|
82
75
|
tickFormatter: D ? (e) => D(e) : void 0
|
|
83
|
-
}), /* @__PURE__ */
|
|
76
|
+
}), /* @__PURE__ */ u(y, {
|
|
84
77
|
type: "number",
|
|
85
78
|
tickLine: !1,
|
|
86
79
|
axisLine: !1,
|
|
87
80
|
tick: z,
|
|
88
81
|
width: 48,
|
|
89
82
|
tickFormatter: (e) => E(Number(e))
|
|
90
|
-
})] }) : /* @__PURE__ */
|
|
83
|
+
})] }) : /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ u(v, {
|
|
91
84
|
type: "number",
|
|
92
85
|
tickLine: !1,
|
|
93
86
|
axisLine: !1,
|
|
94
87
|
tick: z,
|
|
95
88
|
tickFormatter: (e) => E(Number(e))
|
|
96
|
-
}), /* @__PURE__ */
|
|
89
|
+
}), /* @__PURE__ */ u(y, {
|
|
97
90
|
dataKey: x,
|
|
98
91
|
type: "category",
|
|
99
92
|
tickLine: !1,
|
|
@@ -102,18 +95,18 @@ function b({ data: b, xKey: x, series: S, orientation: C = "vertical", stacked:
|
|
|
102
95
|
width: A,
|
|
103
96
|
tickFormatter: D ? (e) => D(e) : void 0
|
|
104
97
|
})] }),
|
|
105
|
-
/* @__PURE__ */
|
|
98
|
+
/* @__PURE__ */ u(_, {
|
|
106
99
|
cursor: {
|
|
107
|
-
fill:
|
|
100
|
+
fill: e.track,
|
|
108
101
|
opacity: .5
|
|
109
102
|
},
|
|
110
|
-
content: /* @__PURE__ */
|
|
103
|
+
content: /* @__PURE__ */ u(c, {
|
|
111
104
|
valueFormat: E,
|
|
112
105
|
labelFormat: D
|
|
113
106
|
})
|
|
114
107
|
}),
|
|
115
|
-
R ? /* @__PURE__ */
|
|
116
|
-
F.map((e, t) => /* @__PURE__ */
|
|
108
|
+
R ? /* @__PURE__ */ u(h, { content: /* @__PURE__ */ u(s, {}) }) : null,
|
|
109
|
+
F.map((e, t) => /* @__PURE__ */ u(f, {
|
|
117
110
|
dataKey: e.key,
|
|
118
111
|
name: e.label,
|
|
119
112
|
fill: e.color,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BarsChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/BarsChart.tsx"],"sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\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 BarsChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the category label. */\n xKey: string;\n /** One or more numeric series. */\n series: ChartSeries[];\n /** `vertical` = columns growing up (default); `horizontal` = bars growing right. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Stack the series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Pixel height. Default 260. */\n height?: number;\n /** Formats numeric values in the axis + tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats the category tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the value-axis grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Width of the category label column in `horizontal` mode. Default 96. */\n categoryWidth?: number;\n /** Message shown when `data` is empty. */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BarsChart — categorical magnitude as columns or horizontal bars, grouped or\n * stacked. Thin (≤ 24px) marks with 4px rounded data-ends, a hairline grid, a\n * per-mark tooltip, a multi-series legend, an empty state and a screen-reader\n * table. Colour is identity only (never re-encoding the bar's length).\n */\nexport function BarsChart({\n data,\n xKey,\n series,\n orientation = \"vertical\",\n stacked = false,\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n categoryWidth = 96,\n emptyLabel,\n ariaLabel,\n className,\n}: BarsChartProps) {\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 ?? `${resolved.map((s) => s.label).join(\", \")} by ${xKey}`;\n\n if (data.length === 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const isColumns = orientation === \"vertical\";\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n const lastIndex = resolved.length - 1;\n\n /** Rounded data-end: columns round the top, horizontal bars the right; a stack\n * rounds only its outermost (last) segment. */\n const radiusFor = (index: number): [number, number, number, number] => {\n const rounded = !stacked || index === lastIndex;\n if (!rounded) return [0, 0, 0, 0];\n return isColumns ? [4, 4, 0, 0] : [0, 4, 4, 0];\n };\n\n const stackId = stacked ? \"stack\" : undefined;\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 <BarChart\n data={data}\n layout={isColumns ? \"horizontal\" : \"vertical\"}\n margin={{ top: 8, right: 16, bottom: 4, left: 4 }}\n barCategoryGap={isColumns ? \"24%\" : \"28%\"}\n >\n {showGrid ? (\n <CartesianGrid\n vertical={!isColumns}\n horizontal={isColumns}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n {isColumns ? (\n <>\n <XAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n <YAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n </>\n ) : (\n <>\n <XAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n <YAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={categoryWidth}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n </>\n )}\n\n <Tooltip\n cursor={{ fill: chartTokens.track, opacity: 0.5 }}\n content={\n <ChartTooltip\n valueFormat={valueFormat}\n labelFormat={xTickFormat}\n />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) => (\n <Bar\n key={s.key}\n dataKey={s.key}\n name={s.label}\n fill={s.color}\n stackId={stackId}\n maxBarSize={24}\n radius={radiusFor(index)}\n isAnimationActive={!reducedMotion}\n />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"BarsChart.js","names":[],"sources":["../../../../src/timecampus/components/charts/BarsChart.tsx"],"sourcesContent":["import {\n Bar,\n BarChart,\n CartesianGrid,\n Legend,\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 BarsChartProps {\n /** Rows of `{ [xKey]: label, [series.key]: number }`. */\n data: ChartDatum[];\n /** Field holding the category label. */\n xKey: string;\n /** One or more numeric series. */\n series: ChartSeries[];\n /** `vertical` = columns growing up (default); `horizontal` = bars growing right. */\n orientation?: \"vertical\" | \"horizontal\";\n /** Stack the series instead of grouping side-by-side. Default false. */\n stacked?: boolean;\n /** Pixel height. Default 260. */\n height?: number;\n /** Formats numeric values in the axis + tooltip. Default grouped integer. */\n valueFormat?: ValueFormatter;\n /** Formats the category tick + tooltip header. */\n xTickFormat?: (value: string | number) => string;\n /** Show the value-axis grid. Default true. */\n showGrid?: boolean;\n /** Force the legend on/off. Default: on when there are ≥ 2 series. */\n showLegend?: boolean;\n /** Width of the category label column in `horizontal` mode. Default 96. */\n categoryWidth?: number;\n /** Message shown when `data` is empty. */\n emptyLabel?: string;\n /** Accessible name. */\n ariaLabel?: string;\n className?: string;\n}\n\n/**\n * BarsChart — categorical magnitude as columns or horizontal bars, grouped or\n * stacked. Thin (≤ 24px) marks with 4px rounded data-ends, a hairline grid, a\n * per-mark tooltip, a multi-series legend, an empty state and a screen-reader\n * table. Colour is identity only (never re-encoding the bar's length).\n */\nexport function BarsChart({\n data,\n xKey,\n series,\n orientation = \"vertical\",\n stacked = false,\n height = 260,\n valueFormat = formatNumber,\n xTickFormat,\n showGrid = true,\n showLegend,\n categoryWidth = 96,\n emptyLabel,\n ariaLabel,\n className,\n}: BarsChartProps) {\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 ?? `${resolved.map((s) => s.label).join(\", \")} by ${xKey}`;\n\n if (data.length === 0) {\n return (\n <ChartEmpty height={height} label={emptyLabel} className={className} />\n );\n }\n\n const isColumns = orientation === \"vertical\";\n const withLegend = showLegend ?? resolved.length > 1;\n const axisTick = { fill: chartTokens.textMuted, fontSize: 12 };\n const lastIndex = resolved.length - 1;\n\n /** Rounded data-end: columns round the top, horizontal bars the right; a stack\n * rounds only its outermost (last) segment. */\n const radiusFor = (index: number): [number, number, number, number] => {\n const rounded = !stacked || index === lastIndex;\n if (!rounded) return [0, 0, 0, 0];\n return isColumns ? [4, 4, 0, 0] : [0, 4, 4, 0];\n };\n\n const stackId = stacked ? \"stack\" : undefined;\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 <BarChart\n data={data}\n layout={isColumns ? \"horizontal\" : \"vertical\"}\n margin={{ top: 8, right: 16, bottom: 4, left: 4 }}\n barCategoryGap={isColumns ? \"24%\" : \"28%\"}\n >\n {showGrid ? (\n <CartesianGrid\n vertical={!isColumns}\n horizontal={isColumns}\n stroke={chartTokens.grid}\n strokeWidth={1}\n />\n ) : null}\n\n {isColumns ? (\n <>\n <XAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickMargin={8}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n <YAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={48}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n </>\n ) : (\n <>\n <XAxis\n type=\"number\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n tickFormatter={(value) => valueFormat(Number(value))}\n />\n <YAxis\n dataKey={xKey}\n type=\"category\"\n tickLine={false}\n axisLine={false}\n tick={axisTick}\n width={categoryWidth}\n tickFormatter={\n xTickFormat\n ? (value) => xTickFormat(value as string | number)\n : undefined\n }\n />\n </>\n )}\n\n <Tooltip\n cursor={{ fill: chartTokens.track, opacity: 0.5 }}\n content={\n <ChartTooltip\n valueFormat={valueFormat}\n labelFormat={xTickFormat}\n />\n }\n />\n\n {withLegend ? <Legend content={<ChartLegend />} /> : null}\n\n {resolved.map((s, index) => (\n <Bar\n key={s.key}\n dataKey={s.key}\n name={s.label}\n fill={s.color}\n stackId={stackId}\n maxBarSize={24}\n radius={radiusFor(index)}\n isAnimationActive={!reducedMotion}\n />\n ))}\n </BarChart>\n </ResponsiveContainer>\n </ChartFigure>\n );\n}\n"],"mappings":";;;;;AA+DA,SAAgB,EAAU,EACxB,SACA,SACA,WACA,iBAAc,YACd,aAAU,IACV,YAAS,KACT,iBAAc,GACd,gBACA,cAAW,IACX,eACA,mBAAgB,IAChB,eACA,cACA,gBACiB;CACjB,IAAM,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,GAAG,EAAS,KAAK,MAAM,EAAE,MAAM,CAAC,KAAK,KAAK,CAAC,MAAM;AAEhE,KAAI,EAAK,WAAW,EAClB,QACE,kBAAC,GAAD;EAAoB;EAAQ,OAAO;EAAuB;EAAa,CAAA;CAI3E,IAAM,IAAY,MAAgB,YAC5B,IAAa,KAAc,EAAS,SAAS,GAC7C,IAAW;EAAE,MAAM,EAAY;EAAW,UAAU;EAAI,EACxD,IAAY,EAAS,SAAS,GAI9B,KAAa,MACD,CAAC,KAAW,MAAU,IAE/B,IAAY;EAAC;EAAG;EAAG;EAAG;EAAE,GAAG;EAAC;EAAG;EAAG;EAAG;EAAE,GADzB;EAAC;EAAG;EAAG;EAAG;EAAE,EAI7B,IAAU,IAAU,UAAU,KAAA;AAEpC,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,kBAAC,GAAD;IACQ;IACN,QAAQ,IAAY,eAAe;IACnC,QAAQ;KAAE,KAAK;KAAG,OAAO;KAAI,QAAQ;KAAG,MAAM;KAAG;IACjD,gBAAgB,IAAY,QAAQ;cAJtC;KAMG,IACC,kBAAC,GAAD;MACE,UAAU,CAAC;MACX,YAAY;MACZ,QAAQ,EAAY;MACpB,aAAa;MACb,CAAA,GACA;KAEH,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,SAAS;MACT,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,YAAY;MACZ,eACE,KACK,MAAU,EAAY,EAAyB,GAChD,KAAA;MAEN,CAAA,EACF,kBAAC,GAAD;MACE,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,OAAO;MACP,gBAAgB,MAAU,EAAY,OAAO,EAAM,CAAC;MACpD,CAAA,CACD,EAAA,CAAA,GAEH,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;MACE,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,gBAAgB,MAAU,EAAY,OAAO,EAAM,CAAC;MACpD,CAAA,EACF,kBAAC,GAAD;MACE,SAAS;MACT,MAAK;MACL,UAAU;MACV,UAAU;MACV,MAAM;MACN,OAAO;MACP,eACE,KACK,MAAU,EAAY,EAAyB,GAChD,KAAA;MAEN,CAAA,CACD,EAAA,CAAA;KAGL,kBAAC,GAAD;MACE,QAAQ;OAAE,MAAM,EAAY;OAAO,SAAS;OAAK;MACjD,SACE,kBAAC,GAAD;OACe;OACb,aAAa;OACb,CAAA;MAEJ,CAAA;KAED,IAAa,kBAAC,GAAD,EAAQ,SAAS,kBAAC,GAAD,EAAe,CAAA,EAAI,CAAA,GAAG;KAEpD,EAAS,KAAK,GAAG,MAChB,kBAAC,GAAD;MAEE,SAAS,EAAE;MACX,MAAM,EAAE;MACR,MAAM,EAAE;MACC;MACT,YAAY;MACZ,QAAQ,EAAU,EAAM;MACxB,mBAAmB,CAAC;MACpB,EARK,EAAE,IAQP,CACF;KACO;;GACS,CAAA;EACV,CAAA"}
|
|
@@ -1,42 +1,38 @@
|
|
|
1
1
|
import { cn as e } from "../../utils/helpers.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { Pie as
|
|
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 =
|
|
12
|
-
let E =
|
|
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 ??
|
|
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__ */
|
|
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) :
|
|
22
|
-
return /* @__PURE__ */
|
|
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__ */
|
|
23
|
+
/* @__PURE__ */ u("div", {
|
|
28
24
|
className: "relative mx-auto",
|
|
29
25
|
style: { height: y },
|
|
30
|
-
children: [/* @__PURE__ */ m
|
|
26
|
+
children: [/* @__PURE__ */ l(m, {
|
|
31
27
|
width: "100%",
|
|
32
28
|
height: "100%",
|
|
33
|
-
children: /* @__PURE__ */
|
|
29
|
+
children: /* @__PURE__ */ u(p, { children: [/* @__PURE__ */ l(h, {
|
|
34
30
|
cursor: !1,
|
|
35
|
-
content: /* @__PURE__ */
|
|
31
|
+
content: /* @__PURE__ */ l(s, {
|
|
36
32
|
valueFormat: x,
|
|
37
33
|
hideLabel: !0
|
|
38
34
|
})
|
|
39
|
-
}), /* @__PURE__ */
|
|
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:
|
|
44
|
+
stroke: t.surface,
|
|
49
45
|
strokeWidth: 2,
|
|
50
46
|
isAnimationActive: !E,
|
|
51
|
-
children: D.map((e) => /* @__PURE__ */
|
|
47
|
+
children: D.map((e) => /* @__PURE__ */ l(d, { fill: e.color }, e.name))
|
|
52
48
|
})] })
|
|
53
|
-
}), j ? /* @__PURE__ */
|
|
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__ */
|
|
51
|
+
children: [/* @__PURE__ */ l("span", {
|
|
56
52
|
className: "text-2xl font-bold text-text-primary",
|
|
57
53
|
children: M
|
|
58
|
-
}), _ ? /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
75
|
-
/* @__PURE__ */
|
|
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__ */
|
|
83
|
-
style:
|
|
78
|
+
/* @__PURE__ */ u("table", {
|
|
79
|
+
style: c,
|
|
84
80
|
children: [
|
|
85
|
-
/* @__PURE__ */
|
|
86
|
-
/* @__PURE__ */
|
|
87
|
-
/* @__PURE__ */
|
|
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__ */
|
|
87
|
+
/* @__PURE__ */ l("th", {
|
|
92
88
|
scope: "col",
|
|
93
89
|
children: "Value"
|
|
94
90
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
91
|
+
/* @__PURE__ */ l("th", {
|
|
96
92
|
scope: "col",
|
|
97
93
|
children: "Share"
|
|
98
94
|
})
|
|
99
95
|
] }) }),
|
|
100
|
-
/* @__PURE__ */
|
|
101
|
-
/* @__PURE__ */
|
|
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__ */
|
|
106
|
-
/* @__PURE__ */
|
|
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":"
|
|
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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"}
|