@nextelco/common-ui 2.1.105 → 2.1.107
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/esm/index.js +201 -145
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/legacy/components/atoms/InputData/InputData.js +2 -13
- package/dist/esm/legacy/components/atoms/InputData/InputData.js.map +1 -1
- package/dist/esm/legacy/components/charts/Charts.js +147 -57
- package/dist/esm/legacy/components/charts/Charts.js.map +1 -1
- package/dist/esm/legacy/components/layout/Layout/Layout.js +21 -82
- package/dist/esm/legacy/components/layout/Layout/Layout.js.map +1 -1
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js +29 -218
- package/dist/esm/legacy/components/layout/Sidebar/Sidebar.js.map +1 -1
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js +77 -10
- package/dist/esm/legacy/components/molecules/ColumnPicker/ColumnPicker.js.map +1 -1
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js +445 -337
- package/dist/esm/legacy/components/molecules/DataTable/DataTable.js.map +1 -1
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js +15 -97
- package/dist/esm/legacy/components/molecules/UserAvatar/UserAvatar.js.map +1 -1
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js +3 -3
- package/dist/esm/legacy/components/organisms/MapaPontos/MapaPontos.js.map +1 -1
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js +15 -3
- package/dist/esm/legacy/components/organisms/PainelFiltros/PainelFiltros.js.map +1 -1
- package/dist/esm/legacy/components/organisms/Selector/Selector.js +4 -4
- package/dist/esm/legacy/components/organisms/Selector/Selector.js.map +1 -1
- package/dist/esm/legacy/components/ui/Avisos.js +23 -76
- package/dist/esm/legacy/components/ui/Avisos.js.map +1 -1
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js +14 -27
- package/dist/esm/legacy/components/ui/CabecalhoPagina.js.map +1 -1
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js +3 -51
- package/dist/esm/legacy/components/ui/CaixaPesquisa.js.map +1 -1
- package/dist/esm/legacy/components/ui/Confirmacao.js +13 -31
- package/dist/esm/legacy/components/ui/Confirmacao.js.map +1 -1
- package/dist/esm/legacy/components/ui/Escolha.js +21 -137
- package/dist/esm/legacy/components/ui/Escolha.js.map +1 -1
- package/dist/esm/legacy/components/ui/FaixaAviso.js +13 -11
- package/dist/esm/legacy/components/ui/FaixaAviso.js.map +1 -1
- package/dist/esm/legacy/components/ui/Separadores.js +11 -46
- package/dist/esm/legacy/components/ui/Separadores.js.map +1 -1
- package/dist/esm/legacy/components/ui/Ui.js +18 -115
- package/dist/esm/legacy/components/ui/Ui.js.map +1 -1
- package/dist/esm/legacy/components/ui/painelFlutuante.js +5 -44
- package/dist/esm/legacy/components/ui/painelFlutuante.js.map +1 -1
- package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js +52 -0
- package/dist/esm/v1/capabilities/overlay/useFloatingPanel.js.map +1 -0
- package/dist/esm/v1/capabilities/theme/useIsDark.js +15 -0
- package/dist/esm/v1/capabilities/theme/useIsDark.js.map +1 -0
- package/dist/esm/v1/capabilities/theme/useTheme.js +66 -0
- package/dist/esm/v1/capabilities/theme/useTheme.js.map +1 -0
- package/dist/esm/v1/components/data/Pagination/Pagination.js +66 -0
- package/dist/esm/v1/components/data/Pagination/Pagination.js.map +1 -0
- package/dist/esm/v1/components/feedback/Toast/Toast.js +105 -0
- package/dist/esm/v1/components/feedback/Toast/Toast.js.map +1 -0
- package/dist/esm/v1/components/forms/FormField/FormField.js.map +1 -1
- package/dist/esm/v1/components/forms/FormGrid/FormGrid.js.map +1 -1
- package/dist/esm/v1/components/layout/AppShell/AppShell.js +89 -0
- package/dist/esm/v1/components/layout/AppShell/AppShell.js.map +1 -0
- package/dist/esm/v1/components/layout/Page/Page.js +16 -0
- package/dist/esm/v1/components/layout/Page/Page.js.map +1 -0
- package/dist/esm/v1/components/layout/PageHeader/PageHeader.js +26 -0
- package/dist/esm/v1/components/layout/PageHeader/PageHeader.js.map +1 -0
- package/dist/esm/v1/components/layout/SideNav/SideNav.js +277 -0
- package/dist/esm/v1/components/layout/SideNav/SideNav.js.map +1 -0
- package/dist/esm/v1/components/layout/navTrail.js +19 -0
- package/dist/esm/v1/components/layout/navTrail.js.map +1 -0
- package/dist/esm/v1/components/lists/ListFinder/ListFinder.js +4 -4
- package/dist/esm/v1/components/lists/ListFinder/ListFinder.js.map +1 -1
- package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js +95 -0
- package/dist/esm/v1/components/overlays/ConfirmDialog/ConfirmDialog.js.map +1 -0
- package/dist/esm/v1/components/overlays/Dialog/Dialog.js.map +1 -1
- package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js +98 -0
- package/dist/esm/v1/components/overlays/Tooltip/Tooltip.js.map +1 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js +84 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipLayer.js.map +1 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js +33 -0
- package/dist/esm/v1/components/overlays/Tooltip/TooltipPanel.js.map +1 -0
- package/dist/esm/v1/components/overlays/topLayer.js +28 -0
- package/dist/esm/v1/components/overlays/topLayer.js.map +1 -0
- package/dist/esm/v1/components/tables/PaginatedTable/PaginatedTable.js.map +1 -1
- package/dist/esm/v1/components/tables/Table/Table.js.map +1 -1
- package/dist/esm/v1/foundations/icons/icons.js +61 -2
- package/dist/esm/v1/foundations/icons/icons.js.map +1 -1
- package/dist/esm/v1/primitives/buttons/Button/Button.js +18 -4
- package/dist/esm/v1/primitives/buttons/Button/Button.js.map +1 -1
- package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js +65 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/SegmentedControl.js.map +1 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js +10 -0
- package/dist/esm/v1/primitives/buttons/SegmentedControl/segmentedStyles.js.map +1 -0
- package/dist/esm/v1/primitives/display/Avatar/Avatar.js +120 -0
- package/dist/esm/v1/primitives/display/Avatar/Avatar.js.map +1 -0
- package/dist/esm/v1/primitives/display/Badge/Badge.js +23 -0
- package/dist/esm/v1/primitives/display/Badge/Badge.js.map +1 -0
- package/dist/esm/v1/primitives/display/Card/Card.js +22 -0
- package/dist/esm/v1/primitives/display/Card/Card.js.map +1 -0
- package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js +45 -0
- package/dist/esm/v1/primitives/display/FilterChips/FilterChips.js.map +1 -0
- package/dist/esm/v1/primitives/display/Kpi/Kpi.js +103 -0
- package/dist/esm/v1/primitives/display/Kpi/Kpi.js.map +1 -0
- package/dist/esm/v1/primitives/display/Notice/Notice.js +71 -0
- package/dist/esm/v1/primitives/display/Notice/Notice.js.map +1 -0
- package/dist/esm/v1/primitives/display/Person/Person.js +14 -0
- package/dist/esm/v1/primitives/display/Person/Person.js.map +1 -0
- package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js +10 -5
- package/dist/esm/v1/primitives/forms/Checkbox/Checkbox.js.map +1 -1
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js +150 -0
- package/dist/esm/v1/primitives/forms/DateInput/DateInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/LookupInput/LookupInput.js.map +1 -1
- package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js +43 -0
- package/dist/esm/v1/primitives/forms/SearchInput/SearchInput.js.map +1 -0
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js +190 -12
- package/dist/esm/v1/primitives/forms/SelectInput/SelectInput.js.map +1 -1
- package/dist/esm/v1/primitives/forms/TextArea/TextArea.js.map +1 -1
- package/dist/esm/v1/primitives/forms/field.js +4 -2
- package/dist/esm/v1/primitives/forms/field.js.map +1 -1
- package/dist/esm/v1/primitives/lists/ListItem/ListItem.js +2 -2
- package/dist/esm/v1/primitives/lists/ListItem/ListItem.js.map +1 -1
- package/dist/esm/v1/primitives/navigation/Tabs/Tabs.js +96 -0
- package/dist/esm/v1/primitives/navigation/Tabs/Tabs.js.map +1 -0
- package/dist/style.components.css +1 -1
- package/dist/style.css +1 -1
- package/dist/style.layered.css +1 -1
- package/dist/tailwind.css +24 -0
- package/dist/theme-boot.js +1 -0
- package/dist/theme.css +10 -3
- package/dist/tokens.css +119 -0
- package/dist/types/legacy/components/atoms/InputData/InputData.d.ts +4 -1
- package/dist/types/legacy/components/charts/Charts.d.ts +58 -5
- package/dist/types/legacy/components/layout/Layout/Layout.d.ts +7 -20
- package/dist/types/legacy/components/layout/Sidebar/Sidebar.d.ts +13 -26
- package/dist/types/legacy/components/molecules/ColumnPicker/ColumnPicker.d.ts +56 -3
- package/dist/types/legacy/components/molecules/DataTable/DataTable.d.ts +72 -7
- package/dist/types/legacy/components/molecules/UserAvatar/UserAvatar.d.ts +4 -5
- package/dist/types/legacy/components/ui/Avisos.d.ts +6 -16
- package/dist/types/legacy/components/ui/CabecalhoPagina.d.ts +6 -20
- package/dist/types/legacy/components/ui/CaixaPesquisa.d.ts +2 -4
- package/dist/types/legacy/components/ui/Confirmacao.d.ts +3 -10
- package/dist/types/legacy/components/ui/Escolha.d.ts +5 -15
- package/dist/types/legacy/components/ui/FaixaAviso.d.ts +2 -6
- package/dist/types/legacy/components/ui/Separadores.d.ts +3 -10
- package/dist/types/legacy/components/ui/Ui.d.ts +12 -54
- package/dist/types/legacy/components/ui/painelFlutuante.d.ts +6 -10
- package/dist/types/legacy/exports/atoms.d.ts +1 -1
- package/dist/types/legacy/exports/charts.d.ts +2 -2
- package/dist/types/legacy/exports/hooks.d.ts +2 -2
- package/dist/types/legacy/exports/molecules.d.ts +2 -2
- package/dist/types/v1/capabilities/overlay/useFloatingPanel.d.ts +20 -0
- package/dist/types/v1/capabilities/theme/useIsDark.d.ts +10 -0
- package/dist/types/v1/capabilities/theme/useTheme.d.ts +29 -0
- package/dist/types/v1/components/data/Pagination/Pagination.d.ts +33 -0
- package/dist/types/v1/components/feedback/Toast/Toast.d.ts +51 -0
- package/dist/types/v1/components/forms/FormField/FormField.d.ts +3 -3
- package/dist/types/v1/components/forms/FormGrid/FormGrid.d.ts +2 -0
- package/dist/types/v1/components/layout/AppShell/AppShell.d.ts +35 -0
- package/dist/types/v1/components/layout/Page/Page.d.ts +23 -0
- package/dist/types/v1/components/layout/PageHeader/PageHeader.d.ts +35 -0
- package/dist/types/v1/components/layout/SideNav/SideNav.d.ts +92 -0
- package/dist/types/v1/components/layout/navTrail.d.ts +15 -0
- package/dist/types/v1/components/lists/ListFinder/ListFinder.d.ts +1 -1
- package/dist/types/v1/components/overlays/ConfirmDialog/ConfirmDialog.d.ts +59 -0
- package/dist/types/v1/components/overlays/Dialog/Dialog.d.ts +6 -3
- package/dist/types/v1/components/overlays/Tooltip/Tooltip.d.ts +34 -0
- package/dist/types/v1/components/overlays/Tooltip/TooltipLayer.d.ts +18 -0
- package/dist/types/v1/components/overlays/Tooltip/TooltipPanel.d.ts +23 -0
- package/dist/types/v1/components/overlays/topLayer.d.ts +23 -0
- package/dist/types/v1/components/tables/PaginatedTable/PaginatedTable.d.ts +1 -1
- package/dist/types/v1/components/tables/Table/Table.d.ts +1 -1
- package/dist/types/v1/foundations/icons/icons.d.ts +20 -0
- package/dist/types/v1/index.d.ts +43 -1
- package/dist/types/v1/primitives/buttons/Button/Button.d.ts +22 -5
- package/dist/types/v1/primitives/buttons/SegmentedControl/SegmentedControl.d.ts +28 -0
- package/dist/types/v1/primitives/buttons/SegmentedControl/segmentedStyles.d.ts +16 -0
- package/dist/types/v1/primitives/display/Avatar/Avatar.d.ts +30 -0
- package/dist/types/v1/primitives/display/Badge/Badge.d.ts +25 -0
- package/dist/types/v1/primitives/display/Card/Card.d.ts +22 -0
- package/dist/types/v1/primitives/display/FilterChips/FilterChips.d.ts +33 -0
- package/dist/types/v1/primitives/display/Kpi/Kpi.d.ts +68 -0
- package/dist/types/v1/primitives/display/Notice/Notice.d.ts +29 -0
- package/dist/types/v1/primitives/display/Person/Person.d.ts +15 -0
- package/dist/types/v1/primitives/forms/Checkbox/Checkbox.d.ts +7 -0
- package/dist/types/v1/primitives/forms/DateInput/DateInput.d.ts +43 -0
- package/dist/types/v1/primitives/forms/LookupInput/LookupInput.d.ts +3 -0
- package/dist/types/v1/primitives/forms/SearchInput/SearchInput.d.ts +23 -0
- package/dist/types/v1/primitives/forms/SelectInput/SelectInput.d.ts +61 -10
- package/dist/types/v1/primitives/forms/TextArea/TextArea.d.ts +3 -0
- package/dist/types/v1/primitives/forms/field.d.ts +2 -0
- package/dist/types/v1/primitives/lists/ListItem/ListItem.d.ts +2 -1
- package/dist/types/v1/primitives/navigation/Tabs/Tabs.d.ts +58 -0
- package/package.json +3 -3
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.css +0 -17
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js +0 -41
- package/dist/esm/legacy/components/atoms/Tooltip/Tooltip.js.map +0 -1
- package/dist/esm/legacy/components/molecules/Search/Search.css +0 -18
- package/dist/esm/legacy/components/molecules/Search/Search.js +0 -30
- package/dist/esm/legacy/components/molecules/Search/Search.js.map +0 -1
- package/dist/esm/legacy/hooks/useTheme.js +0 -39
- package/dist/esm/legacy/hooks/useTheme.js.map +0 -1
- package/dist/esm/v1/primitives/lists/ListItem/ListCheckbox.js +0 -28
- package/dist/esm/v1/primitives/lists/ListItem/ListCheckbox.js.map +0 -1
- package/dist/types/legacy/components/atoms/Tooltip/Tooltip.d.ts +0 -13
- package/dist/types/legacy/components/molecules/Search/Search.d.ts +0 -7
- package/dist/types/legacy/hooks/useTheme.d.ts +0 -17
- package/dist/types/v1/primitives/lists/ListItem/ListCheckbox.d.ts +0 -14
|
@@ -2,6 +2,7 @@ import { jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { Chart, registerables } from "chart.js";
|
|
3
3
|
import ChartDataLabels from "chartjs-plugin-datalabels";
|
|
4
4
|
import { Doughnut, Bar, Bubble, Line } from "react-chartjs-2";
|
|
5
|
+
import { useIsDark } from "../../../v1/capabilities/theme/useIsDark.js";
|
|
5
6
|
function euros(v) {
|
|
6
7
|
if (v == null) return "—";
|
|
7
8
|
const negativo = v < 0;
|
|
@@ -36,63 +37,122 @@ const PALETA = [
|
|
|
36
37
|
function cor(i) {
|
|
37
38
|
return PALETA[i % PALETA.length];
|
|
38
39
|
}
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
function
|
|
44
|
-
return
|
|
40
|
+
function useTema() {
|
|
41
|
+
const escuro = useIsDark();
|
|
42
|
+
return escuro ? { texto: "#CBD5E1", forte: "#E2E8F0", grelha: "#1E293B" } : { texto: "#5B6577", forte: "#182238", grelha: "#EEF1F5" };
|
|
43
|
+
}
|
|
44
|
+
function legendaBaixo(tema) {
|
|
45
|
+
return {
|
|
46
|
+
position: "bottom",
|
|
47
|
+
labels: { boxWidth: 10, font: { size: 11 }, color: tema.forte, usePointStyle: true, pointStyle: "circle" }
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function clique(labels, series, onClick) {
|
|
51
|
+
if (!onClick) return {};
|
|
52
|
+
return {
|
|
53
|
+
onClick: (_e, els) => {
|
|
54
|
+
const el = els[0];
|
|
55
|
+
if (!el) return;
|
|
56
|
+
onClick(labels[el.index], el.index, series?.[el.datasetIndex]?.nome);
|
|
57
|
+
},
|
|
58
|
+
onHover: (e, els) => {
|
|
59
|
+
const alvo = e.native?.target;
|
|
60
|
+
if (alvo) alvo.style.cursor = els.length ? "pointer" : "default";
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function Barras({
|
|
65
|
+
labels: todas,
|
|
66
|
+
series: todasSeries,
|
|
67
|
+
horizontal = false,
|
|
68
|
+
empilhado = false,
|
|
69
|
+
altura,
|
|
70
|
+
limite,
|
|
71
|
+
cores,
|
|
72
|
+
formatar = (v) => String(v),
|
|
73
|
+
valores = true,
|
|
74
|
+
percentagem = false,
|
|
75
|
+
legenda,
|
|
76
|
+
formatarEtiqueta = labelBucket,
|
|
77
|
+
onClick
|
|
78
|
+
}) {
|
|
79
|
+
const tema = useTema();
|
|
80
|
+
const labels = limite ? todas.slice(0, limite) : todas;
|
|
81
|
+
const series = todasSeries.map((s) => ({ ...s, valores: limite ? s.valores.slice(0, limite) : s.valores }));
|
|
82
|
+
const uma = series.length === 1;
|
|
83
|
+
const total = uma ? todasSeries[0].valores.reduce((a, b) => a + (b || 0), 0) : 0;
|
|
84
|
+
const etiqueta = (v) => percentagem && uma && total > 0 ? `${formatar(v)} (${Math.round(v / total * 100)}%)` : formatar(v);
|
|
85
|
+
const alturaFinal = altura ?? (horizontal ? Math.max(200, labels.length * 30 + 40) : 260);
|
|
86
|
+
const eixoValor = { beginAtZero: true, stacked: empilhado, grid: { color: tema.grelha }, ticks: { color: tema.texto, callback: (v) => formatar(Number(v)) } };
|
|
87
|
+
const eixoEtiqueta = { stacked: empilhado, grid: { display: false }, ticks: { color: tema.texto } };
|
|
88
|
+
return /* @__PURE__ */ jsx("div", { style: { height: alturaFinal }, children: /* @__PURE__ */ jsx(
|
|
45
89
|
Bar,
|
|
46
90
|
{
|
|
47
91
|
data: {
|
|
48
|
-
labels:
|
|
49
|
-
datasets:
|
|
92
|
+
labels: labels.map(formatarEtiqueta),
|
|
93
|
+
datasets: series.map((s, i) => ({
|
|
50
94
|
label: s.nome,
|
|
51
95
|
data: s.valores,
|
|
52
|
-
backgroundColor: cor(i),
|
|
53
|
-
borderRadius:
|
|
96
|
+
backgroundColor: uma && cores ? labels.map((_, j) => cores[j % cores.length]) : s.cor ?? cor(i),
|
|
97
|
+
borderRadius: 4,
|
|
98
|
+
maxBarThickness: 40
|
|
54
99
|
}))
|
|
55
100
|
},
|
|
56
101
|
options: {
|
|
102
|
+
indexAxis: horizontal ? "y" : "x",
|
|
57
103
|
maintainAspectRatio: false,
|
|
58
104
|
responsive: true,
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
105
|
+
...clique(labels, series, onClick),
|
|
106
|
+
plugins: {
|
|
107
|
+
legend: legenda ?? !uma ? legendaBaixo(tema) : { display: false },
|
|
108
|
+
tooltip: { callbacks: { label: (c) => `${c.dataset.label ? `${c.dataset.label}: ` : ""}${etiqueta(Number(c.parsed[horizontal ? "x" : "y"]))}` } },
|
|
109
|
+
datalabels: {
|
|
110
|
+
display: (c) => valores && !empilhado && Number(c.dataset.data[c.dataIndex]) > 0,
|
|
111
|
+
anchor: "end",
|
|
112
|
+
align: "end",
|
|
113
|
+
color: tema.forte,
|
|
114
|
+
font: { size: 10, weight: 600 },
|
|
115
|
+
formatter: (v) => etiqueta(v)
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
scales: horizontal ? { x: eixoValor, y: eixoEtiqueta } : { x: eixoEtiqueta, y: eixoValor },
|
|
119
|
+
layout: { padding: horizontal ? { right: valores ? percentagem ? 56 : 32 : 8 } : { top: valores ? 18 : 4 } }
|
|
64
120
|
}
|
|
65
121
|
}
|
|
66
122
|
) });
|
|
67
123
|
}
|
|
68
|
-
function
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
124
|
+
function BarrasEmpilhadas({ serie, altura = 280, onClick }) {
|
|
125
|
+
return /* @__PURE__ */ jsx(Barras, { labels: serie.labels, series: serie.series, empilhado: true, altura, onClick, legenda: true });
|
|
126
|
+
}
|
|
127
|
+
function BarrasHorizontais({
|
|
128
|
+
dados,
|
|
129
|
+
altura = 280,
|
|
130
|
+
limite = 12,
|
|
131
|
+
onClick
|
|
132
|
+
}) {
|
|
133
|
+
const n = Math.min(limite, dados.labels.length);
|
|
134
|
+
return /* @__PURE__ */ jsx(
|
|
135
|
+
Barras,
|
|
73
136
|
{
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
},
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
responsive: true,
|
|
82
|
-
plugins: {
|
|
83
|
-
legend: { display: false },
|
|
84
|
-
datalabels: { display: (c) => c.dataset.data[c.dataIndex] != null, anchor: "end", align: "end", color: "#182238", font: { size: 11, weight: 600 } }
|
|
85
|
-
},
|
|
86
|
-
scales: {
|
|
87
|
-
x: { beginAtZero: true, grid: { color: "#EEF1F5" } },
|
|
88
|
-
y: { grid: { display: false } }
|
|
89
|
-
},
|
|
90
|
-
layout: { padding: { right: 28 } }
|
|
91
|
-
}
|
|
137
|
+
horizontal: true,
|
|
138
|
+
labels: dados.labels,
|
|
139
|
+
series: [{ nome: "", valores: dados.valores }],
|
|
140
|
+
cores: Array.from({ length: n }, (_, i) => cor(i)),
|
|
141
|
+
limite,
|
|
142
|
+
altura,
|
|
143
|
+
onClick
|
|
92
144
|
}
|
|
93
|
-
)
|
|
145
|
+
);
|
|
94
146
|
}
|
|
95
|
-
function Anel({
|
|
147
|
+
function Anel({
|
|
148
|
+
dados,
|
|
149
|
+
altura = 260,
|
|
150
|
+
cores,
|
|
151
|
+
formatar = (v) => String(v),
|
|
152
|
+
onClick
|
|
153
|
+
}) {
|
|
154
|
+
const tema = useTema();
|
|
155
|
+
const total = dados.valores.reduce((a, b) => a + (b || 0), 0);
|
|
96
156
|
return /* @__PURE__ */ jsx("div", { style: { height: altura }, children: /* @__PURE__ */ jsx(
|
|
97
157
|
Doughnut,
|
|
98
158
|
{
|
|
@@ -110,19 +170,36 @@ function Anel({ dados, altura = 260, cores }) {
|
|
|
110
170
|
maintainAspectRatio: false,
|
|
111
171
|
responsive: true,
|
|
112
172
|
cutout: "58%",
|
|
173
|
+
...clique(dados.labels, void 0, onClick),
|
|
113
174
|
plugins: {
|
|
114
|
-
legend: legendaBaixo,
|
|
175
|
+
legend: legendaBaixo(tema),
|
|
176
|
+
tooltip: {
|
|
177
|
+
callbacks: {
|
|
178
|
+
label: (c) => {
|
|
179
|
+
const v = Number(c.parsed);
|
|
180
|
+
return ` ${c.label}: ${formatar(v)}${total > 0 ? ` (${Math.round(v / total * 100)}%)` : ""}`;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
},
|
|
115
184
|
datalabels: {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
185
|
+
// Só nas fatias que têm espaço para o número.
|
|
186
|
+
display: (c) => total > 0 && Number(c.dataset.data[c.dataIndex]) / total >= 0.05,
|
|
187
|
+
color: "#FFFFFF",
|
|
188
|
+
font: { size: 11, weight: 700 },
|
|
189
|
+
formatter: (v) => formatar(v)
|
|
119
190
|
}
|
|
120
191
|
}
|
|
121
192
|
}
|
|
122
193
|
}
|
|
123
194
|
) });
|
|
124
195
|
}
|
|
125
|
-
function Linha({
|
|
196
|
+
function Linha({
|
|
197
|
+
dados,
|
|
198
|
+
altura = 260,
|
|
199
|
+
euros: emEuros = false,
|
|
200
|
+
onClick
|
|
201
|
+
}) {
|
|
202
|
+
const tema = useTema();
|
|
126
203
|
return /* @__PURE__ */ jsx("div", { style: { height: altura }, children: /* @__PURE__ */ jsx(
|
|
127
204
|
Line,
|
|
128
205
|
{
|
|
@@ -143,6 +220,7 @@ function Linha({ dados, altura = 260, euros: emEuros = false }) {
|
|
|
143
220
|
options: {
|
|
144
221
|
maintainAspectRatio: false,
|
|
145
222
|
responsive: true,
|
|
223
|
+
...clique(dados.labels, void 0, onClick),
|
|
146
224
|
plugins: {
|
|
147
225
|
legend: { display: false },
|
|
148
226
|
tooltip: {
|
|
@@ -152,11 +230,11 @@ function Linha({ dados, altura = 260, euros: emEuros = false }) {
|
|
|
152
230
|
}
|
|
153
231
|
},
|
|
154
232
|
scales: {
|
|
155
|
-
x: { grid: { display: false } },
|
|
233
|
+
x: { grid: { display: false }, ticks: { color: tema.texto } },
|
|
156
234
|
y: {
|
|
157
235
|
beginAtZero: true,
|
|
158
|
-
grid: { color:
|
|
159
|
-
ticks: { callback: (v) => emEuros ? euros(Number(v)) : String(v) }
|
|
236
|
+
grid: { color: tema.grelha },
|
|
237
|
+
ticks: { color: tema.texto, callback: (v) => emEuros ? euros(Number(v)) : String(v) }
|
|
160
238
|
}
|
|
161
239
|
}
|
|
162
240
|
}
|
|
@@ -166,18 +244,24 @@ function Linha({ dados, altura = 260, euros: emEuros = false }) {
|
|
|
166
244
|
function Linhas({
|
|
167
245
|
serie,
|
|
168
246
|
altura = 280,
|
|
169
|
-
area = false
|
|
247
|
+
area = false,
|
|
248
|
+
cores,
|
|
249
|
+
formatar = (v) => String(v),
|
|
250
|
+
formatarEtiqueta = labelBucket,
|
|
251
|
+
onClick
|
|
170
252
|
}) {
|
|
253
|
+
const tema = useTema();
|
|
254
|
+
const corDe = (i) => cores?.[i] ?? cor(i);
|
|
171
255
|
return /* @__PURE__ */ jsx("div", { style: { height: altura }, children: /* @__PURE__ */ jsx(
|
|
172
256
|
Line,
|
|
173
257
|
{
|
|
174
258
|
data: {
|
|
175
|
-
labels: serie.labels.map(
|
|
259
|
+
labels: serie.labels.map(formatarEtiqueta),
|
|
176
260
|
datasets: serie.series.map((s, i) => ({
|
|
177
261
|
label: s.nome,
|
|
178
262
|
data: s.valores,
|
|
179
|
-
borderColor:
|
|
180
|
-
backgroundColor: area ? `${
|
|
263
|
+
borderColor: corDe(i),
|
|
264
|
+
backgroundColor: area ? `${corDe(i)}22` : corDe(i),
|
|
181
265
|
fill: area,
|
|
182
266
|
tension: 0.25,
|
|
183
267
|
pointRadius: serie.labels.length > 24 ? 0 : 3,
|
|
@@ -188,10 +272,14 @@ function Linhas({
|
|
|
188
272
|
maintainAspectRatio: false,
|
|
189
273
|
responsive: true,
|
|
190
274
|
interaction: { mode: "index", intersect: false },
|
|
191
|
-
|
|
275
|
+
...clique(serie.labels, serie.series, onClick),
|
|
276
|
+
plugins: {
|
|
277
|
+
legend: legendaBaixo(tema),
|
|
278
|
+
tooltip: { callbacks: { label: (c) => `${c.dataset.label}: ${formatar(Number(c.parsed.y))}` } }
|
|
279
|
+
},
|
|
192
280
|
scales: {
|
|
193
|
-
x: { grid: { display: false } },
|
|
194
|
-
y: { beginAtZero: true, grid: { color:
|
|
281
|
+
x: { grid: { display: false }, ticks: { color: tema.texto, autoSkip: true, maxRotation: 0 } },
|
|
282
|
+
y: { beginAtZero: true, grid: { color: tema.grelha }, ticks: { color: tema.texto, callback: (v) => formatar(Number(v)) } }
|
|
195
283
|
}
|
|
196
284
|
}
|
|
197
285
|
}
|
|
@@ -205,6 +293,7 @@ function Bolhas({
|
|
|
205
293
|
yTitle = "% overdue",
|
|
206
294
|
tooltipLabel = (p) => `${p.responsavel}: ${p.otsAtivas} active, ${p.percentagemForaPrazo}% overdue, ${euros(p.valorPenalizado)}`
|
|
207
295
|
}) {
|
|
296
|
+
const tema = useTema();
|
|
208
297
|
const maxValor = Math.max(1, ...pontos.map((p) => p.valorPenalizado));
|
|
209
298
|
return /* @__PURE__ */ jsx("div", { style: { height: altura }, children: /* @__PURE__ */ jsx(
|
|
210
299
|
Bubble,
|
|
@@ -239,8 +328,8 @@ function Bolhas({
|
|
|
239
328
|
}
|
|
240
329
|
},
|
|
241
330
|
scales: {
|
|
242
|
-
x: { beginAtZero: true, title: { display: true, text: xTitle }, grid: { color:
|
|
243
|
-
y: { beginAtZero: true, title: { display: true, text: yTitle }, grid: { color:
|
|
331
|
+
x: { beginAtZero: true, title: { display: true, text: xTitle, color: tema.texto }, grid: { color: tema.grelha }, ticks: { color: tema.texto } },
|
|
332
|
+
y: { beginAtZero: true, title: { display: true, text: yTitle, color: tema.texto }, grid: { color: tema.grelha }, ticks: { color: tema.texto } }
|
|
244
333
|
}
|
|
245
334
|
}
|
|
246
335
|
}
|
|
@@ -248,6 +337,7 @@ function Bolhas({
|
|
|
248
337
|
}
|
|
249
338
|
export {
|
|
250
339
|
Anel,
|
|
340
|
+
Barras,
|
|
251
341
|
BarrasEmpilhadas,
|
|
252
342
|
BarrasHorizontais,
|
|
253
343
|
Bolhas,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Charts.js","sources":["../../../../../src/legacy/components/charts/Charts.tsx"],"sourcesContent":["import React from 'react'\r\nimport { Chart as ChartJS, registerables } from 'chart.js'\r\nimport ChartDataLabels from 'chartjs-plugin-datalabels'\r\nimport { Bar, Doughnut, Line, Bubble } from 'react-chartjs-2'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Local types (inlined — originally imported from CRE `../types`).\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Stacked series over a set of shared labels (e.g. a dimension over time).\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface SerieEmpilhada {\r\n labels: string[]\r\n series: { nome: string; valores: number[] }[]\r\n}\r\n\r\n/**\r\n * A simple distribution: parallel arrays of labels and values.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface Distribuicao {\r\n labels: string[]\r\n valores: number[]\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Local formatting helpers (inlined — originally imported from CRE `../lib/format`).\r\n// Behavior kept close to the originals; the library stays self-contained.\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Currency formatter. Thousands separated by '.', decimals by ',', suffixed ' €'.\r\n * Independent of Intl/ICU so the thousands separator is stable across browsers.\r\n */\r\nfunction euros(v: number | null | undefined): string {\r\n if (v == null) return '—'\r\n const negativo = v < 0\r\n const [inteiro, decimal] = Math.abs(v).toFixed(2).split('.')\r\n const comMilhares = inteiro.replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\r\n return `${negativo ? '-' : ''}${comMilhares},${decimal} €`\r\n}\r\n\r\n/** 'YYYY-Sxx' / 'YYYY-MM' / 'YYYY-MM-DD' → short axis label. */\r\nfunction labelBucket(b: string): string {\r\n if (/^\\d{4}-S\\d{2}$/.test(b)) return `S${b.slice(6)}/${b.slice(2, 4)}`\r\n if (/^\\d{4}-\\d{2}$/.test(b)) return `${b.slice(5)}/${b.slice(0, 4)}`\r\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(b)) return `${b.slice(8)}/${b.slice(5, 7)}`\r\n return b\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Chart.js registration (once, at module load).\r\n// ---------------------------------------------------------------------------\r\n\r\n// Regista TUDO (registerables inclui Filler, controllers, scales) + o plugin de\r\n// datalabels. O registo parcial degenerava a geometria (doughnut colapsado) e o\r\n// aviso \"fill sem Filler\". registerables = equivalente a chart.js/auto.\r\nChartJS.register(...registerables, ChartDataLabels)\r\n// Datalabels off by default — enabled only where it improves readability.\r\nChartJS.defaults.set('plugins.datalabels', { display: false })\r\nChartJS.defaults.font.family = \"'Montserrat', sans-serif\"\r\nChartJS.defaults.color = '#5B6577'\r\n\r\n/**\r\n * Categorical palette. Stable order so the same dimension always maps to the same color.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport const PALETA = [\r\n '#1868B0',\r\n '#1F8A55',\r\n '#B96E00',\r\n '#C23B34',\r\n '#7C3AED',\r\n '#0891B2',\r\n '#DB2777',\r\n '#65A30D',\r\n '#4B5563',\r\n '#D97706',\r\n '#2563EB',\r\n '#059669',\r\n]\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport function cor(i: number): string {\r\n return PALETA[i % PALETA.length]!\r\n}\r\n\r\nconst legendaBaixo = {\r\n position: 'bottom' as const,\r\n labels: { boxWidth: 10, font: { size: 11 }, color: '#182238', usePointStyle: true, pointStyle: 'circle' as const },\r\n}\r\n\r\n/**\r\n * Stacked bars for a dimension over time.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function BarrasEmpilhadas({ serie, altura = 280 }: { serie: SerieEmpilhada; altura?: number }) {\r\n return (\r\n <div style={{ height: altura }}>\r\n <Bar\r\n data={{\r\n labels: serie.labels.map(labelBucket),\r\n datasets: serie.series.map((s, i) => ({\r\n label: s.nome,\r\n data: s.valores,\r\n backgroundColor: cor(i),\r\n borderRadius: 3,\r\n })),\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n plugins: { legend: legendaBaixo },\r\n scales: {\r\n x: { stacked: true, grid: { display: false } },\r\n y: { stacked: true, beginAtZero: true, grid: { color: '#EEF1F5' } },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Horizontal bars of a distribution (top N).\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function BarrasHorizontais({ dados, altura = 280, limite = 12 }: { dados: Distribuicao; altura?: number; limite?: number }) {\r\n const labels = dados.labels.slice(0, limite)\r\n const valores = dados.valores.slice(0, limite)\r\n return (\r\n <div style={{ height: altura }}>\r\n <Bar\r\n data={{\r\n labels,\r\n datasets: [{ label: '', data: valores, backgroundColor: labels.map((_, i) => cor(i)), borderRadius: 3 }],\r\n }}\r\n options={{\r\n indexAxis: 'y',\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n plugins: {\r\n legend: { display: false },\r\n datalabels: { display: (c) => c.dataset.data[c.dataIndex] != null, anchor: 'end', align: 'end', color: '#182238', font: { size: 11, weight: 600 } },\r\n },\r\n scales: {\r\n x: { beginAtZero: true, grid: { color: '#EEF1F5' } },\r\n y: { grid: { display: false } },\r\n },\r\n layout: { padding: { right: 28 } },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport function Anel({ dados, altura = 260, cores }: { dados: Distribuicao; altura?: number; cores?: string[] }) {\r\n return (\r\n <div style={{ height: altura }}>\r\n <Doughnut\r\n data={{\r\n labels: dados.labels,\r\n datasets: [\r\n {\r\n data: dados.valores,\r\n backgroundColor: cores ?? dados.labels.map((_, i) => cor(i)),\r\n borderWidth: 0,\r\n },\r\n ],\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n cutout: '58%',\r\n plugins: {\r\n legend: legendaBaixo,\r\n datalabels: {\r\n display: (c) => Number(c.dataset.data[c.dataIndex]) > 0,\r\n color: '#182238',\r\n font: { size: 11, weight: 600 },\r\n },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Simple line chart — optionally formats values as currency.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Linha({ dados, altura = 260, euros: emEuros = false }: { dados: Distribuicao; altura?: number; euros?: boolean }) {\r\n return (\r\n <div style={{ height: altura }}>\r\n <Line\r\n data={{\r\n labels: dados.labels.map(labelBucket),\r\n datasets: [\r\n {\r\n label: '',\r\n data: dados.valores,\r\n borderColor: '#C23B34',\r\n backgroundColor: 'rgba(194,59,52,0.12)',\r\n fill: true,\r\n tension: 0.25,\r\n pointRadius: 3,\r\n },\r\n ],\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n plugins: {\r\n legend: { display: false },\r\n tooltip: {\r\n callbacks: {\r\n label: (c) => (emEuros ? euros(Number(c.parsed.y)) : String(c.parsed.y)),\r\n },\r\n },\r\n },\r\n scales: {\r\n x: { grid: { display: false } },\r\n y: {\r\n beginAtZero: true,\r\n grid: { color: '#EEF1F5' },\r\n ticks: { callback: (v) => (emEuros ? euros(Number(v)) : String(v)) },\r\n },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Several lines over the same labels — NOT stacked.\r\n *\r\n * Separate from `BarrasEmpilhadas` on purpose: two series that measure the same\r\n * thing at two moments (created vs closed) must be read against each other, and\r\n * stacking them would draw their sum, which means nothing.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Linhas({\r\n serie,\r\n altura = 280,\r\n area = false,\r\n}: {\r\n serie: SerieEmpilhada\r\n altura?: number\r\n /// Fill under each line. Only legible with one or two series.\r\n area?: boolean\r\n}) {\r\n return (\r\n <div style={{ height: altura }}>\r\n <Line\r\n data={{\r\n labels: serie.labels.map(labelBucket),\r\n datasets: serie.series.map((s, i) => ({\r\n label: s.nome,\r\n data: s.valores,\r\n borderColor: cor(i),\r\n backgroundColor: area ? `${cor(i)}22` : cor(i),\r\n fill: area,\r\n tension: 0.25,\r\n pointRadius: serie.labels.length > 24 ? 0 : 3,\r\n pointHoverRadius: 4,\r\n })),\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n interaction: { mode: 'index', intersect: false },\r\n plugins: { legend: legendaBaixo },\r\n scales: {\r\n x: { grid: { display: false } },\r\n y: { beginAtZero: true, grid: { color: '#EEF1F5' } },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface PontoRisco {\r\n responsavel: string\r\n otsAtivas: number\r\n percentagemForaPrazo: number\r\n valorPenalizado: number\r\n}\r\n\r\n/**\r\n * Risk-map bubbles: x = active OTs, y = % overdue, r = penalized value.\r\n * The radius is normalized against the max so bubbles stay readable at any scale.\r\n *\r\n * Axis titles and the tooltip formatter are exposed as optional props with\r\n * neutral English defaults (previously hardcoded Portuguese) so the component\r\n * carries no locale of its own.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Bolhas({\r\n pontos,\r\n altura = 280,\r\n onClick,\r\n xTitle = 'Active OTs',\r\n yTitle = '% overdue',\r\n tooltipLabel = (p) => `${p.responsavel}: ${p.otsAtivas} active, ${p.percentagemForaPrazo}% overdue, ${euros(p.valorPenalizado)}`,\r\n}: {\r\n pontos: PontoRisco[]\r\n altura?: number\r\n onClick?: (p: PontoRisco) => void\r\n xTitle?: string\r\n yTitle?: string\r\n tooltipLabel?: (p: PontoRisco) => string\r\n}) {\r\n const maxValor = Math.max(1, ...pontos.map((p) => p.valorPenalizado))\r\n return (\r\n <div style={{ height: altura }}>\r\n <Bubble\r\n data={{\r\n datasets: pontos.map((p, i) => ({\r\n label: p.responsavel,\r\n data: [\r\n {\r\n x: p.otsAtivas,\r\n y: p.percentagemForaPrazo,\r\n r: 6 + (p.valorPenalizado / maxValor) * 18,\r\n },\r\n ],\r\n backgroundColor: `${cor(i)}CC`,\r\n borderColor: cor(i),\r\n })),\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n onClick: (_e, elements) => {\r\n const idx = elements[0]?.datasetIndex\r\n if (idx != null && onClick) onClick(pontos[idx]!)\r\n },\r\n plugins: {\r\n legend: { display: false },\r\n tooltip: {\r\n callbacks: {\r\n label: (c) => tooltipLabel(pontos[c.datasetIndex]!),\r\n },\r\n },\r\n },\r\n scales: {\r\n x: { beginAtZero: true, title: { display: true, text: xTitle }, grid: { color: '#EEF1F5' } },\r\n y: { beginAtZero: true, title: { display: true, text: yTitle }, grid: { color: '#EEF1F5' } },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n"],"names":["ChartJS"],"mappings":";;;;AAoCA,SAAS,MAAM,GAAsC;AACnD,MAAI,KAAK,KAAM,QAAO;AACtB,QAAM,WAAW,IAAI;AACrB,QAAM,CAAC,SAAS,OAAO,IAAI,KAAK,IAAI,CAAC,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;AAC3D,QAAM,cAAc,QAAQ,QAAQ,yBAAyB,GAAG;AAChE,SAAO,GAAG,WAAW,MAAM,EAAE,GAAG,WAAW,IAAI,OAAO;AACxD;AAGA,SAAS,YAAY,GAAmB;AACtC,MAAI,iBAAiB,KAAK,CAAC,UAAU,IAAI,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;AACpE,MAAI,gBAAgB,KAAK,CAAC,UAAU,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;AAClE,MAAI,sBAAsB,KAAK,CAAC,UAAU,GAAG,EAAE,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,CAAC,CAAC;AACxE,SAAO;AACT;AASAA,MAAQ,SAAS,GAAG,eAAe,eAAe;AAElDA,MAAQ,SAAS,IAAI,sBAAsB,EAAE,SAAS,OAAO;AAC7DA,MAAQ,SAAS,KAAK,SAAS;AAC/BA,MAAQ,SAAS,QAAQ;AAMlB,MAAM,SAAS;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGO,SAAS,IAAI,GAAmB;AACrC,SAAO,OAAO,IAAI,OAAO,MAAM;AACjC;AAEA,MAAM,eAAe;AAAA,EACnB,UAAU;AAAA,EACV,QAAQ,EAAE,UAAU,IAAI,MAAM,EAAE,MAAM,GAAA,GAAM,OAAO,WAAW,eAAe,MAAM,YAAY,SAAA;AACjG;AAMO,SAAS,iBAAiB,EAAE,OAAO,SAAS,OAAmD;AACpG,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ,QAAQ,MAAM,OAAO,IAAI,WAAW;AAAA,QACpC,UAAU,MAAM,OAAO,IAAI,CAAC,GAAG,OAAO;AAAA,UACpC,OAAO,EAAE;AAAA,UACT,MAAM,EAAE;AAAA,UACR,iBAAiB,IAAI,CAAC;AAAA,UACtB,cAAc;AAAA,QAAA,EACd;AAAA,MAAA;AAAA,MAEJ,SAAS;AAAA,QACP,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS,EAAE,QAAQ,aAAA;AAAA,QACnB,QAAQ;AAAA,UACN,GAAG,EAAE,SAAS,MAAM,MAAM,EAAE,SAAS,QAAM;AAAA,UAC3C,GAAG,EAAE,SAAS,MAAM,aAAa,MAAM,MAAM,EAAE,OAAO,UAAA,EAAU;AAAA,QAAE;AAAA,MACpE;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;AAMO,SAAS,kBAAkB,EAAE,OAAO,SAAS,KAAK,SAAS,MAAiE;AACjI,QAAM,SAAS,MAAM,OAAO,MAAM,GAAG,MAAM;AAC3C,QAAM,UAAU,MAAM,QAAQ,MAAM,GAAG,MAAM;AAC7C,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ;AAAA,QACA,UAAU,CAAC,EAAE,OAAO,IAAI,MAAM,SAAS,iBAAiB,OAAO,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,GAAG,cAAc,GAAG;AAAA,MAAA;AAAA,MAEzG,SAAS;AAAA,QACP,WAAW;AAAA,QACX,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS;AAAA,UACP,QAAQ,EAAE,SAAS,MAAA;AAAA,UACnB,YAAY,EAAE,SAAS,CAAC,MAAM,EAAE,QAAQ,KAAK,EAAE,SAAS,KAAK,MAAM,QAAQ,OAAO,OAAO,OAAO,OAAO,WAAW,MAAM,EAAE,MAAM,IAAI,QAAQ,IAAA,EAAI;AAAA,QAAE;AAAA,QAEpJ,QAAQ;AAAA,UACN,GAAG,EAAE,aAAa,MAAM,MAAM,EAAE,OAAO,YAAU;AAAA,UACjD,GAAG,EAAE,MAAM,EAAE,SAAS,QAAM;AAAA,QAAE;AAAA,QAEhC,QAAQ,EAAE,SAAS,EAAE,OAAO,KAAG;AAAA,MAAE;AAAA,IACnC;AAAA,EAAA,GAEJ;AAEJ;AAGO,SAAS,KAAK,EAAE,OAAO,SAAS,KAAK,SAAqE;AAC/G,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ,QAAQ,MAAM;AAAA,QACd,UAAU;AAAA,UACR;AAAA,YACE,MAAM,MAAM;AAAA,YACZ,iBAAiB,SAAS,MAAM,OAAO,IAAI,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC;AAAA,YAC3D,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,MACF;AAAA,MAEF,SAAS;AAAA,QACP,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,SAAS;AAAA,UACP,QAAQ;AAAA,UACR,YAAY;AAAA,YACV,SAAS,CAAC,MAAM,OAAO,EAAE,QAAQ,KAAK,EAAE,SAAS,CAAC,IAAI;AAAA,YACtD,OAAO;AAAA,YACP,MAAM,EAAE,MAAM,IAAI,QAAQ,IAAA;AAAA,UAAI;AAAA,QAChC;AAAA,MACF;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;AAMO,SAAS,MAAM,EAAE,OAAO,SAAS,KAAK,OAAO,UAAU,SAAoE;AAChI,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ,QAAQ,MAAM,OAAO,IAAI,WAAW;AAAA,QACpC,UAAU;AAAA,UACR;AAAA,YACE,OAAO;AAAA,YACP,MAAM,MAAM;AAAA,YACZ,aAAa;AAAA,YACb,iBAAiB;AAAA,YACjB,MAAM;AAAA,YACN,SAAS;AAAA,YACT,aAAa;AAAA,UAAA;AAAA,QACf;AAAA,MACF;AAAA,MAEF,SAAS;AAAA,QACP,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS;AAAA,UACP,QAAQ,EAAE,SAAS,MAAA;AAAA,UACnB,SAAS;AAAA,YACP,WAAW;AAAA,cACT,OAAO,CAAC,MAAO,UAAU,MAAM,OAAO,EAAE,OAAO,CAAC,CAAC,IAAI,OAAO,EAAE,OAAO,CAAC;AAAA,YAAA;AAAA,UACxE;AAAA,QACF;AAAA,QAEF,QAAQ;AAAA,UACN,GAAG,EAAE,MAAM,EAAE,SAAS,QAAM;AAAA,UAC5B,GAAG;AAAA,YACD,aAAa;AAAA,YACb,MAAM,EAAE,OAAO,UAAA;AAAA,YACf,OAAO,EAAE,UAAU,CAAC,MAAO,UAAU,MAAM,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,EAAA;AAAA,UAAG;AAAA,QACrE;AAAA,MACF;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;AAUO,SAAS,OAAO;AAAA,EACrB;AAAA,EACA,SAAS;AAAA,EACT,OAAO;AACT,GAKG;AACD,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ,QAAQ,MAAM,OAAO,IAAI,WAAW;AAAA,QACpC,UAAU,MAAM,OAAO,IAAI,CAAC,GAAG,OAAO;AAAA,UACpC,OAAO,EAAE;AAAA,UACT,MAAM,EAAE;AAAA,UACR,aAAa,IAAI,CAAC;AAAA,UAClB,iBAAiB,OAAO,GAAG,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC;AAAA,UAC7C,MAAM;AAAA,UACN,SAAS;AAAA,UACT,aAAa,MAAM,OAAO,SAAS,KAAK,IAAI;AAAA,UAC5C,kBAAkB;AAAA,QAAA,EAClB;AAAA,MAAA;AAAA,MAEJ,SAAS;AAAA,QACP,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,aAAa,EAAE,MAAM,SAAS,WAAW,MAAA;AAAA,QACzC,SAAS,EAAE,QAAQ,aAAA;AAAA,QACnB,QAAQ;AAAA,UACN,GAAG,EAAE,MAAM,EAAE,SAAS,QAAM;AAAA,UAC5B,GAAG,EAAE,aAAa,MAAM,MAAM,EAAE,OAAO,YAAU;AAAA,QAAE;AAAA,MACrD;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;AAmBO,SAAS,OAAO;AAAA,EACrB;AAAA,EACA,SAAS;AAAA,EACT;AAAA,EACA,SAAS;AAAA,EACT,SAAS;AAAA,EACT,eAAe,CAAC,MAAM,GAAG,EAAE,WAAW,KAAK,EAAE,SAAS,YAAY,EAAE,oBAAoB,cAAc,MAAM,EAAE,eAAe,CAAC;AAChI,GAOG;AACD,QAAM,WAAW,KAAK,IAAI,GAAG,GAAG,OAAO,IAAI,CAAC,MAAM,EAAE,eAAe,CAAC;AACpE,6BACG,OAAA,EAAI,OAAO,EAAE,QAAQ,UACpB,UAAA;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAM;AAAA,QACJ,UAAU,OAAO,IAAI,CAAC,GAAG,OAAO;AAAA,UAC9B,OAAO,EAAE;AAAA,UACT,MAAM;AAAA,YACJ;AAAA,cACE,GAAG,EAAE;AAAA,cACL,GAAG,EAAE;AAAA,cACL,GAAG,IAAK,EAAE,kBAAkB,WAAY;AAAA,YAAA;AAAA,UAC1C;AAAA,UAEF,iBAAiB,GAAG,IAAI,CAAC,CAAC;AAAA,UAC1B,aAAa,IAAI,CAAC;AAAA,QAAA,EAClB;AAAA,MAAA;AAAA,MAEJ,SAAS;AAAA,QACP,qBAAqB;AAAA,QACrB,YAAY;AAAA,QACZ,SAAS,CAAC,IAAI,aAAa;AACzB,gBAAM,MAAM,SAAS,CAAC,GAAG;AACzB,cAAI,OAAO,QAAQ,QAAS,SAAQ,OAAO,GAAG,CAAE;AAAA,QAClD;AAAA,QACA,SAAS;AAAA,UACP,QAAQ,EAAE,SAAS,MAAA;AAAA,UACnB,SAAS;AAAA,YACP,WAAW;AAAA,cACT,OAAO,CAAC,MAAM,aAAa,OAAO,EAAE,YAAY,CAAE;AAAA,YAAA;AAAA,UACpD;AAAA,QACF;AAAA,QAEF,QAAQ;AAAA,UACN,GAAG,EAAE,aAAa,MAAM,OAAO,EAAE,SAAS,MAAM,MAAM,UAAU,MAAM,EAAE,OAAO,YAAU;AAAA,UACzF,GAAG,EAAE,aAAa,MAAM,OAAO,EAAE,SAAS,MAAM,MAAM,UAAU,MAAM,EAAE,OAAO,YAAU;AAAA,QAAE;AAAA,MAC7F;AAAA,IACF;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"Charts.js","sources":["../../../../../src/legacy/components/charts/Charts.tsx"],"sourcesContent":["import React from 'react'\r\nimport { Chart as ChartJS, registerables, type ActiveElement, type ChartEvent } from 'chart.js'\r\nimport ChartDataLabels from 'chartjs-plugin-datalabels'\r\nimport { Bar, Doughnut, Line, Bubble } from 'react-chartjs-2'\r\nimport { useIsDark } from '../../../v1/capabilities/theme/useIsDark'\r\n\r\n// ---------------------------------------------------------------------------\r\n// Local types (inlined — originally imported from CRE `../types`).\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Stacked series over a set of shared labels (e.g. a dimension over time).\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface SerieEmpilhada {\r\n labels: string[]\r\n series: { nome: string; valores: number[] }[]\r\n}\r\n\r\n/**\r\n * A simple distribution: parallel arrays of labels and values.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport interface Distribuicao {\r\n labels: string[]\r\n valores: number[]\r\n}\r\n\r\n/**\r\n * Clique num elemento do gráfico: a etiqueta (ex: \"Incidente\"), a posição dela\r\n * e o nome da série (quando há várias). Serve para filtrar ao clicar.\r\n */\r\nexport type CliqueGrafico = (label: string, indice: number, serie?: string) => void\r\n\r\n// ---------------------------------------------------------------------------\r\n// Local formatting helpers (inlined — originally imported from CRE `../lib/format`).\r\n// Behavior kept close to the originals; the library stays self-contained.\r\n// ---------------------------------------------------------------------------\r\n\r\n/**\r\n * Currency formatter. Thousands separated by '.', decimals by ',', suffixed ' €'.\r\n * Independent of Intl/ICU so the thousands separator is stable across browsers.\r\n */\r\nfunction euros(v: number | null | undefined): string {\r\n if (v == null) return '—'\r\n const negativo = v < 0\r\n const [inteiro, decimal] = Math.abs(v).toFixed(2).split('.')\r\n const comMilhares = inteiro.replace(/\\B(?=(\\d{3})+(?!\\d))/g, '.')\r\n return `${negativo ? '-' : ''}${comMilhares},${decimal} €`\r\n}\r\n\r\n/** 'YYYY-Sxx' / 'YYYY-MM' / 'YYYY-MM-DD' → short axis label. */\r\nfunction labelBucket(b: string): string {\r\n if (/^\\d{4}-S\\d{2}$/.test(b)) return `S${b.slice(6)}/${b.slice(2, 4)}`\r\n if (/^\\d{4}-\\d{2}$/.test(b)) return `${b.slice(5)}/${b.slice(0, 4)}`\r\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(b)) return `${b.slice(8)}/${b.slice(5, 7)}`\r\n return b\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Chart.js registration (once, at module load).\r\n// ---------------------------------------------------------------------------\r\n\r\n// Regista TUDO (registerables inclui Filler, controllers, scales) + o plugin de\r\n// datalabels. O registo parcial degenerava a geometria (doughnut colapsado) e o\r\n// aviso \"fill sem Filler\". registerables = equivalente a chart.js/auto.\r\nChartJS.register(...registerables, ChartDataLabels)\r\n// Datalabels off by default — enabled only where it improves readability.\r\nChartJS.defaults.set('plugins.datalabels', { display: false })\r\nChartJS.defaults.font.family = \"'Montserrat', sans-serif\"\r\nChartJS.defaults.color = '#5B6577'\r\n\r\n/**\r\n * Categorical palette. Stable order so the same dimension always maps to the same color.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport const PALETA = [\r\n '#1868B0',\r\n '#1F8A55',\r\n '#B96E00',\r\n '#C23B34',\r\n '#7C3AED',\r\n '#0891B2',\r\n '#DB2777',\r\n '#65A30D',\r\n '#4B5563',\r\n '#D97706',\r\n '#2563EB',\r\n '#059669',\r\n]\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport function cor(i: number): string {\r\n return PALETA[i % PALETA.length]!\r\n}\r\n\r\n/**\r\n * Cores do texto e da grelha conforme o tema: as do claro sobre o fundo escuro\r\n * deixavam os eixos e os valores ilegíveis.\r\n */\r\nfunction useTema() {\r\n const escuro = useIsDark()\r\n return escuro\r\n ? { texto: '#CBD5E1', forte: '#E2E8F0', grelha: '#1E293B' }\r\n : { texto: '#5B6577', forte: '#182238', grelha: '#EEF1F5' }\r\n}\r\n\r\nfunction legendaBaixo(tema: ReturnType<typeof useTema>) {\r\n return {\r\n position: 'bottom' as const,\r\n labels: { boxWidth: 10, font: { size: 11 }, color: tema.forte, usePointStyle: true, pointStyle: 'circle' as const },\r\n }\r\n}\r\n\r\n/** Liga o clique do Chart.js ao `onClick` da biblioteca, com a mão por cima dos elementos. */\r\nfunction clique(labels: string[], series: { nome: string }[] | undefined, onClick?: CliqueGrafico) {\r\n if (!onClick) return {}\r\n return {\r\n onClick: (_e: ChartEvent, els: ActiveElement[]) => {\r\n const el = els[0]\r\n if (!el) return\r\n onClick(labels[el.index]!, el.index, series?.[el.datasetIndex]?.nome)\r\n },\r\n onHover: (e: ChartEvent, els: ActiveElement[]) => {\r\n const alvo = e.native?.target as HTMLElement | undefined\r\n if (alvo) alvo.style.cursor = els.length ? 'pointer' : 'default'\r\n },\r\n }\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Barras — o componente geral; BarrasEmpilhadas e BarrasHorizontais são atalhos.\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface BarrasProps {\r\n labels: string[]\r\n /** Uma ou várias séries (ex: \"Atribuídos\" e \"Resolvidos\"), lado a lado ou empilhadas. */\r\n series: { nome: string; valores: number[]; cor?: string }[]\r\n /** Barras deitadas, com as etiquetas à esquerda (bom para nomes compridos e rankings). */\r\n horizontal?: boolean\r\n /** Séries empilhadas em vez de lado a lado. */\r\n empilhado?: boolean\r\n /** Altura em px. Nas horizontais, por omissão cresce com o número de barras. */\r\n altura?: number\r\n /** Só as primeiras N (ex: top 10). */\r\n limite?: number\r\n /** Cor de cada barra, quando há uma só série (ex: a cor de cada estado). */\r\n cores?: string[]\r\n /** Formato dos valores no tooltip, nas etiquetas e no eixo (ex: minutos → \"7h30\"). */\r\n formatar?: (v: number) => string\r\n /** Mostra o valor na ponta de cada barra. */\r\n valores?: boolean\r\n /** Junta a percentagem do total ao valor (ex: \"12 (34%)\"); só com uma série. */\r\n percentagem?: boolean\r\n /** Legenda das séries. Por omissão, só quando há mais do que uma. */\r\n legenda?: boolean\r\n /** Formato das etiquetas do eixo (ex: datas). Por omissão, datas ISO ficam curtas. */\r\n formatarEtiqueta?: (label: string) => string\r\n /** Clique numa barra: devolve a etiqueta, a posição e a série. */\r\n onClick?: CliqueGrafico\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport function Barras({\r\n labels: todas,\r\n series: todasSeries,\r\n horizontal = false,\r\n empilhado = false,\r\n altura,\r\n limite,\r\n cores,\r\n formatar = (v) => String(v),\r\n valores = true,\r\n percentagem = false,\r\n legenda,\r\n formatarEtiqueta = labelBucket,\r\n onClick,\r\n}: BarrasProps) {\r\n const tema = useTema()\r\n const labels = limite ? todas.slice(0, limite) : todas\r\n const series = todasSeries.map((s) => ({ ...s, valores: limite ? s.valores.slice(0, limite) : s.valores }))\r\n const uma = series.length === 1\r\n // A percentagem é do total, não só das barras mostradas (com `limite` seria das top N).\r\n const total = uma ? todasSeries[0]!.valores.reduce((a, b) => a + (b || 0), 0) : 0\r\n const etiqueta = (v: number) => (percentagem && uma && total > 0 ? `${formatar(v)} (${Math.round((v / total) * 100)}%)` : formatar(v))\r\n const alturaFinal = altura ?? (horizontal ? Math.max(200, labels.length * 30 + 40) : 260)\r\n const eixoValor = { beginAtZero: true, stacked: empilhado, grid: { color: tema.grelha }, ticks: { color: tema.texto, callback: (v: string | number) => formatar(Number(v)) } }\r\n const eixoEtiqueta = { stacked: empilhado, grid: { display: false }, ticks: { color: tema.texto } }\r\n\r\n return (\r\n <div style={{ height: alturaFinal }}>\r\n <Bar\r\n data={{\r\n labels: labels.map(formatarEtiqueta),\r\n datasets: series.map((s, i) => ({\r\n label: s.nome,\r\n data: s.valores,\r\n backgroundColor: uma && cores ? labels.map((_, j) => cores[j % cores.length]!) : (s.cor ?? cor(i)),\r\n borderRadius: 4,\r\n maxBarThickness: 40,\r\n })),\r\n }}\r\n options={{\r\n indexAxis: horizontal ? 'y' : 'x',\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n ...clique(labels, series, onClick),\r\n plugins: {\r\n legend: legenda ?? !uma ? legendaBaixo(tema) : { display: false },\r\n tooltip: { callbacks: { label: (c) => `${c.dataset.label ? `${c.dataset.label}: ` : ''}${etiqueta(Number(c.parsed[horizontal ? 'x' : 'y']))}` } },\r\n datalabels: {\r\n display: (c) => valores && !empilhado && Number(c.dataset.data[c.dataIndex]) > 0,\r\n anchor: 'end',\r\n align: 'end',\r\n color: tema.forte,\r\n font: { size: 10, weight: 600 },\r\n formatter: (v: number) => etiqueta(v),\r\n },\r\n },\r\n scales: horizontal ? { x: eixoValor, y: eixoEtiqueta } : { x: eixoEtiqueta, y: eixoValor },\r\n layout: { padding: horizontal ? { right: valores ? (percentagem ? 56 : 32) : 8 } : { top: valores ? 18 : 4 } },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Stacked bars for a dimension over time.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function BarrasEmpilhadas({ serie, altura = 280, onClick }: { serie: SerieEmpilhada; altura?: number; onClick?: CliqueGrafico }) {\r\n return <Barras labels={serie.labels} series={serie.series} empilhado altura={altura} onClick={onClick} legenda />\r\n}\r\n\r\n/**\r\n * Horizontal bars of a distribution (top N).\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function BarrasHorizontais({\r\n dados,\r\n altura = 280,\r\n limite = 12,\r\n onClick,\r\n}: {\r\n dados: Distribuicao\r\n altura?: number\r\n limite?: number\r\n onClick?: CliqueGrafico\r\n}) {\r\n const n = Math.min(limite, dados.labels.length)\r\n return (\r\n <Barras\r\n horizontal\r\n labels={dados.labels}\r\n series={[{ nome: '', valores: dados.valores }]}\r\n cores={Array.from({ length: n }, (_, i) => cor(i))}\r\n limite={limite}\r\n altura={altura}\r\n onClick={onClick}\r\n />\r\n )\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport function Anel({\r\n dados,\r\n altura = 260,\r\n cores,\r\n formatar = (v) => String(v),\r\n onClick,\r\n}: {\r\n dados: Distribuicao\r\n altura?: number\r\n cores?: string[]\r\n /** Formato dos valores no tooltip. */\r\n formatar?: (v: number) => string\r\n /** Clique numa fatia: devolve a etiqueta e a posição. */\r\n onClick?: CliqueGrafico\r\n}) {\r\n const tema = useTema()\r\n const total = dados.valores.reduce((a, b) => a + (b || 0), 0)\r\n return (\r\n <div style={{ height: altura }}>\r\n <Doughnut\r\n data={{\r\n labels: dados.labels,\r\n datasets: [\r\n {\r\n data: dados.valores,\r\n backgroundColor: cores ?? dados.labels.map((_, i) => cor(i)),\r\n borderWidth: 0,\r\n },\r\n ],\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n cutout: '58%',\r\n ...clique(dados.labels, undefined, onClick),\r\n plugins: {\r\n legend: legendaBaixo(tema),\r\n tooltip: {\r\n callbacks: {\r\n label: (c) => {\r\n const v = Number(c.parsed)\r\n return ` ${c.label}: ${formatar(v)}${total > 0 ? ` (${Math.round((v / total) * 100)}%)` : ''}`\r\n },\r\n },\r\n },\r\n datalabels: {\r\n // Só nas fatias que têm espaço para o número.\r\n display: (c) => total > 0 && Number(c.dataset.data[c.dataIndex]) / total >= 0.05,\r\n color: '#FFFFFF',\r\n font: { size: 11, weight: 700 },\r\n formatter: (v: number) => formatar(v),\r\n },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Simple line chart — optionally formats values as currency.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Linha({\r\n dados,\r\n altura = 260,\r\n euros: emEuros = false,\r\n onClick,\r\n}: {\r\n dados: Distribuicao\r\n altura?: number\r\n euros?: boolean\r\n onClick?: CliqueGrafico\r\n}) {\r\n const tema = useTema()\r\n return (\r\n <div style={{ height: altura }}>\r\n <Line\r\n data={{\r\n labels: dados.labels.map(labelBucket),\r\n datasets: [\r\n {\r\n label: '',\r\n data: dados.valores,\r\n borderColor: '#C23B34',\r\n backgroundColor: 'rgba(194,59,52,0.12)',\r\n fill: true,\r\n tension: 0.25,\r\n pointRadius: 3,\r\n },\r\n ],\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n ...clique(dados.labels, undefined, onClick),\r\n plugins: {\r\n legend: { display: false },\r\n tooltip: {\r\n callbacks: {\r\n label: (c) => (emEuros ? euros(Number(c.parsed.y)) : String(c.parsed.y)),\r\n },\r\n },\r\n },\r\n scales: {\r\n x: { grid: { display: false }, ticks: { color: tema.texto } },\r\n y: {\r\n beginAtZero: true,\r\n grid: { color: tema.grelha },\r\n ticks: { color: tema.texto, callback: (v) => (emEuros ? euros(Number(v)) : String(v)) },\r\n },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/**\r\n * Several lines over the same labels — NOT stacked.\r\n *\r\n * Separate from `BarrasEmpilhadas` on purpose: two series that measure the same\r\n * thing at two moments (created vs closed) must be read against each other, and\r\n * stacking them would draw their sum, which means nothing.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Linhas({\r\n serie,\r\n altura = 280,\r\n area = false,\r\n cores,\r\n formatar = (v) => String(v),\r\n formatarEtiqueta = labelBucket,\r\n onClick,\r\n}: {\r\n serie: SerieEmpilhada\r\n altura?: number\r\n /// Fill under each line. Only legible with one or two series.\r\n area?: boolean\r\n /** Cor de cada série, pela ordem. */\r\n cores?: string[]\r\n /** Formato dos valores no tooltip e no eixo. */\r\n formatar?: (v: number) => string\r\n /** Formato das etiquetas do eixo (ex: datas). */\r\n formatarEtiqueta?: (label: string) => string\r\n /** Clique num ponto: devolve a etiqueta (ex: o dia) e a série. */\r\n onClick?: CliqueGrafico\r\n}) {\r\n const tema = useTema()\r\n const corDe = (i: number) => cores?.[i] ?? cor(i)\r\n return (\r\n <div style={{ height: altura }}>\r\n <Line\r\n data={{\r\n labels: serie.labels.map(formatarEtiqueta),\r\n datasets: serie.series.map((s, i) => ({\r\n label: s.nome,\r\n data: s.valores,\r\n borderColor: corDe(i),\r\n backgroundColor: area ? `${corDe(i)}22` : corDe(i),\r\n fill: area,\r\n tension: 0.25,\r\n pointRadius: serie.labels.length > 24 ? 0 : 3,\r\n pointHoverRadius: 4,\r\n })),\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n interaction: { mode: 'index', intersect: false },\r\n ...clique(serie.labels, serie.series, onClick),\r\n plugins: {\r\n legend: legendaBaixo(tema),\r\n tooltip: { callbacks: { label: (c) => `${c.dataset.label}: ${formatar(Number(c.parsed.y))}` } },\r\n },\r\n scales: {\r\n x: { grid: { display: false }, ticks: { color: tema.texto, autoSkip: true, maxRotation: 0 } },\r\n y: { beginAtZero: true, grid: { color: tema.grelha }, ticks: { color: tema.texto, callback: (v) => formatar(Number(v)) } },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n\r\n/** @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy. */\r\nexport interface PontoRisco {\r\n responsavel: string\r\n otsAtivas: number\r\n percentagemForaPrazo: number\r\n valorPenalizado: number\r\n}\r\n\r\n/**\r\n * Risk-map bubbles: x = active OTs, y = % overdue, r = penalized value.\r\n * The radius is normalized against the max so bubbles stay readable at any scale.\r\n *\r\n * Axis titles and the tooltip formatter are exposed as optional props with\r\n * neutral English defaults (previously hardcoded Portuguese) so the component\r\n * carries no locale of its own.\r\n * @deprecated Legacy — não usar em código novo. Ver Storybook › Legacy.\r\n */\r\nexport function Bolhas({\r\n pontos,\r\n altura = 280,\r\n onClick,\r\n xTitle = 'Active OTs',\r\n yTitle = '% overdue',\r\n tooltipLabel = (p) => `${p.responsavel}: ${p.otsAtivas} active, ${p.percentagemForaPrazo}% overdue, ${euros(p.valorPenalizado)}`,\r\n}: {\r\n pontos: PontoRisco[]\r\n altura?: number\r\n onClick?: (p: PontoRisco) => void\r\n xTitle?: string\r\n yTitle?: string\r\n tooltipLabel?: (p: PontoRisco) => string\r\n}) {\r\n const tema = useTema()\r\n const maxValor = Math.max(1, ...pontos.map((p) => p.valorPenalizado))\r\n return (\r\n <div style={{ height: altura }}>\r\n <Bubble\r\n data={{\r\n datasets: pontos.map((p, i) => ({\r\n label: p.responsavel,\r\n data: [\r\n {\r\n x: p.otsAtivas,\r\n y: p.percentagemForaPrazo,\r\n r: 6 + (p.valorPenalizado / maxValor) * 18,\r\n },\r\n ],\r\n backgroundColor: `${cor(i)}CC`,\r\n borderColor: cor(i),\r\n })),\r\n }}\r\n options={{\r\n maintainAspectRatio: false,\r\n responsive: true,\r\n onClick: (_e, elements) => {\r\n const idx = elements[0]?.datasetIndex\r\n if (idx != null && onClick) onClick(pontos[idx]!)\r\n },\r\n plugins: {\r\n legend: { display: false },\r\n tooltip: {\r\n callbacks: {\r\n label: (c) => tooltipLabel(pontos[c.datasetIndex]!),\r\n },\r\n },\r\n },\r\n scales: {\r\n x: { beginAtZero: true, title: { display: true, text: xTitle, color: tema.texto }, grid: { color: tema.grelha }, ticks: { color: tema.texto } },\r\n y: { beginAtZero: true, title: { display: true, text: yTitle, color: tema.texto }, grid: { color: tema.grelha }, ticks: { color: tema.texto } },\r\n },\r\n }}\r\n />\r\n </div>\r\n )\r\n}\r\n"],"names":["ChartJS"],"mappings":"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"}
|
|
@@ -1,91 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
const Menu = ({ size = 24, className }) => /* @__PURE__ */ jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className, children: [
|
|
5
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "12", y2: "12" }),
|
|
6
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "6", y2: "6" }),
|
|
7
|
-
/* @__PURE__ */ jsx("line", { x1: "4", x2: "20", y1: "18", y2: "18" })
|
|
8
|
-
] });
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import AppShell from "../../../../v1/components/layout/AppShell/AppShell.js";
|
|
3
|
+
import { labelsV1, menuV1 } from "../Sidebar/Sidebar.js";
|
|
9
4
|
const Layout = ({
|
|
10
5
|
children,
|
|
11
6
|
menus,
|
|
12
|
-
groupLabels,
|
|
13
|
-
appTitle,
|
|
14
|
-
topBar,
|
|
15
|
-
avatar,
|
|
16
|
-
onLogout,
|
|
17
|
-
logoutLabel,
|
|
18
|
-
languages,
|
|
19
7
|
currentLang,
|
|
20
|
-
|
|
21
|
-
theme,
|
|
22
|
-
onThemeChange,
|
|
8
|
+
logoutLabel,
|
|
23
9
|
themeLabels,
|
|
24
|
-
footer,
|
|
25
|
-
deployedAt,
|
|
26
10
|
deployedAtLabel,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
const contentMarginLeft = isMobile ? 0 : sidebarOpen ? 256 : 80;
|
|
45
|
-
return /* @__PURE__ */ jsxs("div", { className: "min-h-screen bg-slate-50/30 dark:bg-slate-950 flex", children: [
|
|
46
|
-
/* @__PURE__ */ jsx(
|
|
47
|
-
Sidebar,
|
|
48
|
-
{
|
|
49
|
-
isOpen: sidebarOpen,
|
|
50
|
-
setIsOpen: setSidebarOpen,
|
|
51
|
-
menus,
|
|
52
|
-
groupLabels,
|
|
53
|
-
appTitle,
|
|
54
|
-
avatar,
|
|
55
|
-
onLogout,
|
|
56
|
-
logoutLabel,
|
|
57
|
-
languages,
|
|
58
|
-
currentLang,
|
|
59
|
-
onLanguageChange,
|
|
60
|
-
theme,
|
|
61
|
-
onThemeChange,
|
|
62
|
-
themeLabels,
|
|
63
|
-
footer,
|
|
64
|
-
deployedAt,
|
|
65
|
-
deployedAtLabel
|
|
66
|
-
}
|
|
67
|
-
),
|
|
68
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-1 flex flex-col min-w-0 transition-all duration-300", children: [
|
|
69
|
-
!sidebarOpen && /* @__PURE__ */ jsx(
|
|
70
|
-
"button",
|
|
71
|
-
{
|
|
72
|
-
onClick: () => setSidebarOpen(true),
|
|
73
|
-
className: "fixed top-6 left-6 z-50 p-2.5 bg-white shadow-md border border-slate-200 rounded-lg text-slate-500 hover:text-proef-blue dark:bg-slate-900 dark:border-slate-700 dark:text-slate-400 transition-colors sm:hidden",
|
|
74
|
-
children: /* @__PURE__ */ jsx(Menu, { size: 20 })
|
|
75
|
-
}
|
|
76
|
-
),
|
|
77
|
-
topBar && /* @__PURE__ */ jsx("div", { style: { marginLeft: contentMarginLeft }, className: "sticky top-0 z-30 transition-all duration-300", children: topBar }),
|
|
78
|
-
/* @__PURE__ */ jsx(
|
|
79
|
-
"main",
|
|
80
|
-
{
|
|
81
|
-
style: { marginLeft: contentMarginLeft },
|
|
82
|
-
className: `pb-16 px-4 sm:px-12 transition-all duration-300 ${topBar ? "pt-6 sm:pt-6" : "pt-24 sm:pt-8"}`,
|
|
83
|
-
children: /* @__PURE__ */ jsx("div", { className: "mx-auto animate-in fade-in slide-in-from-bottom-2 duration-700", children })
|
|
84
|
-
}
|
|
85
|
-
)
|
|
86
|
-
] })
|
|
87
|
-
] });
|
|
88
|
-
};
|
|
11
|
+
footer,
|
|
12
|
+
sidebarOpen,
|
|
13
|
+
onSidebarOpenChange,
|
|
14
|
+
...rest
|
|
15
|
+
}) => /* @__PURE__ */ jsx(
|
|
16
|
+
AppShell,
|
|
17
|
+
{
|
|
18
|
+
...rest,
|
|
19
|
+
menu: menuV1(menus),
|
|
20
|
+
currentLanguage: currentLang,
|
|
21
|
+
labels: labelsV1({ logoutLabel, themeLabels, deployedAtLabel }),
|
|
22
|
+
sidebarFooter: footer,
|
|
23
|
+
defaultOpen: sidebarOpen,
|
|
24
|
+
onOpenChange: onSidebarOpenChange,
|
|
25
|
+
children
|
|
26
|
+
}
|
|
27
|
+
);
|
|
89
28
|
export {
|
|
90
29
|
Layout as default
|
|
91
30
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Layout.js","sources":["../../../../../../src/legacy/components/layout/Layout/Layout.tsx"],"sourcesContent":["import React
|
|
1
|
+
{"version":3,"file":"Layout.js","sources":["../../../../../../src/legacy/components/layout/Layout/Layout.tsx"],"sourcesContent":["import React from 'react'\r\nimport AppShell from '../../../../v1/components/layout/AppShell/AppShell'\r\nimport { labelsV1, menuV1, type SidebarMenuItem, type SidebarLanguage, type SidebarTheme } from '../Sidebar/Sidebar'\r\n\r\n/*\r\n * Migrado para o V1: a moldura da app é o `AppShell` do V1. Este ficheiro só\r\n * mantém a API antiga, e os seus textos por omissão, para as apps que ainda a\r\n * usam.\r\n */\r\n\r\n/** @deprecated Legacy — usar `AppShellProps` do V1. */\r\nexport interface LayoutProps {\r\n children: React.ReactNode\r\n menus: SidebarMenuItem[]\r\n groupLabels?: Record<string, string>\r\n appTitle?: string\r\n /** Barra superior opcional (título/alertas), sticky acima do conteúdo. */\r\n topBar?: React.ReactNode\r\n avatar?: React.ReactNode\r\n onLogout?: () => void\r\n logoutLabel?: string\r\n languages?: SidebarLanguage[]\r\n currentLang?: string\r\n onLanguageChange?: (code: string) => void\r\n theme?: SidebarTheme\r\n onThemeChange?: (theme: SidebarTheme) => void\r\n themeLabels?: { label?: string; light?: string; dark?: string; system?: string }\r\n footer?: (isExpanded: boolean) => React.ReactNode\r\n deployedAt?: string | number | Date\r\n deployedAtLabel?: string\r\n /** Estado inicial da sidebar (aberta/fechada). */\r\n sidebarOpen?: boolean\r\n /** Chamado quando a pessoa abre/fecha a sidebar. */\r\n onSidebarOpenChange?: (open: boolean) => void\r\n}\r\n\r\n/** @deprecated Legacy — usar `AppShell` do V1. */\r\nconst Layout = ({\r\n children,\r\n menus,\r\n currentLang,\r\n logoutLabel,\r\n themeLabels,\r\n deployedAtLabel,\r\n footer,\r\n sidebarOpen,\r\n onSidebarOpenChange,\r\n ...rest\r\n}: LayoutProps) => (\r\n <AppShell\r\n {...rest}\r\n menu={menuV1(menus)}\r\n currentLanguage={currentLang}\r\n labels={labelsV1({ logoutLabel, themeLabels, deployedAtLabel })}\r\n sidebarFooter={footer}\r\n defaultOpen={sidebarOpen}\r\n onOpenChange={onSidebarOpenChange}\r\n >\r\n {children}\r\n </AppShell>\r\n)\r\n\r\nexport default Layout\r\n"],"names":[],"mappings":";;;AAqCA,MAAM,SAAS,CAAC;AAAA,EACd;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,MACE;AAAA,EAAC;AAAA,EAAA;AAAA,IACE,GAAG;AAAA,IACJ,MAAM,OAAO,KAAK;AAAA,IAClB,iBAAiB;AAAA,IACjB,QAAQ,SAAS,EAAE,aAAa,aAAa,iBAAiB;AAAA,IAC9D,eAAe;AAAA,IACf,aAAa;AAAA,IACb,cAAc;AAAA,IAEb;AAAA,EAAA;AACH;"}
|