@actionexec/dashboards 0.13.0 → 0.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +30 -25
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/types/statement.d.ts +7 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsxs as _, jsx as r, Fragment as oe } from "react/jsx-runtime";
|
|
2
|
-
import { useState as
|
|
3
|
-
import { M as Y, f as Ne, a as Se, c as Q, b as Z, d as ke, e as de, i as J, g as j, p as Ce, h as X, j as ue, k as me, l as z, m as Re, D, S as he, n as $e, o as xe, C as
|
|
2
|
+
import { useState as A, useRef as R, useEffect as W, useCallback as T, useMemo as ce } from "react";
|
|
3
|
+
import { M as Y, f as Ne, a as Se, c as Q, b as Z, d as ke, e as de, i as J, g as j, p as Ce, h as X, j as ue, k as me, l as z, m as Re, D, S as he, n as $e, o as xe, C as Ae, q as Ie, r as ge, s as Te, t as Fe, u as Ee, G as Me, v as ee, w as Le, x as Oe, y as Pe, z as We, A as De } from "./ColorPaletteSelector-CZP3HDNJ.js";
|
|
4
4
|
import { B as qt } from "./ColorPaletteSelector-CZP3HDNJ.js";
|
|
5
5
|
import { LineChart as He, Line as ze, AreaChart as Ge, Area as Ye, BarChart as fe, Bar as V, CartesianGrid as _e, XAxis as pe, YAxis as be, Tooltip as K, Legend as je, Cell as te, PieChart as Ve, Pie as Ke } from "recharts";
|
|
6
6
|
const re = "__window";
|
|
@@ -27,7 +27,7 @@ function ve(e) {
|
|
|
27
27
|
}
|
|
28
28
|
const Ue = 300;
|
|
29
29
|
function Xe(e) {
|
|
30
|
-
const [t, a] =
|
|
30
|
+
const [t, a] = A(null), [n, l] = A(null), [s, o] = A({}), [i, m] = A({}), [d, f] = A(null), [h, u] = A(!0), [g, p] = A(null), N = R(), C = R(!1);
|
|
31
31
|
W(() => {
|
|
32
32
|
let k = !1;
|
|
33
33
|
return Ne(e).then((S) => {
|
|
@@ -94,18 +94,18 @@ function Ze(e) {
|
|
|
94
94
|
function Je(e) {
|
|
95
95
|
const t = R(e);
|
|
96
96
|
t.current = e;
|
|
97
|
-
const a = R(null), n = R(null), l = R(null), s = R(null), o = R(null), i = R(0), m = R(0), d = R(!1), f = R(!1), h = R(-1), [u, g] =
|
|
97
|
+
const a = R(null), n = R(null), l = R(null), s = R(null), o = R(null), i = R(0), m = R(0), d = R(!1), f = R(!1), h = R(-1), [u, g] = A(!1), p = T((c) => {
|
|
98
98
|
const b = n.current;
|
|
99
99
|
if (f.current || t.current.silenceWarnings || !b) return;
|
|
100
|
-
const
|
|
101
|
-
!
|
|
102
|
-
`[@actionexec/dashboards] O dashboard esta sendo cortado: o container precisa de ${Math.ceil(c.gridHeight)}px de altura, mas o ancestral com overflow oculto tem ${
|
|
100
|
+
const I = Ze(b);
|
|
101
|
+
!I || I.clientHeight >= c.gridHeight || (f.current = !0, console.warn(
|
|
102
|
+
`[@actionexec/dashboards] O dashboard esta sendo cortado: o container precisa de ${Math.ceil(c.gridHeight)}px de altura, mas o ancestral com overflow oculto tem ${I.clientHeight}px. A altura do dashboard varia com a largura — use a prop onGeometryChange para dimensionar o container, ou troque o overflow para auto. Passe silenceWarnings para desligar este aviso.`
|
|
103
103
|
));
|
|
104
104
|
}, []), N = T(() => {
|
|
105
105
|
var P, M;
|
|
106
106
|
if (!a.current) return;
|
|
107
|
-
const { columns: c, cellAspect: b } = t.current,
|
|
108
|
-
containerWidth:
|
|
107
|
+
const { columns: c, cellAspect: b } = t.current, I = i.current, O = Z(I, c), v = {
|
|
108
|
+
containerWidth: I,
|
|
109
109
|
cellWidth: O,
|
|
110
110
|
cellHeight: Q(O, b),
|
|
111
111
|
gridHeight: m.current,
|
|
@@ -115,12 +115,12 @@ function Je(e) {
|
|
|
115
115
|
}, [p]), C = T((c = !1) => {
|
|
116
116
|
const b = a.current;
|
|
117
117
|
if (!b) return;
|
|
118
|
-
const
|
|
119
|
-
if (!c &&
|
|
120
|
-
h.current =
|
|
121
|
-
const { columns: O, cellAspect: v, stackBelow: F } = t.current, E = Z(
|
|
118
|
+
const I = i.current;
|
|
119
|
+
if (!c && I === h.current) return;
|
|
120
|
+
h.current = I;
|
|
121
|
+
const { columns: O, cellAspect: v, stackBelow: F } = t.current, E = Z(I, O);
|
|
122
122
|
b.style.setProperty("--dash-cell-h", `${Q(E, v)}px`);
|
|
123
|
-
const P = Qe(F, O, v), M = P > 0 &&
|
|
123
|
+
const P = Qe(F, O, v), M = P > 0 && I > 0 && I < P;
|
|
124
124
|
M !== d.current && (d.current = M, g(M));
|
|
125
125
|
}, []), y = T(() => {
|
|
126
126
|
s.current !== null && (cancelAnimationFrame(s.current), s.current = null);
|
|
@@ -232,7 +232,7 @@ function st({ data: e, palette: t, label: a }) {
|
|
|
232
232
|
] }) });
|
|
233
233
|
}
|
|
234
234
|
function q(e) {
|
|
235
|
-
const [t, a] =
|
|
235
|
+
const [t, a] = A({ width: 0, height: 0 });
|
|
236
236
|
return W(() => {
|
|
237
237
|
const n = e.current;
|
|
238
238
|
if (!n) return;
|
|
@@ -633,14 +633,14 @@ function $t({ config: e, palette: t, onChange: a }) {
|
|
|
633
633
|
const n = e.label || "Cores", l = e.locked || !1;
|
|
634
634
|
return /* @__PURE__ */ _("div", { className: `widget-palette ${l ? "widget-palette--locked" : ""}`, children: [
|
|
635
635
|
/* @__PURE__ */ r("label", { className: "widget-palette__label", children: n }),
|
|
636
|
-
/* @__PURE__ */ r(
|
|
636
|
+
/* @__PURE__ */ r(Ae, { selected: t, onSelect: a, customMode: !0, disabled: l }),
|
|
637
637
|
l && /* @__PURE__ */ r("span", { className: "widget-palette__lock-icon", title: "Bloqueado", children: "🔒" })
|
|
638
638
|
] });
|
|
639
639
|
}
|
|
640
640
|
const xt = {
|
|
641
641
|
failed_to_compute: "Não foi possível calcular este widget"
|
|
642
642
|
};
|
|
643
|
-
function
|
|
643
|
+
function At({
|
|
644
644
|
type: e,
|
|
645
645
|
computed: t,
|
|
646
646
|
palette: a,
|
|
@@ -663,7 +663,7 @@ function It({
|
|
|
663
663
|
stateMessage: xt[String(t.error)]
|
|
664
664
|
}
|
|
665
665
|
);
|
|
666
|
-
const h =
|
|
666
|
+
const h = Ie(a);
|
|
667
667
|
switch (e) {
|
|
668
668
|
case "kpi_card":
|
|
669
669
|
return /* @__PURE__ */ r(at, { data: t, label: n == null ? void 0 : n.label });
|
|
@@ -710,7 +710,7 @@ function It({
|
|
|
710
710
|
return /* @__PURE__ */ r(L, { name: "unknown", state: "unconfigured" });
|
|
711
711
|
}
|
|
712
712
|
}
|
|
713
|
-
const
|
|
713
|
+
const It = (e, t) => e.grid.y - t.grid.y || e.grid.x - t.grid.x;
|
|
714
714
|
function Kt({
|
|
715
715
|
token: e,
|
|
716
716
|
cellAspect: t = Le,
|
|
@@ -738,7 +738,7 @@ function Kt({
|
|
|
738
738
|
silenceWarnings: l
|
|
739
739
|
}), $ = ce(() => {
|
|
740
740
|
const c = (o == null ? void 0 : o.widgets) ?? [];
|
|
741
|
-
return w ? [...c].sort(
|
|
741
|
+
return w ? [...c].sort(It) : c;
|
|
742
742
|
}, [o == null ? void 0 : o.widgets, w]), x = {
|
|
743
743
|
"--dash-gap": `${ee}px`,
|
|
744
744
|
"--dash-pad": `${Me}px`
|
|
@@ -751,14 +751,14 @@ function Kt({
|
|
|
751
751
|
else if (o.widgets.length === 0)
|
|
752
752
|
S = /* @__PURE__ */ r("div", { className: "preview-tab__empty", children: "Este dashboard nao possui widgets." });
|
|
753
753
|
else {
|
|
754
|
-
const c = (i == null ? void 0 : i.widgets) ?? {}, b = (i == null ? void 0 : i.date_bounds) ?? null,
|
|
754
|
+
const c = (i == null ? void 0 : i.widgets) ?? {}, b = (i == null ? void 0 : i.date_bounds) ?? null, I = {
|
|
755
755
|
"--dash-cols": o.gridColumns,
|
|
756
756
|
"--dash-rows": o.gridRows,
|
|
757
757
|
...ge(u)
|
|
758
758
|
}, O = ["preview-tab__grid", w && "preview-tab__grid--stacked"].filter(Boolean).join(" ");
|
|
759
759
|
S = /* @__PURE__ */ _(oe, { children: [
|
|
760
760
|
d && !i && /* @__PURE__ */ r("div", { className: "preview-tab__error", children: d }),
|
|
761
|
-
i && /* @__PURE__ */ r("div", { className: O, style:
|
|
761
|
+
i && /* @__PURE__ */ r("div", { className: O, style: I, ref: y, children: $.map((v) => {
|
|
762
762
|
const F = Te.has(v.type), E = c[v.id], P = w ? {
|
|
763
763
|
gridColumn: 1,
|
|
764
764
|
aspectRatio: `${Ee(v.grid.w, v.grid.h, t)}`,
|
|
@@ -773,7 +773,7 @@ function Kt({
|
|
|
773
773
|
className: `preview-tab__widget ${F ? "preview-tab__widget--control" : ""}`,
|
|
774
774
|
style: P,
|
|
775
775
|
children: F || E ? /* @__PURE__ */ r(
|
|
776
|
-
|
|
776
|
+
At,
|
|
777
777
|
{
|
|
778
778
|
type: v.type,
|
|
779
779
|
computed: E || {},
|
|
@@ -817,7 +817,7 @@ function Lt(e, t) {
|
|
|
817
817
|
}
|
|
818
818
|
const Ot = 300;
|
|
819
819
|
function Pt(e) {
|
|
820
|
-
const [t, a] =
|
|
820
|
+
const [t, a] = A(null), [n, l] = A(null), [s, o] = A({}), [i, m] = A(!0), [d, f] = A(null), [h, u] = A(!1), g = R(), p = R(!1);
|
|
821
821
|
W(() => {
|
|
822
822
|
let y = !1;
|
|
823
823
|
return Pe(e).then((w) => {
|
|
@@ -918,7 +918,7 @@ function Ht({ definition: e, value: t, options: a, bounds: n, onChange: l }) {
|
|
|
918
918
|
function zt({ line: e, columnCount: t, showTotal: a, showVertical: n, showHorizontal: l }) {
|
|
919
919
|
if (e.type === "separator")
|
|
920
920
|
return /* @__PURE__ */ r("tr", { className: "stmt__row stmt__row--separator", children: /* @__PURE__ */ r("td", { colSpan: t }) });
|
|
921
|
-
if (e.type === "header")
|
|
921
|
+
if (e.type === "header" && e.formatted.length === 0)
|
|
922
922
|
return /* @__PURE__ */ _("tr", { className: "stmt__row stmt__row--header", children: [
|
|
923
923
|
/* @__PURE__ */ r("th", { scope: "row", style: ie(e.style.indent), children: e.label }),
|
|
924
924
|
/* @__PURE__ */ r("td", { colSpan: t - 1 })
|
|
@@ -1009,6 +1009,11 @@ function Ut({ token: e, palette: t, showDownload: a = !0, className: n }) {
|
|
|
1009
1009
|
] })
|
|
1010
1010
|
] }),
|
|
1011
1011
|
i && /* @__PURE__ */ r("div", { className: "stmt__error", children: i }),
|
|
1012
|
+
(s == null ? void 0 : s.truncated) && /* @__PURE__ */ _("div", { className: "stmt__warning", children: [
|
|
1013
|
+
"A janela pedida excede o limite de colunas: o documento mostra as primeiras ",
|
|
1014
|
+
w.length,
|
|
1015
|
+
". Escolha um período menor ou uma coluna mais larga."
|
|
1016
|
+
] }),
|
|
1012
1017
|
s ? w.length === 0 ? /* @__PURE__ */ r("div", { className: "stmt__state", children: "Nenhum período na janela selecionada." }) : $.length === 0 ? /* @__PURE__ */ r("div", { className: "stmt__state", children: "Este demonstrativo não possui linhas." }) : /* @__PURE__ */ r("div", { className: "stmt__scroll", children: /* @__PURE__ */ _("table", { className: "stmt__table", children: [
|
|
1013
1018
|
/* @__PURE__ */ r("thead", { children: /* @__PURE__ */ _("tr", { children: [
|
|
1014
1019
|
/* @__PURE__ */ r("th", { className: "stmt__corner", scope: "col", children: s.name }),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/api/params.ts","../src/hooks/useDashboardData.ts","../src/hooks/useGridGeometry.ts","../src/widgets/WidgetFrame.tsx","../src/widgets/comparison.ts","../src/widgets/KPIWidget.tsx","../src/widgets/GaugeWidget.tsx","../src/hooks/useContainerSize.ts","../src/widgets/ChartWidget.tsx","../src/widgets/CompositionWidget.tsx","../src/widgets/TableWidget.tsx","../src/widgets/FilterWidget.tsx","../src/widgets/VariableWidget.tsx","../src/widgets/ColorPaletteWidget.tsx","../src/widgets/WidgetRenderer.tsx","../src/Dashboard.tsx","../src/utils/download.ts","../src/hooks/useStatementData.ts","../src/Statement.tsx"],"sourcesContent":["// Purpose: Protocolo de query params da API externa (prefixos f_ e v_).\n// Scope: Compartilhado por dashboards e demonstrativos — as duas verticais falam a\n// mesma lingua com o backend, entao a traducao mora num lugar so.\n// Public API: WINDOW_FILTER_ID, buildQueryParams, syncFiltersFromApplied\n\nimport { MULTI_VALUE_SEPARATOR } from '../types';\n\n/**\n * Chave reservada da janela de datas embutida do demonstrativo.\n *\n * Nao e um filtro declarado: e o recorte que define as colunas, e existe mesmo\n * quando o documento nao declara filtro nenhum. Vale-se do formato \"start|end\"\n * para virar `f_date_start`/`f_date_end` como qualquer filtro temporal.\n */\nexport const WINDOW_FILTER_ID = '__window';\n\n/**\n * Constroi os query params no formato esperado pela API.\n *\n * Filtros temporais viajam como \"start|end\" e viram o par global\n * `f_date_start`/`f_date_end` — a janela e uma so por request, seja qual for o\n * filtro que a tenha definido.\n */\nexport function buildQueryParams(\n filters: Record<string, string>,\n variables: Record<string, number> = {},\n): Record<string, string> {\n const params: Record<string, string> = {};\n\n for (const [key, val] of Object.entries(filters)) {\n if (val.includes('|')) {\n const [start, end] = val.split('|');\n if (start) params['f_date_start'] = start;\n if (end) params['f_date_end'] = end;\n } else {\n params[`f_${key}`] = val;\n }\n }\n\n for (const [key, val] of Object.entries(variables)) {\n params[`v_${key}`] = String(val);\n }\n\n return params;\n}\n\n/** Converte o `applied` do backend para o formato local de filtros. */\nexport function syncFiltersFromApplied(applied: Record<string, unknown>): Record<string, string> {\n const synced: Record<string, string> = {};\n for (const [id, val] of Object.entries(applied)) {\n if (val && typeof val === 'object' && 'start' in val) {\n const d = val as { start?: string; end?: string };\n synced[id] = `${d.start || ''}|${d.end || ''}`;\n } else if (Array.isArray(val)) {\n synced[id] = val.join(MULTI_VALUE_SEPARATOR);\n } else if (typeof val === 'string') {\n synced[id] = val;\n }\n }\n return synced;\n}\n","// Purpose: Hook que gerencia estado + fetch de um dashboard inteiro.\r\n// Scope: Carrega layout uma vez + render com debounce quando filtros/variaveis mudam.\r\n// Sincroniza estado local com os defaults aplicados pelo backend na 1a carga.\r\n// Public API: useDashboardData\r\n\r\nimport { useState, useEffect, useCallback, useMemo, useRef } from 'react';\r\nimport { fetchLayout, fetchRender } from '../api/fetcher';\r\nimport { buildQueryParams, syncFiltersFromApplied } from '../api/params';\r\nimport type { LayoutResponse, RenderResponse } from '../types';\r\n\r\nexport interface UseDashboardDataResult {\r\n layout: LayoutResponse | null;\r\n renderData: RenderResponse | null;\r\n loading: boolean;\r\n error: string | null;\r\n /** Filtros selecionados (formato string por widget — date_range como \"start|end\"). */\r\n filters: Record<string, string>;\r\n /** Overrides de variaveis por widget. */\r\n variables: Record<string, number>;\r\n /** Paleta efetiva (override local substitui a do layout). */\r\n palette: string[];\r\n setFilter(widgetId: string, value: string): void;\r\n setVariable(widgetId: string, value: number): void;\r\n setPalette(colors: string[]): void;\r\n}\r\n\r\nconst DEBOUNCE_MS = 300;\r\n\r\nexport function useDashboardData(token: string): UseDashboardDataResult {\r\n const [layout, setLayout] = useState<LayoutResponse | null>(null);\r\n const [renderData, setRenderData] = useState<RenderResponse | null>(null);\r\n const [filters, setFilters] = useState<Record<string, string>>({});\r\n const [variables, setVariables] = useState<Record<string, number>>({});\r\n const [localPalette, setLocalPalette] = useState<string[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const debounceRef = useRef<ReturnType<typeof setTimeout>>();\r\n const appliedSyncedRef = useRef(false);\r\n\r\n // -------Carrega layout uma unica vez (por token)-------\r\n useEffect(() => {\r\n let cancelled = false;\r\n fetchLayout(token)\r\n .then((res) => { if (!cancelled) setLayout(res); })\r\n .catch((err: Error) => { if (!cancelled) setError(err.message); });\r\n return () => { cancelled = true; };\r\n }, [token]);\r\n\r\n // -------Render com debounce quando filtros/variaveis mudam-------\r\n useEffect(() => {\r\n if (!layout) return;\r\n if (debounceRef.current) clearTimeout(debounceRef.current);\r\n\r\n debounceRef.current = setTimeout(() => {\r\n const params = buildQueryParams(filters, variables);\r\n setLoading(true);\r\n fetchRender(token, params)\r\n .then((res) => {\r\n setRenderData(res);\r\n if (!appliedSyncedRef.current && res.applied) {\r\n appliedSyncedRef.current = true;\r\n setFilters((prev) => ({ ...syncFiltersFromApplied(res.applied), ...prev }));\r\n }\r\n setError(null);\r\n })\r\n .catch((err: Error) => setError(err.message))\r\n .finally(() => setLoading(false));\r\n }, DEBOUNCE_MS);\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current);\r\n };\r\n }, [token, layout, filters, variables]);\r\n\r\n const setFilter = useCallback((widgetId: string, value: string) => {\r\n setFilters((prev) => ({ ...prev, [widgetId]: value }));\r\n }, []);\r\n\r\n const setVariable = useCallback((widgetId: string, value: number) => {\r\n setVariables((prev) => ({ ...prev, [widgetId]: value }));\r\n }, []);\r\n\r\n const setPalette = useCallback((colors: string[]) => {\r\n setLocalPalette(colors);\r\n }, []);\r\n\r\n const palette = useMemo(\r\n () => localPalette ?? layout?.palette ?? [],\r\n [localPalette, layout],\r\n );\r\n\r\n return {\r\n layout, renderData, loading, error,\r\n filters, variables, palette,\r\n setFilter, setVariable, setPalette,\r\n };\r\n}\r\n","// Purpose: Medir o container do dashboard e projetar a geometria do grid no DOM.\n// Scope: Um unico ResizeObserver sobre a raiz (largura) e o grid (altura). A altura\n// da celula e escrita como custom property, fora do React; so a troca de\n// modo (colunas <-> empilhado) passa por estado. Tambem reporta a geometria\n// ao consumidor e avisa quando o host corta o dashboard.\n// Public API: useGridGeometry\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DashboardGeometry } from '../utils/grid';\nimport { computeCellHeight, computeCellWidth, computeStackThreshold } from '../utils/grid';\n\nexport interface UseGridGeometryOptions {\n /** Numero de colunas do layout. 0 enquanto o layout nao carregou. */\n columns: number;\n /** Proporcao largura/altura da celula. */\n cellAspect: number;\n /** Largura de container abaixo da qual empilhar. `auto` deriva do limiar natural. */\n stackBelow?: number | 'auto';\n /** Notificado quando qualquer medida do grid muda. */\n onGeometryChange?: (geometry: DashboardGeometry) => void;\n /** Desliga o aviso de corte no console. */\n silenceWarnings?: boolean;\n}\n\nexport interface UseGridGeometryResult {\n /** Ref da raiz — elemento medido e portador das custom properties. */\n rootRef: (element: HTMLDivElement | null) => void;\n /** Ref do grid — medido apenas para reportar a altura ocupada. */\n gridRef: (element: HTMLDivElement | null) => void;\n /** True quando o container e estreito demais para a grade de colunas. */\n stacked: boolean;\n}\n\nconst readInlineSize = (entry: ResizeObserverEntry): number =>\n entry.borderBoxSize?.[0]?.inlineSize ?? (entry.target as HTMLElement).offsetWidth;\n\nconst readBlockSize = (entry: ResizeObserverEntry): number =>\n entry.borderBoxSize?.[0]?.blockSize ?? (entry.target as HTMLElement).offsetHeight;\n\n/** Limiar efetivo de empilhamento. 0 desliga o modo. */\nfunction resolveStackThreshold(\n stackBelow: number | 'auto' | undefined,\n columns: number,\n aspect: number,\n): number {\n if (stackBelow === undefined) return 0;\n if (stackBelow === 'auto') return computeStackThreshold(columns, aspect);\n return Math.max(0, stackBelow);\n}\n\n/**\n * Ancestral que efetivamente recorta o elemento.\n *\n * Para na primeira caixa de rolagem: se ela rola (`auto`/`scroll`), nada acima\n * dela corta o dashboard, e o embutimento e legitimo.\n */\nfunction findClippingAncestor(element: HTMLElement): HTMLElement | null {\n let node = element.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const { overflowY } = getComputedStyle(node);\n if (overflowY !== 'visible') {\n return overflowY === 'hidden' || overflowY === 'clip' ? node : null;\n }\n node = node.parentElement;\n }\n return null;\n}\n\nexport function useGridGeometry(options: UseGridGeometryOptions): UseGridGeometryResult {\n // Latest-ref: o observer e criado uma vez e precisa enxergar os valores atuais\n // sem ser reassinado a cada render. Nunca lido durante o render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const rootElRef = useRef<HTMLDivElement | null>(null);\n const gridElRef = useRef<HTMLDivElement | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n const frameRef = useRef<number | null>(null);\n const geometryRef = useRef<DashboardGeometry | null>(null);\n const widthRef = useRef(0);\n const gridHeightRef = useRef(0);\n const stackedRef = useRef(false);\n const warnedRef = useRef(false);\n // Largura ja projetada no DOM. -1 forca a proxima projecao (troca de layout).\n const appliedWidthRef = useRef(-1);\n\n const [stacked, setStacked] = useState(false);\n\n const warnIfClipped = useCallback((geometry: DashboardGeometry) => {\n const grid = gridElRef.current;\n if (warnedRef.current || optionsRef.current.silenceWarnings || !grid) return;\n\n const ancestor = findClippingAncestor(grid);\n if (!ancestor || ancestor.clientHeight >= geometry.gridHeight) return;\n\n warnedRef.current = true;\n console.warn(\n '[@actionexec/dashboards] O dashboard esta sendo cortado: o container precisa de '\n + `${Math.ceil(geometry.gridHeight)}px de altura, mas o ancestral com overflow oculto tem `\n + `${ancestor.clientHeight}px. A altura do dashboard varia com a largura — use a prop `\n + 'onGeometryChange para dimensionar o container, ou troque o overflow para auto. '\n + 'Passe silenceWarnings para desligar este aviso.',\n );\n }, []);\n\n const emit = useCallback(() => {\n if (!rootElRef.current) return;\n\n const { columns, cellAspect } = optionsRef.current;\n // Usa a largura ja medida em vez de reler o DOM: emit roda logo apos apply\n // escrever as custom properties, e um getBoundingClientRect aqui forcaria\n // um reflow sincrono por frame de arrasto.\n const containerWidth = widthRef.current;\n const cellWidth = computeCellWidth(containerWidth, columns);\n\n const next: DashboardGeometry = {\n containerWidth,\n cellWidth,\n cellHeight: computeCellHeight(cellWidth, cellAspect),\n gridHeight: gridHeightRef.current,\n stacked: stackedRef.current,\n };\n\n const prev = geometryRef.current;\n const unchanged = prev\n && prev.containerWidth === next.containerWidth\n && prev.cellWidth === next.cellWidth\n && prev.cellHeight === next.cellHeight\n && prev.gridHeight === next.gridHeight\n && prev.stacked === next.stacked;\n if (unchanged) return;\n\n geometryRef.current = next;\n optionsRef.current.onGeometryChange?.(next);\n warnIfClipped(next);\n }, [warnIfClipped]);\n\n /**\n * Projeta a largura medida na geometria do grid.\n *\n * As custom properties sao escritas direto no no, sem passar pelo React: o\n * arrasto da janela emite uma medida por frame, e re-renderizar a arvore de\n * widgets nessa cadencia custaria caro com graficos em tela. Elas nunca\n * aparecem no objeto `style` do JSX — o React so remove chaves que ele mesmo\n * escreveu, entao o valor imperativo sobrevive aos renders seguintes.\n *\n * NUNCA chamar de dentro do callback do ResizeObserver: ver handleEntries.\n */\n const apply = useCallback((force = false) => {\n const root = rootElRef.current;\n if (!root) return;\n\n const width = widthRef.current;\n if (!force && width === appliedWidthRef.current) return;\n appliedWidthRef.current = width;\n\n const { columns, cellAspect, stackBelow } = optionsRef.current;\n const cellWidth = computeCellWidth(width, columns);\n root.style.setProperty('--dash-cell-h', `${computeCellHeight(cellWidth, cellAspect)}px`);\n\n const threshold = resolveStackThreshold(stackBelow, columns, cellAspect);\n const nextStacked = threshold > 0 && width > 0 && width < threshold;\n if (nextStacked !== stackedRef.current) {\n stackedRef.current = nextStacked;\n setStacked(nextStacked);\n }\n }, []);\n\n const cancelFrame = useCallback(() => {\n if (frameRef.current === null) return;\n cancelAnimationFrame(frameRef.current);\n // Zerar junto com o cancelamento e obrigatorio: o unico outro ponto que\n // zera e o corpo do frame, que acabou de ser cancelado. Sem isto o guard de\n // scheduleFrame veria um id obsoleto e sairia cedo para sempre.\n frameRef.current = null;\n }, []);\n\n // O observer pode disparar mais de uma vez por frame; projecao e relato sao\n // coalescidos num unico frame.\n const scheduleFrame = useCallback(() => {\n if (frameRef.current !== null) return;\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n apply();\n emit();\n });\n }, [apply, emit]);\n\n const handleEntries = useCallback((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n if (entry.target === rootElRef.current) widthRef.current = Math.round(readInlineSize(entry));\n else if (entry.target === gridElRef.current) gridHeightRef.current = readBlockSize(entry);\n }\n // Deliberadamente NAO escreve no DOM aqui. Escrever --dash-cell-h durante a\n // entrega das observacoes mudaria a altura do grid e, por tabela, a da raiz\n // (que e flex column sem altura propria). A raiz esta numa profundidade\n // menor que a ultima entregue, entao vira \"skipped observation\" e o browser\n // emite o ErrorEvent \"ResizeObserver loop completed with undelivered\n // notifications\" — que o app hospedeiro captura como erro nao tratado.\n // Adiar para o frame seguinte fecha o laco limpo.\n scheduleFrame();\n }, [scheduleFrame]);\n\n const ensureObserver = useCallback(() => {\n if (observerRef.current) return observerRef.current;\n if (typeof ResizeObserver === 'undefined') return null;\n observerRef.current = new ResizeObserver(handleEntries);\n return observerRef.current;\n }, [handleEntries]);\n\n const rootRef = useCallback((element: HTMLDivElement | null) => {\n const observer = ensureObserver();\n if (rootElRef.current) observer?.unobserve(rootElRef.current);\n rootElRef.current = element;\n if (!element) return;\n observer?.observe(element);\n // Medicao e projecao sincronas, fora do laco do observer: sem elas o\n // primeiro frame usaria o fallback do CSS em vez da celula real.\n widthRef.current = Math.round(element.getBoundingClientRect().width);\n apply(true);\n scheduleFrame();\n }, [apply, ensureObserver, scheduleFrame]);\n\n const gridRef = useCallback((element: HTMLDivElement | null) => {\n const observer = ensureObserver();\n if (gridElRef.current) observer?.unobserve(gridElRef.current);\n gridElRef.current = element;\n if (!element) {\n gridHeightRef.current = 0;\n return;\n }\n observer?.observe(element);\n gridHeightRef.current = element.getBoundingClientRect().height;\n scheduleFrame();\n }, [ensureObserver, scheduleFrame]);\n\n // O effect e o dono do ciclo de vida do observer. Deixar so as ref callbacks\n // criando e um effect destruindo seria assimetrico: o StrictMode do React 18\n // roda o cleanup sem reanexar refs, e a raiz ficaria sem observacao pelo resto\n // da sessao — quebrando em dev exatamente a proporcao que o hook mantem.\n // observe() e idempotente, entao reobservar o que as refs ja pegaram e seguro.\n useEffect(() => {\n const observer = ensureObserver();\n if (rootElRef.current) observer?.observe(rootElRef.current);\n if (gridElRef.current) observer?.observe(gridElRef.current);\n return () => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n cancelFrame();\n };\n }, [ensureObserver, cancelFrame]);\n\n // Trocar de layout muda o numero de colunas e, com ele, toda a geometria.\n // Roda fora do laco do observer, entao a escrita sincrona aqui e segura.\n useEffect(() => {\n if (!rootElRef.current) return;\n apply(true);\n scheduleFrame();\n }, [options.columns, options.cellAspect, options.stackBelow, apply, scheduleFrame]);\n\n return { rootRef, gridRef, stacked };\n}\n","// Purpose: Moldura comum a todos os widgets — titulo e estados nao-prontos.\n// Scope: Antes cada widget desenhava o proprio titulo (h4/span, quatro classes\n// diferentes) e o proprio \"Sem dados\". Aqui ficam a marcacao e as classes\n// unicas; o widget cuida so do seu conteudo.\n// Public API: WidgetFrame, WidgetState, WidgetStateKind\n\nimport type { ReactNode } from 'react';\n\n/** Estados em que o widget mostra uma mensagem no lugar do conteudo. */\nexport type WidgetStateKind = 'empty' | 'error' | 'loading' | 'unconfigured';\n\nconst STATE_MESSAGES: Record<WidgetStateKind, string> = {\n empty: 'Sem dados',\n error: 'Não foi possível carregar',\n loading: 'Carregando...',\n unconfigured: 'Widget não configurado',\n};\n\ninterface WidgetStateProps {\n kind: WidgetStateKind;\n /** Sobrescreve a mensagem padrao do estado. */\n message?: string;\n}\n\n/** Mensagem centralizada exibida no lugar do conteudo do widget. */\nexport function WidgetState({ kind, message }: WidgetStateProps) {\n return (\n <div className={`widget__state widget__state--${kind}`} role={kind === 'error' ? 'alert' : undefined}>\n {message || STATE_MESSAGES[kind]}\n </div>\n );\n}\n\ninterface WidgetFrameProps {\n /** Sufixo da classe do widget (`kpi` -> `.widget-kpi`). */\n name: string;\n title?: string;\n /** Quando definido, substitui o conteudo pela mensagem de estado. */\n state?: WidgetStateKind;\n stateMessage?: string;\n /** Renderizado entre o titulo e o conteudo (ex: barra de abas da tabela). */\n toolbar?: ReactNode;\n children?: ReactNode;\n}\n\n/**\n * Casca padrao de um widget: mesma hierarquia visual em todos os tipos.\n *\n * O titulo sai do payload computado ou da config; widgets sem titulo apenas o\n * omitem — o conteudo ocupa a altura toda, sem espacador vazio.\n */\nexport function WidgetFrame({ name, title, state, stateMessage, toolbar, children }: WidgetFrameProps) {\n return (\n <div className={`widget widget-${name}`}>\n {title && <span className=\"widget__title\">{title}</span>}\n {toolbar}\n {state ? <WidgetState kind={state} message={stateMessage} /> : children}\n </div>\n );\n}\n","// Purpose: Leitura do bloco de comparacoes que o backend devolve.\n// Scope: O card e o gauge consomem o MESMO payload — o card le a variacao, o\n// gauge le a proporcao no arco. Este modulo guarda o formato e a regra de\n// o que aparece, para que os dois nao divirjam.\n// Public API: ComputedComparison, TREND_ARROWS, visibleComparisons\n\nexport interface ComputedComparison {\n id?: string;\n label?: string | null;\n /** `unavailable` = configurada, mas sem como resolver (ex: desvio sem filtro de data). */\n status?: string;\n display?: string;\n baseline?: number | null;\n baseline_formatted?: string | null;\n delta?: number | null;\n delta_formatted?: string | null;\n variance_pct?: number | null;\n ratio?: number | null;\n /** Numero em destaque, ja formatado pelo backend conforme `display`. */\n formatted?: string | null;\n trend?: string | null;\n sentiment?: string | null;\n}\n\nexport const TREND_ARROWS: Record<string, string> = { up: '↑', down: '↓' };\n\n/**\n * Comparacoes que o dashboard publicado mostra.\n *\n * As indisponiveis somem em vez de virar \"-\": quem ve o dashboard nao configurou\n * nada e nao tem o que fazer com o aviso. Quem configurou ve a pendencia no\n * builder, que le o mesmo `status`.\n */\nexport function visibleComparisons(raw: unknown): ComputedComparison[] {\n if (!Array.isArray(raw)) return [];\n return (raw as ComputedComparison[]).filter(\n (c) => c && c.status === 'ok' && c.formatted && c.formatted !== '-',\n );\n}\n","// Purpose: Card com valor computado + comparacoes.\n// Scope: Renderiza titulo, valor e uma linha por comparacao. Todo numero e todo\n// texto vem prontos do backend — a primeira comparacao ganha destaque, as\n// demais seguem em linha compacta.\n// Public API: KPIWidget\n\nimport { WidgetFrame } from './WidgetFrame';\nimport type { ComputedComparison } from './comparison';\nimport { TREND_ARROWS, visibleComparisons } from './comparison';\n\ninterface Props {\n data: Record<string, unknown>;\n label?: string;\n}\n\nfunction ComparisonLine({ comparison, primary }: { comparison: ComputedComparison; primary: boolean }) {\n const sentiment = comparison.sentiment ?? 'neutral';\n const arrow = TREND_ARROWS[comparison.trend ?? ''] ?? '';\n\n return (\n <div className={`widget-kpi__trend widget-kpi__trend--${sentiment}${primary ? '' : ' widget-kpi__trend--muted'}`}>\n <span className=\"widget-kpi__variance\">{arrow} {comparison.formatted}</span>\n {comparison.label && <span className=\"widget-kpi__trend-label\">{comparison.label}</span>}\n </div>\n );\n}\n\nexport function KPIWidget({ data, label }: Props) {\n const title = label || String(data.label || '');\n const formatted = String(data.formatted || '-');\n const comparisons = visibleComparisons(data.comparisons);\n\n return (\n <WidgetFrame name=\"kpi\" title={title}>\n <span className=\"widget-kpi__value\">{formatted}</span>\n {comparisons.map((comparison, i) => (\n <ComparisonLine key={comparison.id || i} comparison={comparison} primary={i === 0} />\n ))}\n </WidgetFrame>\n );\n}\n","// Purpose: Gauge widget (progresso vs meta).\n// Scope: Semicirculo SVG com percentual, valores brutos e indicador de meta batida.\n// Public API: GaugeWidget\n\nimport { WidgetFrame } from './WidgetFrame';\nimport { formatCompact } from '../utils/format';\nimport { visibleComparisons } from './comparison';\n\ninterface Props {\n data: Record<string, unknown>;\n palette: string[];\n label?: string;\n}\n\nconst COLOR_EMPTY = 'var(--bg-elevated)';\n\n// Faixas de atingimento -> cor de preenchimento do arco\nconst FILL_THRESHOLDS: [number, string][] = [\n [1, 'var(--color-success)'],\n [0.7, ''], // vazio = cor da serie 1 (destaque do dashboard)\n [0.4, 'var(--color-warning)'],\n [0, 'var(--color-error)'],\n];\n\n/** Gera path SVG de um arco semicircular (de esquerda para direita, no topo). */\nfunction arcPath(cx: number, cy: number, r: number, fraction: number): string {\n if (fraction <= 0) return '';\n if (fraction >= 1) {\n // Semicirculo completo: dois arcos de 90° (SVG nao desenha arco de exatamente 180°)\n return `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx} ${cy - r} A ${r} ${r} 0 0 1 ${cx + r} ${cy}`;\n }\n const angle = fraction * Math.PI;\n return `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx - r * Math.cos(angle)} ${cy - r * Math.sin(angle)}`;\n}\n\nexport function GaugeWidget({ data, palette, label: propLabel }: Props) {\n const title = propLabel || String(data.label || '');\n const ratio = typeof data.ratio === 'number' ? data.ratio : 0;\n const format = typeof data.format === 'string' ? data.format : undefined;\n\n // O backend ja formata valor e base na unidade do widget; o compacto so entra\n // como fallback para payloads antigos, sem os campos formatados.\n const valueFormatted = String(data.value_formatted || formatCompact(data.value, format));\n const ratioFormatted = String(data.formatted || '-');\n\n // O arco e a primeira comparacao; as demais viram texto sob ele\n const comparisons = visibleComparisons(data.comparisons);\n const [primary, ...extras] = comparisons;\n const targetFormatted = String(primary?.baseline_formatted || '-');\n const comparisonLabel = primary?.label ?? null;\n const exceeded = ratio >= 1;\n const clamped = Math.min(Math.max(ratio, 0), 1);\n\n const threshold = FILL_THRESHOLDS.find(([min]) => ratio >= min);\n const fillColor = threshold?.[1] || palette[0] || 'var(--color-info)';\n\n const cx = 50, cy = 50, r = 44, stroke = 10;\n\n return (\n <WidgetFrame name=\"gauge\" title={title}>\n <div className=\"widget-gauge__chart\">\n <svg viewBox=\"0 0 100 56\" preserveAspectRatio=\"xMidYMax meet\" role=\"img\" aria-label={`${ratioFormatted} da meta`}>\n <path d={arcPath(cx, cy, r, 1)} fill=\"none\" stroke={COLOR_EMPTY} strokeWidth={stroke} strokeLinecap=\"butt\" />\n {clamped > 0 && (\n <path d={arcPath(cx, cy, r, clamped)} fill=\"none\" stroke={fillColor} strokeWidth={stroke} strokeLinecap=\"butt\" />\n )}\n </svg>\n <div className=\"widget-gauge__center\">\n <span className=\"widget-gauge__percent\">{ratioFormatted}</span>\n <span className=\"widget-gauge__comparison\">{valueFormatted} / {targetFormatted}</span>\n {exceeded && <span className=\"widget-gauge__badge\">{comparisonLabel || 'Meta batida'}</span>}\n {!exceeded && comparisonLabel && <span className=\"widget-gauge__comparison\">{comparisonLabel}</span>}\n {extras.map((c, i) => (\n <span key={c.id || i} className=\"widget-gauge__comparison\">\n {c.formatted} {c.label}\n </span>\n ))}\n </div>\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Medida do container de um grafico.\n// Scope: Recharts precisa de width/height em pixels; o grid entrega tamanho via\n// CSS. Este hook faz a ponte com ResizeObserver. Compartilhado por chart e\n// composition — antes vivia dentro do ChartWidget.\n// Public API: useContainerSize\n\nimport { useState, useEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport function useContainerSize(ref: RefObject<HTMLDivElement | null>) {\n const [size, setSize] = useState({ width: 0, height: 0 });\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const observer = new ResizeObserver(([entry]) => {\n const { width, height } = entry.contentRect;\n // Compara arredondado: subpixel de layout nao deve disparar re-render\n setSize((prev) =>\n prev.width !== Math.floor(width) || prev.height !== Math.floor(height)\n ? { width: Math.floor(width), height: Math.floor(height) }\n : prev\n );\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [ref]);\n\n return size;\n}\n","// Purpose: Chart widget cartesiano (bar/line/area via Recharts).\r\n// Scope: Renderiza com dados pre-calculados pelo backend + tooltip tematizado.\r\n// Public API: ChartWidget\r\n\r\nimport { useRef, type ComponentType, type ReactElement } from 'react';\r\nimport {\r\n BarChart, Bar,\r\n LineChart, Line,\r\n AreaChart, Area,\r\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\r\n} from 'recharts';\r\nimport { WidgetFrame, WidgetState } from './WidgetFrame';\r\nimport { useContainerSize } from '../hooks/useContainerSize';\r\n\r\nconst AXIS_STYLE = { fontSize: 10, fill: 'var(--text-muted)' };\r\nconst GRID_STROKE = 'var(--bg-elevated)';\r\n\r\n// Tooltip segue a paleta do dashboard via CSS variables (getPaletteCssVars)\r\nconst TOOLTIP_CONTENT_STYLE = {\r\n backgroundColor: 'var(--bg-elevated)',\r\n border: '1px solid var(--bg-paper)',\r\n borderRadius: '6px',\r\n color: 'var(--text-primary)',\r\n};\r\nconst TOOLTIP_LABEL_STYLE = {\r\n color: 'var(--text-primary)',\r\n fontWeight: 600,\r\n};\r\n\r\n// Usa `tooltipLabel` (versao verbose) do data point quando presente,\r\n// fallback para o label do eixo X (compacto).\r\nfunction tooltipLabelFormatter(label: unknown, payload: readonly unknown[]): string {\r\n const first = (Array.isArray(payload) ? payload[0] : undefined) as { payload?: Record<string, unknown> } | undefined;\r\n const verbose = first?.payload?.tooltipLabel;\r\n if (typeof verbose === 'string' && verbose) return verbose;\r\n return String(label ?? '');\r\n}\r\n\r\ninterface SeriesInfo { key: string; label: string }\r\n\r\n// Componente generico para charts cartesianos (bar/line/area)\r\nfunction CartesianChart({ Chart, chartData, xKey, series, palette, renderSeries, width, height }: {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n Chart: ComponentType<any>;\r\n chartData: Record<string, unknown>[];\r\n xKey: string;\r\n series: SeriesInfo[];\r\n palette: string[];\r\n renderSeries: (s: SeriesInfo, color: string, idx: number) => ReactElement;\r\n width: number;\r\n height: number;\r\n}) {\r\n return (\r\n <Chart data={chartData} width={width} height={height}>\r\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\r\n <XAxis dataKey={xKey} tick={AXIS_STYLE} />\r\n <YAxis tick={AXIS_STYLE} />\r\n <Tooltip\r\n contentStyle={TOOLTIP_CONTENT_STYLE}\r\n labelStyle={TOOLTIP_LABEL_STYLE}\r\n labelFormatter={tooltipLabelFormatter}\r\n cursor={{ fill: 'var(--bg-paper)', opacity: 0.3 }}\r\n />\r\n {series.length > 1 && <Legend />}\r\n {series.map((s, i) => renderSeries(s, palette[i % palette.length], i))}\r\n </Chart>\r\n );\r\n}\r\n\r\ninterface Props {\r\n data: Record<string, unknown>;\r\n palette: string[];\r\n label?: string;\r\n}\r\n\r\nexport function ChartWidget({ data, palette, label: propLabel }: Props) {\r\n const chartType = String(data.chartType || 'bar');\r\n const title = propLabel || String(data.label || '');\r\n const xKey = String(data.xKey || 'label');\r\n const series = (data.series || []) as SeriesInfo[];\r\n const chartData = (data.data || []) as Record<string, unknown>[];\r\n\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const { width, height } = useContainerSize(containerRef);\r\n\r\n const renderChart = () => {\r\n if (width <= 0 || height <= 0) return null;\r\n\r\n const common = { chartData, xKey, series, palette, width, height };\r\n\r\n if (chartType === 'line') {\r\n return (\r\n <CartesianChart {...common} Chart={LineChart} renderSeries={(s, color) => (\r\n <Line key={s.key} type=\"monotone\" dataKey={s.key} name={s.label}\r\n stroke={color} strokeWidth={2} dot={chartData.length <= 31} />\r\n )} />\r\n );\r\n }\r\n\r\n if (chartType === 'area') {\r\n return (\r\n <CartesianChart {...common} Chart={AreaChart} renderSeries={(s, color) => (\r\n <Area key={s.key} type=\"monotone\" dataKey={s.key} name={s.label}\r\n fill={color} stroke={color} fillOpacity={0.3} />\r\n )} />\r\n );\r\n }\r\n\r\n return (\r\n <CartesianChart {...common} Chart={BarChart} renderSeries={(s, color) => (\r\n <Bar key={s.key} dataKey={s.key} name={s.label}\r\n fill={color} radius={[3, 3, 0, 0]} />\r\n )} />\r\n );\r\n };\r\n\r\n return (\r\n <WidgetFrame name=\"chart\" title={title}>\r\n {/* Container sempre montado: mantem o ResizeObserver atado ao mesmo elemento\r\n mesmo no estado vazio, evitando que o grafico nao remonte ao voltar dados. */}\r\n <div ref={containerRef} className=\"widget-chart__container\">\r\n {chartData.length === 0 ? <WidgetState kind=\"empty\" /> : renderChart()}\r\n </div>\r\n </WidgetFrame>\r\n );\r\n}\r\n","// Purpose: Widget de composicao — reparte uma medida entre categorias.\n// Scope: Dois desenhos sobre o mesmo dado: pizza (partes de um todo) e ponte\n// (caminho de um ponto a outro). O servidor ja manda cada barra posicionada\n// (`base` onde comeca, `span` o quanto ocupa), entao aqui nao ha conta de\n// acumulado — so escolha de cor e traco.\n// Public API: CompositionWidget\n\nimport { useRef } from 'react';\nimport {\n BarChart, Bar, Cell,\n PieChart, Pie,\n XAxis, YAxis, CartesianGrid, Tooltip,\n} from 'recharts';\nimport { WidgetFrame, WidgetState } from './WidgetFrame';\nimport { useContainerSize } from '../hooks/useContainerSize';\nimport { formatCompact } from '../utils/format';\n\nconst AXIS_STYLE = { fontSize: 10, fill: 'var(--text-muted)' };\nconst GRID_STROKE = 'var(--bg-elevated)';\nconst TOOLTIP_CURSOR = { fill: 'var(--bg-paper)', opacity: 0.3 };\n\n/** Uma barra/fatia ja posicionada pelo servidor. */\ninterface CompositionBar {\n label: string;\n kind: 'slice' | 'anchor' | 'delta' | 'residual';\n value: number;\n base: number;\n span: number;\n formatted: string;\n}\n\ninterface Props {\n data: Record<string, unknown>;\n palette: string[];\n label?: string;\n}\n\n/**\n * Cor por papel da barra, nao por posicao: ancora e o patamar, delta positivo\n * soma, delta negativo subtrai, e o residuo e o que os dados nao explicam.\n */\nfunction barColor(bar: CompositionBar): string {\n if (bar.kind === 'anchor') return 'var(--color-accent)';\n if (bar.kind === 'residual') return 'var(--color-warning)';\n return bar.value < 0 ? 'var(--color-error)' : 'var(--color-success)';\n}\n\ninterface TooltipProps {\n active?: boolean;\n payload?: { payload?: CompositionBar }[];\n}\n\n/**\n * Hover unico da pizza e da ponte: rotulo em negrito e, embaixo, o valor\n * formatado pelo servidor.\n *\n * O padrao do Recharts lista uma linha por serie — na ponte sao duas (`base`\n * invisivel e `span`), o que repetia a mesma categoria e mostrava a extensao da\n * barra em vez do valor. Lendo o `payload` da barra tocada, as duas formas caem\n * na mesma leitura e o valor aparece sempre.\n */\nfunction CompositionTooltip({ active, payload }: TooltipProps) {\n const bar = active ? payload?.[0]?.payload : undefined;\n if (!bar) return null;\n\n return (\n <div className=\"widget-composition__tooltip\">\n <span className=\"widget-composition__tooltip-label\">{bar.label}</span>\n <span className=\"widget-composition__tooltip-value\">{bar.formatted}</span>\n </div>\n );\n}\n\nexport function CompositionWidget({ data, palette, label: propLabel }: Props) {\n const title = propLabel || String(data.label || '');\n const display = String(data.display || 'pie');\n const bars = (data.data || []) as CompositionBar[];\n const format = typeof data.format === 'string' ? data.format : undefined;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const { width, height } = useContainerSize(containerRef);\n\n const renderBridge = () => (\n <BarChart data={bars} width={width} height={height}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis dataKey=\"label\" tick={AXIS_STYLE} interval={0} />\n <YAxis tick={AXIS_STYLE} tickFormatter={(v) => formatCompact(v, format)} />\n <Tooltip content={<CompositionTooltip />} cursor={TOOLTIP_CURSOR} />\n {/* A primeira barra so eleva a segunda ate `base`: e o truque que faz a\n barra flutuar sem componente dedicado. */}\n <Bar dataKey=\"base\" stackId=\"bridge\" fill=\"none\" fillOpacity={0} isAnimationActive={false} />\n <Bar dataKey=\"span\" stackId=\"bridge\" radius={[3, 3, 0, 0]}>\n {bars.map((bar, i) => <Cell key={i} fill={barColor(bar)} />)}\n </Bar>\n </BarChart>\n );\n\n const renderPie = () => (\n <PieChart width={width} height={height}>\n <Pie\n data={bars}\n dataKey=\"value\"\n nameKey=\"label\"\n cx=\"50%\" cy=\"50%\" outerRadius=\"75%\"\n label={({ name, percent }: { name: string; percent: number }) =>\n `${name}: ${(percent * 100).toFixed(0)}%`\n }\n labelLine={false}\n >\n {bars.map((_, i) => <Cell key={i} fill={palette[i % palette.length]} />)}\n </Pie>\n <Tooltip content={<CompositionTooltip />} />\n </PieChart>\n );\n\n return (\n <WidgetFrame name=\"composition\" title={title}>\n {/* Container sempre montado: mantem o ResizeObserver atado ao mesmo elemento\n mesmo no estado vazio, evitando que o grafico nao remonte ao voltar dados. */}\n <div ref={containerRef} className=\"widget-composition__container\">\n {bars.length === 0 || width <= 0 || height <= 0\n ? <WidgetState kind=\"empty\" />\n : (display === 'bridge' ? renderBridge() : renderPie())}\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Widget de tabela — mostra linhas x colunas do dataset.\n// Scope: Renderiza data.columns (cabecalho) + data.rows (linhas), formatando cada\n// celula pelo format da coluna (via utils/format, o mesmo dos demais widgets).\n// Colore colunas de porcentagem (verde/vermelho). `data.overflow` decide o\n// que fazer com o que passa da altura: rolar ou cortar.\n// Public API: TableWidget\n\nimport { useRef } from 'react';\nimport { WidgetFrame } from './WidgetFrame';\nimport { useContainerSize } from '../hooks/useContainerSize';\nimport { formatValue, isNumericFormat } from '../utils/format';\n\ninterface TableColumn {\n key: string;\n label?: string;\n format?: string;\n}\n\ninterface Props {\n data: Record<string, unknown>;\n label?: string;\n}\n\n/** Classe de tendencia para colunas percentuais (positivo verde, negativo vermelho). */\nfunction trendClass(value: unknown, format?: string): string {\n if (format !== 'percentage') return '';\n const n = Number(value);\n if (Number.isNaN(n) || n === 0) return '';\n return n > 0 ? ' widget-table__td--up' : ' widget-table__td--down';\n}\n\n/**\n * Quantas linhas cabem inteiras na altura disponivel.\n *\n * A altura vem de uma linha ja desenhada, e nao de uma constante: a fonte da\n * tabela escala com o container. Mede a PRIMEIRA linha em vez da altura total do\n * corpo — o total encolhe assim que o corte acontece, e dividi-lo pelo numero\n * de linhas daria uma altura cada vez menor a cada medida.\n *\n * Sem medida ainda (primeiro render), devolve todas: cortar antes de medir\n * faria linhas piscarem na tela.\n */\nfunction fittingRows(total: number, availableHeight: number, head: HTMLElement | null, firstRow: Element | null): number {\n const rowHeight = (firstRow as HTMLElement | null)?.offsetHeight ?? 0;\n if (total === 0 || availableHeight <= 0 || rowHeight <= 0) return total;\n\n const fits = Math.floor((availableHeight - (head?.offsetHeight ?? 0)) / rowHeight);\n return Math.max(0, Math.min(total, fits));\n}\n\nexport function TableWidget({ data, label }: Props) {\n const columns = (data.columns as TableColumn[]) || [];\n const rows = (data.rows as Record<string, unknown>[]) || [];\n const clip = data.overflow === 'clip';\n // A numeracao e posicional: acompanha a ordem em que a linha e desenhada, e\n // por isso e contada aqui em vez de vir como coluna de dado.\n const numbered = data.indexColumn === true;\n const title = label || String(data.label || '');\n\n const containerRef = useRef<HTMLDivElement>(null);\n const headRef = useRef<HTMLTableSectionElement>(null);\n const bodyRef = useRef<HTMLTableSectionElement>(null);\n const { height } = useContainerSize(containerRef);\n\n const visible = clip\n ? rows.slice(0, fittingRows(\n rows.length, height, headRef.current, bodyRef.current?.firstElementChild ?? null,\n ))\n : rows;\n\n if (columns.length === 0) {\n return (\n <WidgetFrame\n name=\"table\"\n title={title}\n state=\"unconfigured\"\n stateMessage=\"Configure as colunas da tabela.\"\n />\n );\n }\n\n return (\n <WidgetFrame name=\"table\" title={title}>\n <div\n ref={containerRef}\n className={`widget-table__scroll${clip ? ' widget-table__scroll--clip' : ''}`}\n >\n {/* `--fill` estica as linhas para ocupar a altura que sobra. Fica de fora\n quando o corte esta ativo: a linha esticada mudaria a altura que\n decide quantas cabem, e a conta oscilaria a cada medida. */}\n <table\n className={`widget-table__table${clip && visible.length < rows.length ? '' : ' widget-table__table--fill'}`}\n >\n <thead ref={headRef}>\n <tr>\n {numbered && <th className=\"widget-table__th widget-table__th--index\">#</th>}\n {columns.map((c) => (\n <th\n key={c.key}\n className={`widget-table__th${isNumericFormat(c.format) ? ' widget-table__th--num' : ''}`}\n >\n {c.label || c.key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody ref={bodyRef}>\n {visible.length === 0 ? (\n <tr>\n <td\n className=\"widget-table__td widget-table__td--placeholder\"\n colSpan={columns.length + (numbered ? 1 : 0)}\n >\n Sem dados\n </td>\n </tr>\n ) : (\n visible.map((row, i) => (\n <tr key={i}>\n {numbered && <td className=\"widget-table__td widget-table__td--index\">{i + 1}</td>}\n {columns.map((c) => {\n const raw = row[c.key];\n const numeric = isNumericFormat(c.format) ? ' widget-table__td--num' : '';\n return (\n <td key={c.key} className={`widget-table__td${numeric}${trendClass(raw, c.format)}`}>\n {formatValue(raw, c.format)}\n </td>\n );\n })}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Widget de filtro interativo no grid (date_range, select, multi_select).\r\n// Scope: Modos temporais (range, monthly, weekly, yearly), select unico, multi-select.\r\n// Modo categorico padrao (select/checkbox) ou lista com busca (searchable).\r\n// Public API: FilterWidget\r\n\r\nimport type { FilterConfig, DateFilterMode } from '../types';\r\nimport {\r\n MONTH_NAMES_SHORT, getFullYearRange, getMonthRange,\r\n getMonthWeeks, parseMonthWeekFromRange,\r\n parseYearFromRange, parseMonthFromRange, getYearRange,\r\n} from '../utils/date';\r\nimport { DashboardDatePicker } from '../components/DashboardDatePicker';\r\nimport { SearchableSelect } from '../components/SearchableSelect';\r\nimport { MULTI_VALUE_SEPARATOR } from '../types';\r\n\r\ninterface Props {\r\n config: FilterConfig;\r\n value: string;\r\n options?: string[];\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}\r\n\r\n// -------Componente principal-------\r\n\r\nexport function FilterWidget({ config, value, options = [], dateBounds, onChange }: Props) {\r\n const filterType = config.filterType || 'select';\r\n const label = config.label || 'Filtro';\r\n const dateMode: DateFilterMode = config.dateFilterMode || 'range';\r\n\r\n return (\r\n <div className=\"widget-filter\">\r\n <label className=\"widget-filter__label\">{label}</label>\r\n {filterType === 'date_range' ? (\r\n dateMode === 'yearly' ? (\r\n <YearlyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : dateMode === 'monthly' ? (\r\n <MonthlyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : dateMode === 'weekly' ? (\r\n <WeeklyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : (\r\n <DateRangeFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n )\r\n ) : (\r\n <SelectFilter\r\n value={value}\r\n options={options}\r\n multi={filterType === 'multi_select'}\r\n searchable={config.searchable || false}\r\n onChange={onChange}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// -------DateRangeFilter (modo range puro)-------\r\n\r\nfunction DateRangeFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start, end] = value ? value.split('|') : ['', ''];\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--stacked\">\r\n <DashboardDatePicker\r\n value={start}\r\n minIso={dateBounds?.min}\r\n maxIso={end || dateBounds?.max}\r\n selectsStart\r\n startIso={start}\r\n endIso={end}\r\n placeholder=\"Data inicial\"\r\n onChange={(iso) => onChange(`${iso}|${end}`)}\r\n />\r\n <DashboardDatePicker\r\n value={end}\r\n minIso={start || dateBounds?.min}\r\n maxIso={dateBounds?.max}\r\n selectsEnd\r\n startIso={start}\r\n endIso={end}\r\n placeholder=\"Data final\"\r\n onChange={(iso) => onChange(`${start}|${iso}`)}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\n// -------YearlyFilter (modo anual)-------\r\n\r\nfunction YearlyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseYearFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const years = getYearRange(dateBounds);\r\n\r\n const handleYearChange = (year: number) => {\r\n const yr = getFullYearRange(year);\r\n onChange(`${yr.start}|${yr.end}`);\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--year\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => handleYearChange(parseInt(e.target.value))}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------MonthlyFilter (modo mensal)-------\r\n\r\nfunction MonthlyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseMonthFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const selectedMonth = parsed?.month ?? (now.getMonth() + 1);\r\n const years = getYearRange(dateBounds);\r\n\r\n const handleMonthChange = (year: number, month: number) => {\r\n const range = getMonthRange(year, month);\r\n onChange(`${range.start}|${range.end}`);\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--month\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedMonth}\r\n onChange={(e) => handleMonthChange(selectedYear, parseInt(e.target.value))}\r\n >\r\n {MONTH_NAMES_SHORT.map((name, i) => (\r\n <option key={i + 1} value={i + 1}>{name}</option>\r\n ))}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => handleMonthChange(parseInt(e.target.value), selectedMonth)}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------WeeklyFilter (modo semanal)-------\r\n\r\nfunction WeeklyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseMonthFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const selectedMonth = parsed?.month ?? (now.getMonth() + 1);\r\n const years = getYearRange(dateBounds);\r\n\r\n const monthWeeks = getMonthWeeks(selectedYear, selectedMonth);\r\n const selectedWeekIdx = parseMonthWeekFromRange(start, selectedYear, selectedMonth) || 1;\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--week\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => {\r\n const y = parseInt(e.target.value);\r\n const weeks = getMonthWeeks(y, selectedMonth);\r\n const w = weeks[0];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedMonth}\r\n onChange={(e) => {\r\n const m = parseInt(e.target.value);\r\n const weeks = getMonthWeeks(selectedYear, m);\r\n const w = weeks[0];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {MONTH_NAMES_SHORT.map((name, i) => (\r\n <option key={i + 1} value={i + 1}>{name}</option>\r\n ))}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedWeekIdx}\r\n onChange={(e) => {\r\n const w = monthWeeks[parseInt(e.target.value) - 1];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {monthWeeks.map((w) => (\r\n <option key={w.index} value={w.index}>{w.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------SelectFilter (categorico)-------\r\n\r\nfunction SelectFilter({ value, options, multi, searchable, onChange }: {\r\n value: string;\r\n options: string[];\r\n multi: boolean;\r\n searchable: boolean;\r\n onChange: (value: string) => void;\r\n}) {\r\n // Modo lista com busca: unico componente cobre selecao unica e multipla\r\n if (searchable) {\r\n return (\r\n <SearchableSelect\r\n value={value}\r\n options={options}\r\n multi={multi}\r\n onChange={onChange}\r\n />\r\n );\r\n }\r\n\r\n if (multi) {\r\n const selected = value ? value.split(MULTI_VALUE_SEPARATOR) : [];\r\n const toggle = (opt: string) => {\r\n const next = selected.includes(opt)\r\n ? selected.filter((s) => s !== opt)\r\n : [...selected, opt];\r\n onChange(next.join(MULTI_VALUE_SEPARATOR));\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__multi\">\r\n {/* Limpar filtro: desmarca tudo. Vazio = todos selecionados (sem filtro). */}\r\n {selected.length > 0 && (\r\n <button\r\n type=\"button\"\r\n className=\"widget-filter__multi-clear\"\r\n onClick={() => onChange('')}\r\n >\r\n Limpar filtro\r\n </button>\r\n )}\r\n {options.map((opt) => (\r\n <label key={opt} className=\"widget-filter__multi-option\">\r\n <input\r\n type=\"checkbox\"\r\n checked={selected.includes(opt)}\r\n onChange={() => toggle(opt)}\r\n />\r\n {opt}\r\n </label>\r\n ))}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <select\r\n className=\"widget-filter__select\"\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n >\r\n <option value=\"\">Todos</option>\r\n {options.map((opt) => (\r\n <option key={opt} value={opt}>{opt}</option>\r\n ))}\r\n </select>\r\n );\r\n}\r\n","// Purpose: Widget de variavel editavel no grid (what-if scenarios).\n// Scope: Input numerico com label, formato e opcao de bloqueio.\n// Public API: VariableWidget\n\nimport type { VariableConfig } from '../types';\n\ninterface Props {\n config: VariableConfig;\n value: number;\n onChange: (value: number) => void;\n}\n\nconst FORMAT_SUFFIX: Record<string, string> = {\n currency: 'R$',\n percentage: '%',\n};\n\nexport function VariableWidget({ config, value, onChange }: Props) {\n const label = config.label || 'Variavel';\n const locked = config.locked || false;\n const fmt = config.variableFormat || 'number';\n const suffix = FORMAT_SUFFIX[fmt] || '';\n\n return (\n <div className={`widget-variable ${locked ? 'widget-variable--locked' : ''}`}>\n <label className=\"widget-variable__label\">{label}</label>\n <div className=\"widget-variable__input-wrapper\">\n <input\n className=\"widget-variable__input\"\n type=\"number\"\n value={value}\n onChange={(e) => onChange(parseFloat(e.target.value) || 0)}\n disabled={locked}\n step={fmt === 'integer' ? 1 : 0.01}\n />\n {suffix && <span className=\"widget-variable__suffix\">{suffix}</span>}\n </div>\n {locked && <span className=\"widget-variable__lock-icon\" title=\"Bloqueado\">🔒</span>}\n </div>\n );\n}\n","// Purpose: Widget de paleta de cores editavel no grid.\n// Scope: Permite ao usuario do dashboard trocar a paleta em runtime. Respeita bloqueio.\n// Public API: ColorPaletteWidget\n\nimport type { PaletteConfig } from '../types';\nimport { ColorPaletteSelector } from '../components/ColorPaletteSelector';\n\ninterface Props {\n config: PaletteConfig;\n palette: string[];\n onChange: (colors: string[]) => void;\n}\n\nexport function ColorPaletteWidget({ config, palette, onChange }: Props) {\n const label = config.label || 'Cores';\n const locked = config.locked || false;\n\n return (\n <div className={`widget-palette ${locked ? 'widget-palette--locked' : ''}`}>\n <label className=\"widget-palette__label\">{label}</label>\n <ColorPaletteSelector selected={palette} onSelect={onChange} customMode disabled={locked} />\n {locked && <span className=\"widget-palette__lock-icon\" title=\"Bloqueado\">🔒</span>}\n </div>\n );\n}\n","// Purpose: Dispatch de rendering por tipo de widget (dados + controle).\r\n// Scope: Recebe computed data e/ou config, renderiza widget correto.\r\n// Public API: WidgetRenderer\r\n\r\nimport type { WidgetType, AnyWidgetConfig, FilterConfig, VariableConfig, PaletteConfig } from '../types';\r\nimport { getSeries } from '../palettes';\r\nimport { KPIWidget } from './KPIWidget';\r\nimport { GaugeWidget } from './GaugeWidget';\r\nimport { ChartWidget } from './ChartWidget';\r\nimport { CompositionWidget } from './CompositionWidget';\r\nimport { TableWidget } from './TableWidget';\r\nimport { FilterWidget } from './FilterWidget';\r\nimport { VariableWidget } from './VariableWidget';\r\nimport { ColorPaletteWidget } from './ColorPaletteWidget';\r\nimport { WidgetFrame } from './WidgetFrame';\r\n\r\n// Codigos de erro do backend -> mensagem para o leitor do dashboard.\r\n// Codigo desconhecido cai na mensagem padrao de WidgetState.\r\nconst ERROR_MESSAGES: Record<string, string> = {\r\n failed_to_compute: 'Não foi possível calcular este widget',\r\n};\r\n\r\ninterface Props {\r\n type: WidgetType;\r\n computed: Record<string, unknown>;\r\n palette: string[];\r\n // Control widget props (opcionais)\r\n config?: AnyWidgetConfig;\r\n filterValue?: string;\r\n filterOptions?: string[];\r\n dateBounds?: { min: string; max: string } | null;\r\n onFilterChange?: (value: string) => void;\r\n variableValue?: number;\r\n onVariableChange?: (value: number) => void;\r\n onPaletteChange?: (colors: string[]) => void;\r\n}\r\n\r\nexport function WidgetRenderer({\r\n type, computed, palette, config,\r\n filterValue, filterOptions, dateBounds, onFilterChange,\r\n variableValue, onVariableChange,\r\n onPaletteChange,\r\n}: Props) {\r\n if (computed.error) {\r\n // O backend devolve um codigo tecnico (ex: \"failed_to_compute\") e loga o\r\n // detalhe server-side. Ao leitor do dashboard vai uma mensagem em pt-BR.\r\n return (\r\n <WidgetFrame\r\n name={type.replace('_', '-')}\r\n title={config?.label}\r\n state=\"error\"\r\n stateMessage={ERROR_MESSAGES[String(computed.error)]}\r\n />\r\n );\r\n }\r\n\r\n // Widgets de dados usam apenas as cores de series (5 primeiras).\r\n // UI colors sao aplicadas via CSS vars no grid container.\r\n const seriesColors = getSeries(palette);\r\n\r\n switch (type) {\r\n case 'kpi_card':\r\n return <KPIWidget data={computed} label={config?.label} />;\r\n case 'gauge':\r\n return <GaugeWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'chart':\r\n return <ChartWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'composition':\r\n return <CompositionWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'table':\r\n return <TableWidget data={computed} label={config?.label} />;\r\n case 'filter':\r\n return config && onFilterChange ? (\r\n <FilterWidget\r\n config={config as FilterConfig}\r\n value={filterValue || ''}\r\n options={filterOptions}\r\n dateBounds={dateBounds}\r\n onChange={onFilterChange}\r\n />\r\n ) : null;\r\n case 'variable': {\r\n const vc = config as VariableConfig | undefined;\r\n return vc && onVariableChange ? (\r\n <VariableWidget\r\n config={vc}\r\n value={variableValue ?? vc.variableValue ?? 0}\r\n onChange={onVariableChange}\r\n />\r\n ) : null;\r\n }\r\n case 'color_palette':\r\n return config && onPaletteChange ? (\r\n <ColorPaletteWidget\r\n config={config as PaletteConfig}\r\n palette={palette}\r\n onChange={onPaletteChange}\r\n />\r\n ) : null;\r\n default:\r\n return <WidgetFrame name=\"unknown\" state=\"unconfigured\" />;\r\n }\r\n}\r\n","// Purpose: Componente top-level que renderiza um dashboard completo.\n// Scope: Busca layout + render da API Action com o token, aplica paleta como CSS vars,\n// renderiza grid com widgets interativos (filtros + variaveis + paleta).\n// Public API: Dashboard, DashboardProps\n\nimport { useMemo } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport { useDashboardData } from './hooks/useDashboardData';\nimport { useGridGeometry } from './hooks/useGridGeometry';\nimport { WidgetRenderer } from './widgets/WidgetRenderer';\nimport { getPaletteCssVars } from './palettes';\nimport { CONTROL_WIDGET_SET } from './types';\nimport type { WidgetDefinition } from './types';\nimport type { DashboardGeometry } from './utils/grid';\nimport {\n CELL_ASPECT, GRID_GAP_PX, GRID_PADDING_PX, MIN_CELL_HEIGHT_PX,\n computeGridHeight, computeWidgetAspect,\n} from './utils/grid';\n\nexport interface DashboardProps {\n /** Token Bearer de acesso ao dashboard. */\n token: string;\n /**\n * Proporcao largura/altura da celula do grid. Default 1 (celula quadrada).\n *\n * A largura da celula vem da largura do container dividida pelo numero de\n * colunas do layout; a altura e derivada desta proporcao. E o que mantem o\n * dashboard com a mesma forma em qualquer aplicacao que o embuta.\n */\n cellAspect?: number;\n /**\n * Largura de container, em px, abaixo da qual os widgets sao empilhados em\n * coluna unica, cada um preservando a propria proporcao. `'auto'` usa o\n * limiar natural do layout — o ponto em que a celula ficaria estreita demais\n * e a proporcao ja nao seria respeitada. Ausente: nunca empilha.\n */\n stackBelow?: number | 'auto';\n /**\n * Notificado a cada mudanca de geometria. A altura do dashboard varia com a\n * largura, entao um host de altura fixa deve usar `gridHeight` para se\n * dimensionar.\n */\n onGeometryChange?: (geometry: DashboardGeometry) => void;\n /** Desliga o aviso de corte emitido no console. */\n silenceWarnings?: boolean;\n /** Classe CSS adicional no container raiz. */\n className?: string;\n}\n\n/** Ordem de leitura — usada apenas ao empilhar, onde a ordem no DOM e a ordem visual. */\nconst byReadingOrder = (a: WidgetDefinition, b: WidgetDefinition) =>\n a.grid.y - b.grid.y || a.grid.x - b.grid.x;\n\nexport function Dashboard({\n token,\n cellAspect = CELL_ASPECT,\n stackBelow,\n onGeometryChange,\n silenceWarnings,\n className,\n}: DashboardProps) {\n const {\n layout, renderData, loading, error,\n filters, variables, palette,\n setFilter, setVariable, setPalette,\n } = useDashboardData(token);\n\n // Mede a raiz, nao o grid: a raiz existe desde o primeiro render (estados de\n // carga e erro tambem a usam), entao a largura ja e conhecida quando o grid\n // aparece — sem frame intermediario com a celula no tamanho minimo.\n const { rootRef, gridRef, stacked } = useGridGeometry({\n columns: layout?.gridColumns ?? 0,\n cellAspect,\n stackBelow,\n onGeometryChange,\n silenceWarnings,\n });\n\n const widgets = useMemo(() => {\n const list = layout?.widgets ?? [];\n return stacked ? [...list].sort(byReadingOrder) : list;\n }, [layout?.widgets, stacked]);\n\n // Estaticas, mas derivadas de utils/grid: mante-las fora do CSS garante que a\n // geometria tenha uma fonte so. O React as escreve uma vez e nao volta mais.\n const rootStyle = {\n '--dash-gap': `${GRID_GAP_PX}px`,\n '--dash-pad': `${GRID_PADDING_PX}px`,\n } as CSSProperties;\n\n const rootClass = ['preview-tab', className].filter(Boolean).join(' ');\n\n let body: ReactNode;\n\n if (error && !layout) {\n body = <div className=\"preview-tab__error\">{error}</div>;\n } else if (!layout) {\n body = <div className=\"preview-tab__loading\">Carregando dashboard...</div>;\n } else if (layout.widgets.length === 0) {\n body = <div className=\"preview-tab__empty\">Este dashboard nao possui widgets.</div>;\n } else {\n const widgetsData = renderData?.widgets ?? {};\n const dateBounds = renderData?.date_bounds ?? null;\n\n // --dash-cell-h e escrita na raiz pelo useGridGeometry, fora do React.\n // Aqui ficam apenas as medidas que mudam com o layout, nao com o resize.\n const gridStyle = {\n '--dash-cols': layout.gridColumns,\n '--dash-rows': layout.gridRows,\n ...getPaletteCssVars(palette),\n } as CSSProperties;\n\n const gridClass = ['preview-tab__grid', stacked && 'preview-tab__grid--stacked']\n .filter(Boolean).join(' ');\n\n body = (\n <>\n {error && !renderData && <div className=\"preview-tab__error\">{error}</div>}\n\n {renderData && (\n <div className={gridClass} style={gridStyle} ref={gridRef}>\n {widgets.map((widget) => {\n const isControl = CONTROL_WIDGET_SET.has(widget.type);\n const computed = widgetsData[widget.id];\n\n // Empilhado, a proporcao do widget vira aspect-ratio em CSS puro:\n // nao depende de medicao, entao o resize nao re-renderiza nada.\n // O piso evita que um widget largo e baixo (ex.: 30x2) vire uma\n // faixa de poucos pixels ao ocupar a largura inteira.\n const widgetStyle: CSSProperties = stacked\n ? {\n gridColumn: 1,\n aspectRatio: `${computeWidgetAspect(widget.grid.w, widget.grid.h, cellAspect)}`,\n minHeight: `${computeGridHeight(widget.grid.h, MIN_CELL_HEIGHT_PX, GRID_GAP_PX, 0)}px`,\n }\n : {\n gridColumn: `${widget.grid.x + 1} / span ${widget.grid.w}`,\n gridRow: `${widget.grid.y + 1} / span ${widget.grid.h}`,\n };\n\n const variableValue = widget.type === 'variable'\n ? variables[widget.id] ?? (computed?.value as number) ?? widget.config.variableValue ?? 0\n : undefined;\n\n return (\n <div\n key={widget.id}\n className={`preview-tab__widget ${isControl ? 'preview-tab__widget--control' : ''}`}\n style={widgetStyle}\n >\n {isControl || computed ? (\n <WidgetRenderer\n type={widget.type}\n computed={computed || {}}\n palette={palette}\n config={widget.config}\n filterValue={filters[widget.id] || ''}\n filterOptions={\n // Estruturais: vem do /layout (cacheavel), nao do /render —\n // recalcula-los a cada render custaria um DISTINCT por filtro.\n widget.type === 'filter' ? widget.config.availableValues ?? [] : []\n }\n dateBounds={dateBounds}\n onFilterChange={(val) => setFilter(widget.id, val)}\n variableValue={variableValue}\n onVariableChange={(val) => setVariable(widget.id, val)}\n onPaletteChange={setPalette}\n />\n ) : (\n <div className=\"preview-tab__widget-loading\">\n {loading ? 'Carregando...' : 'Sem dados'}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {loading && renderData && (\n <div className=\"preview-tab__recalculating\">Atualizando...</div>\n )}\n </>\n );\n }\n\n return <div className={rootClass} style={rootStyle} ref={rootRef}>{body}</div>;\n}\n","// Purpose: Entrega de arquivo ao usuario a partir de um blob em memoria.\n// Scope: Usado pelo download de PDF do demonstrativo, cujo conteudo chega por\n// fetch autenticado — nao ha URL publica para apontar um link.\n// Public API: downloadBlob, toFileName\n\n/** Dispara o download de um blob com o nome informado. */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n // Revogar no mesmo tick corta o download em alguns navegadores: o clique so\n // agenda a leitura da URL. Um turno de event loop basta para ela comecar.\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n// Faixa Unicode das marcas de acentuacao combinantes.\nconst COMBINING_FIRST = 0x0300;\nconst COMBINING_LAST = 0x036f;\n\n/** Remove acentuacao preservando a letra base (\"Balanço\" -> \"Balanco\"). */\nfunction stripDiacritics(text: string): string {\n // normalize('NFD') separa a letra da marca de acentuacao; sobra descartar as marcas.\n return Array.from(text.normalize('NFD'))\n .filter((char) => {\n const code = char.codePointAt(0) ?? 0;\n return code < COMBINING_FIRST || code > COMBINING_LAST;\n })\n .join('');\n}\n\n/**\n * Converte um titulo em nome de arquivo seguro.\n *\n * Acentos viram a letra base e o que nao for alfanumerico vira hifen: o nome\n * atravessa sistemas de arquivos diferentes sem depender de normalizacao do SO.\n */\nexport function toFileName(title: string, extension: string): string {\n const slug = stripDiacritics(title)\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n return `${slug || 'documento'}.${extension}`;\n}\n","// Purpose: Hook que gerencia estado + fetch de um demonstrativo inteiro.\n// Scope: Carrega o layout uma vez e recomputa o documento com debounce quando a\n// janela ou os filtros mudam. Tambem entrega o PDF, que le a MESMA janela\n// do documento na tela — o arquivo baixado nunca mostra outro recorte.\n// Public API: useStatementData\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n fetchStatementLayout, fetchStatementPdf, fetchStatementRender,\n} from '../api/fetcher';\nimport { buildQueryParams, syncFiltersFromApplied } from '../api/params';\nimport { downloadBlob, toFileName } from '../utils/download';\nimport type { StatementLayoutResponse, StatementRenderResponse } from '../types/statement';\n\nexport interface UseStatementDataResult {\n layout: StatementLayoutResponse | null;\n renderData: StatementRenderResponse | null;\n loading: boolean;\n error: string | null;\n /** Filtros selecionados (formato string por id — temporais como \"start|end\"). */\n filters: Record<string, string>;\n setFilter(filterId: string, value: string): void;\n downloadPdf(): void;\n downloading: boolean;\n}\n\nconst DEBOUNCE_MS = 300;\n\nexport function useStatementData(token: string): UseStatementDataResult {\n const [layout, setLayout] = useState<StatementLayoutResponse | null>(null);\n const [renderData, setRenderData] = useState<StatementRenderResponse | null>(null);\n const [filters, setFilters] = useState<Record<string, string>>({});\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [downloading, setDownloading] = useState(false);\n\n const debounceRef = useRef<ReturnType<typeof setTimeout>>();\n const appliedSyncedRef = useRef(false);\n\n // -------Carrega o layout uma unica vez (por token)-------\n useEffect(() => {\n let cancelled = false;\n fetchStatementLayout(token)\n .then((res) => { if (!cancelled) setLayout(res); })\n .catch((err: Error) => { if (!cancelled) setError(err.message); });\n return () => { cancelled = true; };\n }, [token]);\n\n // -------Recomputa com debounce quando a janela ou os filtros mudam-------\n useEffect(() => {\n if (!layout) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n\n debounceRef.current = setTimeout(() => {\n setLoading(true);\n fetchStatementRender(token, buildQueryParams(filters))\n .then((res) => {\n setRenderData(res);\n // Os defaults dos filtros sao resolvidos no backend; a primeira resposta\n // e a unica que pode ensina-los ao estado local.\n if (!appliedSyncedRef.current && res.applied) {\n appliedSyncedRef.current = true;\n setFilters((prev) => ({ ...syncFiltersFromApplied(res.applied), ...prev }));\n }\n setError(null);\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setLoading(false));\n }, DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [token, layout, filters]);\n\n const setFilter = useCallback((filterId: string, value: string) => {\n setFilters((prev) => ({ ...prev, [filterId]: value }));\n }, []);\n\n const downloadPdf = useCallback(() => {\n setDownloading(true);\n fetchStatementPdf(token, buildQueryParams(filters))\n .then((blob) => {\n downloadBlob(blob, toFileName(layout?.name ?? 'demonstrativo', 'pdf'));\n setError(null);\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setDownloading(false));\n }, [token, filters, layout?.name]);\n\n return {\n layout, renderData, loading, error,\n filters, setFilter,\n downloadPdf, downloading,\n };\n}\n","// Purpose: Componente top-level que renderiza um demonstrativo completo.\n// Scope: Busca layout + render da API Action com o token e desenha o documento\n// (linhas x colunas de periodo). NAO calcula nada: valores, formatacao e\n// analises chegam prontos do backend — e a mesma resposta que qualquer\n// consumidor da API recebe, entao o documento e identico em todo lugar.\n// Public API: Statement, StatementProps\n\nimport type { CSSProperties, ReactNode } from 'react';\nimport { useStatementData } from './hooks/useStatementData';\nimport { getPaletteCssVars } from './palettes';\nimport { formatValue } from './utils/format';\nimport { DashboardDatePicker } from './components/DashboardDatePicker';\nimport { SearchableSelect } from './components/SearchableSelect';\nimport { WINDOW_FILTER_ID } from './api/params';\nimport type { FilterDefinition } from './types';\nimport type { StatementComputedLine } from './types/statement';\n\nexport interface StatementProps {\n /** Token Bearer de acesso ao demonstrativo. */\n token: string;\n /**\n * Paleta de 15 cores, no mesmo formato do dashboard. Serve a quem embute os\n * dois lado a lado e quer a mesma identidade visual; ausente, usa a paleta\n * padrao da plataforma.\n */\n palette?: string[];\n /** Botao de download do PDF. Default true. */\n showDownload?: boolean;\n /** Classe CSS adicional no container raiz. */\n className?: string;\n}\n\ntype DateBounds = { min: string | null; max: string | null };\n\nconst LABEL_PADDING_PX = 8;\nconst INDENT_STEP_PX = 14;\n\n/** Recuo do rotulo conforme o nivel declarado na linha. */\nfunction labelStyle(indent: number): CSSProperties {\n return { paddingLeft: `${LABEL_PADDING_PX + indent * INDENT_STEP_PX}px` };\n}\n\n// -------Controles da barra-------\n\nfunction DateRangeControl({ label, value, bounds, onChange }: {\n label: string;\n value: string;\n bounds: DateBounds;\n onChange: (value: string) => void;\n}) {\n const [start, end] = value ? value.split('|') : ['', ''];\n\n return (\n <div className=\"stmt__filter stmt__filter--range\">\n <span className=\"stmt__filter-label\">{label}</span>\n <div className=\"stmt__filter-range\">\n <DashboardDatePicker\n value={start}\n minIso={bounds.min}\n maxIso={end || bounds.max}\n selectsStart\n startIso={start}\n endIso={end}\n placeholder=\"Início\"\n onChange={(iso) => onChange(`${iso}|${end}`)}\n />\n <DashboardDatePicker\n value={end}\n minIso={start || bounds.min}\n maxIso={bounds.max}\n selectsEnd\n startIso={start}\n endIso={end}\n placeholder=\"Fim\"\n onChange={(iso) => onChange(`${start}|${iso}`)}\n />\n </div>\n </div>\n );\n}\n\nfunction StatementFilter({ definition, value, options, bounds, onChange }: {\n definition: FilterDefinition;\n value: string;\n options: string[];\n bounds: DateBounds;\n onChange: (value: string) => void;\n}) {\n if (definition.type === 'date_range') {\n return (\n <DateRangeControl\n label={definition.label}\n value={value}\n bounds={bounds}\n onChange={onChange}\n />\n );\n }\n\n return (\n <div className=\"stmt__filter\">\n <span className=\"stmt__filter-label\">{definition.label}</span>\n <SearchableSelect\n value={value}\n options={options}\n multi={definition.type === 'multi_select'}\n onChange={onChange}\n />\n </div>\n );\n}\n\n// -------Linha do documento-------\n\nfunction StatementRow({ line, columnCount, showTotal, showVertical, showHorizontal }: {\n line: StatementComputedLine;\n columnCount: number;\n showTotal: boolean;\n showVertical: boolean;\n showHorizontal: boolean;\n}) {\n if (line.type === 'separator') {\n return (\n <tr className=\"stmt__row stmt__row--separator\">\n <td colSpan={columnCount} />\n </tr>\n );\n }\n\n if (line.type === 'header') {\n return (\n <tr className=\"stmt__row stmt__row--header\">\n <th scope=\"row\" style={labelStyle(line.style.indent)}>{line.label}</th>\n <td colSpan={columnCount - 1} />\n </tr>\n );\n }\n\n const rowClass = [\n 'stmt__row',\n `stmt__row--${line.type}`,\n line.style.bold && 'stmt__row--bold',\n ].filter(Boolean).join(' ');\n\n return (\n <tr className={rowClass}>\n <th scope=\"row\" style={labelStyle(line.style.indent)}>{line.label}</th>\n\n {line.formatted.map((text, index) => {\n const horizontal = line.horizontalAnalysis[index];\n\n return (\n <td key={index} className=\"stmt__value\">\n <span className=\"stmt__number\">{text}</span>\n\n {showVertical && line.verticalAnalysis[index] != null && (\n <span className=\"stmt__aux\" title=\"Análise vertical\">\n {formatValue(line.verticalAnalysis[index], 'percentage')}\n </span>\n )}\n\n {showHorizontal && horizontal != null && (\n <span\n className={`stmt__aux stmt__aux--${horizontal < 0 ? 'down' : 'up'}`}\n title=\"Variação sobre o período anterior\"\n >\n {formatValue(horizontal, 'percentage')}\n </span>\n )}\n </td>\n );\n })}\n\n {showTotal && (\n <td className=\"stmt__value stmt__value--total\">\n <span className=\"stmt__number\">{line.totalFormatted ?? '-'}</span>\n </td>\n )}\n </tr>\n );\n}\n\n// -------Componente principal-------\n\nexport function Statement({ token, palette, showDownload = true, className }: StatementProps) {\n const {\n layout, renderData, loading, error,\n filters, setFilter, downloadPdf, downloading,\n } = useStatementData(token);\n\n const rootClass = ['stmt', className].filter(Boolean).join(' ');\n const rootStyle = getPaletteCssVars(palette) as CSSProperties;\n\n let body: ReactNode;\n\n if (error && !layout) {\n body = <div className=\"stmt__error\">{error}</div>;\n } else if (!layout) {\n body = <div className=\"stmt__state\">Carregando demonstrativo...</div>;\n } else {\n const bounds: DateBounds = renderData?.dateBounds ?? layout.dateBounds;\n const showTotal = layout.periods.showTotal;\n\n // A janela embutida so aparece quando o documento NAO declara um filtro de\n // data: as duas escreveriam o mesmo par de parametros na request, e o autor\n // que declarou um filtro ja decidiu como o recorte se escolhe.\n const hasDeclaredWindow = layout.filters.some((f) => f.type === 'date_range');\n\n const columns = renderData?.columns ?? [];\n const lines = renderData?.lines ?? [];\n const columnCount = 1 + columns.length + (showTotal ? 1 : 0);\n const showVertical = lines.some((line) => line.verticalAnalysis.length > 0);\n const showHorizontal = lines.some((line) => line.horizontalAnalysis.length > 0);\n\n body = (\n <>\n <div className=\"stmt__toolbar\">\n {!hasDeclaredWindow && (\n <DateRangeControl\n label=\"Período\"\n value={filters[WINDOW_FILTER_ID] ?? ''}\n bounds={bounds}\n onChange={(value) => setFilter(WINDOW_FILTER_ID, value)}\n />\n )}\n\n {layout.filters.map((definition) => (\n <StatementFilter\n key={definition.id}\n definition={definition}\n value={filters[definition.id] ?? ''}\n options={layout.filterOptions[definition.id] ?? []}\n bounds={bounds}\n onChange={(value) => setFilter(definition.id, value)}\n />\n ))}\n\n <div className=\"stmt__toolbar-end\">\n <span className=\"stmt__bounds\">\n Base: {bounds.min} a {bounds.max}\n </span>\n {showDownload && (\n <button\n type=\"button\"\n className=\"stmt__download\"\n onClick={downloadPdf}\n disabled={downloading || !renderData}\n title=\"Baixar o documento em PDF\"\n >\n {downloading ? 'Gerando...' : 'Baixar PDF'}\n </button>\n )}\n </div>\n </div>\n\n {error && <div className=\"stmt__error\">{error}</div>}\n\n {!renderData ? (\n <div className=\"stmt__state\">Calculando...</div>\n ) : columns.length === 0 ? (\n <div className=\"stmt__state\">\n Nenhum período na janela selecionada.\n </div>\n ) : lines.length === 0 ? (\n <div className=\"stmt__state\">Este demonstrativo não possui linhas.</div>\n ) : (\n <div className=\"stmt__scroll\">\n <table className=\"stmt__table\">\n <thead>\n <tr>\n <th className=\"stmt__corner\" scope=\"col\">{renderData.name}</th>\n {columns.map((column) => (\n <th key={column.key} scope=\"col\" title={`${column.start} a ${column.end}`}>\n {column.label}\n </th>\n ))}\n {showTotal && (\n <th scope=\"col\" className=\"stmt__total-head\">\n {layout.periods.totalLabel}\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {lines.map((line) => (\n <StatementRow\n key={line.id}\n line={line}\n columnCount={columnCount}\n showTotal={showTotal}\n showVertical={showVertical}\n showHorizontal={showHorizontal}\n />\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {loading && renderData && (\n <div className=\"stmt__recalculating\">Atualizando...</div>\n )}\n </>\n );\n }\n\n return <div className={rootClass} style={rootStyle}>{body}</div>;\n}\n"],"names":["WINDOW_FILTER_ID","buildQueryParams","filters","variables","params","key","val","start","end","syncFiltersFromApplied","applied","synced","id","d","MULTI_VALUE_SEPARATOR","DEBOUNCE_MS","useDashboardData","token","layout","setLayout","useState","renderData","setRenderData","setFilters","setVariables","localPalette","setLocalPalette","loading","setLoading","error","setError","debounceRef","useRef","appliedSyncedRef","useEffect","cancelled","fetchLayout","res","err","fetchRender","prev","setFilter","useCallback","widgetId","value","setVariable","setPalette","colors","palette","useMemo","readInlineSize","entry","_b","_a","readBlockSize","resolveStackThreshold","stackBelow","columns","aspect","computeStackThreshold","findClippingAncestor","element","node","overflowY","useGridGeometry","options","optionsRef","rootElRef","gridElRef","observerRef","frameRef","geometryRef","widthRef","gridHeightRef","stackedRef","warnedRef","appliedWidthRef","stacked","setStacked","warnIfClipped","geometry","grid","ancestor","emit","cellAspect","containerWidth","cellWidth","computeCellWidth","next","computeCellHeight","apply","force","root","width","threshold","nextStacked","cancelFrame","scheduleFrame","handleEntries","entries","ensureObserver","rootRef","observer","gridRef","STATE_MESSAGES","WidgetState","kind","message","jsx","WidgetFrame","name","title","state","stateMessage","toolbar","children","jsxs","TREND_ARROWS","visibleComparisons","raw","c","ComparisonLine","comparison","primary","sentiment","arrow","KPIWidget","data","label","formatted","comparisons","i","COLOR_EMPTY","FILL_THRESHOLDS","arcPath","cx","cy","r","fraction","angle","GaugeWidget","propLabel","ratio","format","valueFormatted","formatCompact","ratioFormatted","extras","targetFormatted","comparisonLabel","exceeded","clamped","min","fillColor","stroke","useContainerSize","ref","size","setSize","el","height","AXIS_STYLE","GRID_STROKE","TOOLTIP_CONTENT_STYLE","TOOLTIP_LABEL_STYLE","tooltipLabelFormatter","payload","first","verbose","CartesianChart","Chart","chartData","xKey","series","renderSeries","CartesianGrid","XAxis","YAxis","Tooltip","Legend","s","ChartWidget","chartType","containerRef","renderChart","common","LineChart","color","Line","AreaChart","Area","BarChart","Bar","TOOLTIP_CURSOR","barColor","bar","CompositionTooltip","active","CompositionWidget","display","bars","renderBridge","v","Cell","renderPie","PieChart","Pie","percent","_","trendClass","n","fittingRows","total","availableHeight","head","firstRow","rowHeight","fits","TableWidget","rows","clip","numbered","headRef","bodyRef","visible","isNumericFormat","row","numeric","formatValue","FilterWidget","config","dateBounds","onChange","filterType","dateMode","YearlyFilter","MonthlyFilter","WeeklyFilter","DateRangeFilter","SelectFilter","DashboardDatePicker","iso","parsed","parseYearFromRange","now","selectedYear","years","getYearRange","handleYearChange","year","yr","getFullYearRange","e","y","parseMonthFromRange","selectedMonth","handleMonthChange","month","range","getMonthRange","MONTH_NAMES_SHORT","monthWeeks","getMonthWeeks","selectedWeekIdx","parseMonthWeekFromRange","w","m","multi","searchable","SearchableSelect","selected","toggle","opt","FORMAT_SUFFIX","VariableWidget","locked","fmt","suffix","ColorPaletteWidget","ColorPaletteSelector","ERROR_MESSAGES","WidgetRenderer","type","computed","filterValue","filterOptions","onFilterChange","variableValue","onVariableChange","onPaletteChange","seriesColors","getSeries","vc","byReadingOrder","a","b","Dashboard","CELL_ASPECT","onGeometryChange","silenceWarnings","className","widgets","list","rootStyle","GRID_GAP_PX","GRID_PADDING_PX","rootClass","body","widgetsData","gridStyle","getPaletteCssVars","gridClass","Fragment","widget","isControl","CONTROL_WIDGET_SET","widgetStyle","computeWidgetAspect","computeGridHeight","MIN_CELL_HEIGHT_PX","downloadBlob","blob","fileName","url","anchor","COMBINING_FIRST","COMBINING_LAST","stripDiacritics","text","char","code","toFileName","extension","useStatementData","downloading","setDownloading","fetchStatementLayout","fetchStatementRender","filterId","downloadPdf","fetchStatementPdf","LABEL_PADDING_PX","INDENT_STEP_PX","labelStyle","indent","DateRangeControl","bounds","StatementFilter","definition","StatementRow","line","columnCount","showTotal","showVertical","showHorizontal","rowClass","index","horizontal","Statement","showDownload","hasDeclaredWindow","f","lines","column"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/api/params.ts","../src/hooks/useDashboardData.ts","../src/hooks/useGridGeometry.ts","../src/widgets/WidgetFrame.tsx","../src/widgets/comparison.ts","../src/widgets/KPIWidget.tsx","../src/widgets/GaugeWidget.tsx","../src/hooks/useContainerSize.ts","../src/widgets/ChartWidget.tsx","../src/widgets/CompositionWidget.tsx","../src/widgets/TableWidget.tsx","../src/widgets/FilterWidget.tsx","../src/widgets/VariableWidget.tsx","../src/widgets/ColorPaletteWidget.tsx","../src/widgets/WidgetRenderer.tsx","../src/Dashboard.tsx","../src/utils/download.ts","../src/hooks/useStatementData.ts","../src/Statement.tsx"],"sourcesContent":["// Purpose: Protocolo de query params da API externa (prefixos f_ e v_).\n// Scope: Compartilhado por dashboards e demonstrativos — as duas verticais falam a\n// mesma lingua com o backend, entao a traducao mora num lugar so.\n// Public API: WINDOW_FILTER_ID, buildQueryParams, syncFiltersFromApplied\n\nimport { MULTI_VALUE_SEPARATOR } from '../types';\n\n/**\n * Chave reservada da janela de datas embutida do demonstrativo.\n *\n * Nao e um filtro declarado: e o recorte que define as colunas, e existe mesmo\n * quando o documento nao declara filtro nenhum. Vale-se do formato \"start|end\"\n * para virar `f_date_start`/`f_date_end` como qualquer filtro temporal.\n */\nexport const WINDOW_FILTER_ID = '__window';\n\n/**\n * Constroi os query params no formato esperado pela API.\n *\n * Filtros temporais viajam como \"start|end\" e viram o par global\n * `f_date_start`/`f_date_end` — a janela e uma so por request, seja qual for o\n * filtro que a tenha definido.\n */\nexport function buildQueryParams(\n filters: Record<string, string>,\n variables: Record<string, number> = {},\n): Record<string, string> {\n const params: Record<string, string> = {};\n\n for (const [key, val] of Object.entries(filters)) {\n if (val.includes('|')) {\n const [start, end] = val.split('|');\n if (start) params['f_date_start'] = start;\n if (end) params['f_date_end'] = end;\n } else {\n params[`f_${key}`] = val;\n }\n }\n\n for (const [key, val] of Object.entries(variables)) {\n params[`v_${key}`] = String(val);\n }\n\n return params;\n}\n\n/** Converte o `applied` do backend para o formato local de filtros. */\nexport function syncFiltersFromApplied(applied: Record<string, unknown>): Record<string, string> {\n const synced: Record<string, string> = {};\n for (const [id, val] of Object.entries(applied)) {\n if (val && typeof val === 'object' && 'start' in val) {\n const d = val as { start?: string; end?: string };\n synced[id] = `${d.start || ''}|${d.end || ''}`;\n } else if (Array.isArray(val)) {\n synced[id] = val.join(MULTI_VALUE_SEPARATOR);\n } else if (typeof val === 'string') {\n synced[id] = val;\n }\n }\n return synced;\n}\n","// Purpose: Hook que gerencia estado + fetch de um dashboard inteiro.\r\n// Scope: Carrega layout uma vez + render com debounce quando filtros/variaveis mudam.\r\n// Sincroniza estado local com os defaults aplicados pelo backend na 1a carga.\r\n// Public API: useDashboardData\r\n\r\nimport { useState, useEffect, useCallback, useMemo, useRef } from 'react';\r\nimport { fetchLayout, fetchRender } from '../api/fetcher';\r\nimport { buildQueryParams, syncFiltersFromApplied } from '../api/params';\r\nimport type { LayoutResponse, RenderResponse } from '../types';\r\n\r\nexport interface UseDashboardDataResult {\r\n layout: LayoutResponse | null;\r\n renderData: RenderResponse | null;\r\n loading: boolean;\r\n error: string | null;\r\n /** Filtros selecionados (formato string por widget — date_range como \"start|end\"). */\r\n filters: Record<string, string>;\r\n /** Overrides de variaveis por widget. */\r\n variables: Record<string, number>;\r\n /** Paleta efetiva (override local substitui a do layout). */\r\n palette: string[];\r\n setFilter(widgetId: string, value: string): void;\r\n setVariable(widgetId: string, value: number): void;\r\n setPalette(colors: string[]): void;\r\n}\r\n\r\nconst DEBOUNCE_MS = 300;\r\n\r\nexport function useDashboardData(token: string): UseDashboardDataResult {\r\n const [layout, setLayout] = useState<LayoutResponse | null>(null);\r\n const [renderData, setRenderData] = useState<RenderResponse | null>(null);\r\n const [filters, setFilters] = useState<Record<string, string>>({});\r\n const [variables, setVariables] = useState<Record<string, number>>({});\r\n const [localPalette, setLocalPalette] = useState<string[] | null>(null);\r\n const [loading, setLoading] = useState(true);\r\n const [error, setError] = useState<string | null>(null);\r\n\r\n const debounceRef = useRef<ReturnType<typeof setTimeout>>();\r\n const appliedSyncedRef = useRef(false);\r\n\r\n // -------Carrega layout uma unica vez (por token)-------\r\n useEffect(() => {\r\n let cancelled = false;\r\n fetchLayout(token)\r\n .then((res) => { if (!cancelled) setLayout(res); })\r\n .catch((err: Error) => { if (!cancelled) setError(err.message); });\r\n return () => { cancelled = true; };\r\n }, [token]);\r\n\r\n // -------Render com debounce quando filtros/variaveis mudam-------\r\n useEffect(() => {\r\n if (!layout) return;\r\n if (debounceRef.current) clearTimeout(debounceRef.current);\r\n\r\n debounceRef.current = setTimeout(() => {\r\n const params = buildQueryParams(filters, variables);\r\n setLoading(true);\r\n fetchRender(token, params)\r\n .then((res) => {\r\n setRenderData(res);\r\n if (!appliedSyncedRef.current && res.applied) {\r\n appliedSyncedRef.current = true;\r\n setFilters((prev) => ({ ...syncFiltersFromApplied(res.applied), ...prev }));\r\n }\r\n setError(null);\r\n })\r\n .catch((err: Error) => setError(err.message))\r\n .finally(() => setLoading(false));\r\n }, DEBOUNCE_MS);\r\n\r\n return () => {\r\n if (debounceRef.current) clearTimeout(debounceRef.current);\r\n };\r\n }, [token, layout, filters, variables]);\r\n\r\n const setFilter = useCallback((widgetId: string, value: string) => {\r\n setFilters((prev) => ({ ...prev, [widgetId]: value }));\r\n }, []);\r\n\r\n const setVariable = useCallback((widgetId: string, value: number) => {\r\n setVariables((prev) => ({ ...prev, [widgetId]: value }));\r\n }, []);\r\n\r\n const setPalette = useCallback((colors: string[]) => {\r\n setLocalPalette(colors);\r\n }, []);\r\n\r\n const palette = useMemo(\r\n () => localPalette ?? layout?.palette ?? [],\r\n [localPalette, layout],\r\n );\r\n\r\n return {\r\n layout, renderData, loading, error,\r\n filters, variables, palette,\r\n setFilter, setVariable, setPalette,\r\n };\r\n}\r\n","// Purpose: Medir o container do dashboard e projetar a geometria do grid no DOM.\n// Scope: Um unico ResizeObserver sobre a raiz (largura) e o grid (altura). A altura\n// da celula e escrita como custom property, fora do React; so a troca de\n// modo (colunas <-> empilhado) passa por estado. Tambem reporta a geometria\n// ao consumidor e avisa quando o host corta o dashboard.\n// Public API: useGridGeometry\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport type { DashboardGeometry } from '../utils/grid';\nimport { computeCellHeight, computeCellWidth, computeStackThreshold } from '../utils/grid';\n\nexport interface UseGridGeometryOptions {\n /** Numero de colunas do layout. 0 enquanto o layout nao carregou. */\n columns: number;\n /** Proporcao largura/altura da celula. */\n cellAspect: number;\n /** Largura de container abaixo da qual empilhar. `auto` deriva do limiar natural. */\n stackBelow?: number | 'auto';\n /** Notificado quando qualquer medida do grid muda. */\n onGeometryChange?: (geometry: DashboardGeometry) => void;\n /** Desliga o aviso de corte no console. */\n silenceWarnings?: boolean;\n}\n\nexport interface UseGridGeometryResult {\n /** Ref da raiz — elemento medido e portador das custom properties. */\n rootRef: (element: HTMLDivElement | null) => void;\n /** Ref do grid — medido apenas para reportar a altura ocupada. */\n gridRef: (element: HTMLDivElement | null) => void;\n /** True quando o container e estreito demais para a grade de colunas. */\n stacked: boolean;\n}\n\nconst readInlineSize = (entry: ResizeObserverEntry): number =>\n entry.borderBoxSize?.[0]?.inlineSize ?? (entry.target as HTMLElement).offsetWidth;\n\nconst readBlockSize = (entry: ResizeObserverEntry): number =>\n entry.borderBoxSize?.[0]?.blockSize ?? (entry.target as HTMLElement).offsetHeight;\n\n/** Limiar efetivo de empilhamento. 0 desliga o modo. */\nfunction resolveStackThreshold(\n stackBelow: number | 'auto' | undefined,\n columns: number,\n aspect: number,\n): number {\n if (stackBelow === undefined) return 0;\n if (stackBelow === 'auto') return computeStackThreshold(columns, aspect);\n return Math.max(0, stackBelow);\n}\n\n/**\n * Ancestral que efetivamente recorta o elemento.\n *\n * Para na primeira caixa de rolagem: se ela rola (`auto`/`scroll`), nada acima\n * dela corta o dashboard, e o embutimento e legitimo.\n */\nfunction findClippingAncestor(element: HTMLElement): HTMLElement | null {\n let node = element.parentElement;\n while (node && node !== document.body && node !== document.documentElement) {\n const { overflowY } = getComputedStyle(node);\n if (overflowY !== 'visible') {\n return overflowY === 'hidden' || overflowY === 'clip' ? node : null;\n }\n node = node.parentElement;\n }\n return null;\n}\n\nexport function useGridGeometry(options: UseGridGeometryOptions): UseGridGeometryResult {\n // Latest-ref: o observer e criado uma vez e precisa enxergar os valores atuais\n // sem ser reassinado a cada render. Nunca lido durante o render.\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const rootElRef = useRef<HTMLDivElement | null>(null);\n const gridElRef = useRef<HTMLDivElement | null>(null);\n const observerRef = useRef<ResizeObserver | null>(null);\n const frameRef = useRef<number | null>(null);\n const geometryRef = useRef<DashboardGeometry | null>(null);\n const widthRef = useRef(0);\n const gridHeightRef = useRef(0);\n const stackedRef = useRef(false);\n const warnedRef = useRef(false);\n // Largura ja projetada no DOM. -1 forca a proxima projecao (troca de layout).\n const appliedWidthRef = useRef(-1);\n\n const [stacked, setStacked] = useState(false);\n\n const warnIfClipped = useCallback((geometry: DashboardGeometry) => {\n const grid = gridElRef.current;\n if (warnedRef.current || optionsRef.current.silenceWarnings || !grid) return;\n\n const ancestor = findClippingAncestor(grid);\n if (!ancestor || ancestor.clientHeight >= geometry.gridHeight) return;\n\n warnedRef.current = true;\n console.warn(\n '[@actionexec/dashboards] O dashboard esta sendo cortado: o container precisa de '\n + `${Math.ceil(geometry.gridHeight)}px de altura, mas o ancestral com overflow oculto tem `\n + `${ancestor.clientHeight}px. A altura do dashboard varia com a largura — use a prop `\n + 'onGeometryChange para dimensionar o container, ou troque o overflow para auto. '\n + 'Passe silenceWarnings para desligar este aviso.',\n );\n }, []);\n\n const emit = useCallback(() => {\n if (!rootElRef.current) return;\n\n const { columns, cellAspect } = optionsRef.current;\n // Usa a largura ja medida em vez de reler o DOM: emit roda logo apos apply\n // escrever as custom properties, e um getBoundingClientRect aqui forcaria\n // um reflow sincrono por frame de arrasto.\n const containerWidth = widthRef.current;\n const cellWidth = computeCellWidth(containerWidth, columns);\n\n const next: DashboardGeometry = {\n containerWidth,\n cellWidth,\n cellHeight: computeCellHeight(cellWidth, cellAspect),\n gridHeight: gridHeightRef.current,\n stacked: stackedRef.current,\n };\n\n const prev = geometryRef.current;\n const unchanged = prev\n && prev.containerWidth === next.containerWidth\n && prev.cellWidth === next.cellWidth\n && prev.cellHeight === next.cellHeight\n && prev.gridHeight === next.gridHeight\n && prev.stacked === next.stacked;\n if (unchanged) return;\n\n geometryRef.current = next;\n optionsRef.current.onGeometryChange?.(next);\n warnIfClipped(next);\n }, [warnIfClipped]);\n\n /**\n * Projeta a largura medida na geometria do grid.\n *\n * As custom properties sao escritas direto no no, sem passar pelo React: o\n * arrasto da janela emite uma medida por frame, e re-renderizar a arvore de\n * widgets nessa cadencia custaria caro com graficos em tela. Elas nunca\n * aparecem no objeto `style` do JSX — o React so remove chaves que ele mesmo\n * escreveu, entao o valor imperativo sobrevive aos renders seguintes.\n *\n * NUNCA chamar de dentro do callback do ResizeObserver: ver handleEntries.\n */\n const apply = useCallback((force = false) => {\n const root = rootElRef.current;\n if (!root) return;\n\n const width = widthRef.current;\n if (!force && width === appliedWidthRef.current) return;\n appliedWidthRef.current = width;\n\n const { columns, cellAspect, stackBelow } = optionsRef.current;\n const cellWidth = computeCellWidth(width, columns);\n root.style.setProperty('--dash-cell-h', `${computeCellHeight(cellWidth, cellAspect)}px`);\n\n const threshold = resolveStackThreshold(stackBelow, columns, cellAspect);\n const nextStacked = threshold > 0 && width > 0 && width < threshold;\n if (nextStacked !== stackedRef.current) {\n stackedRef.current = nextStacked;\n setStacked(nextStacked);\n }\n }, []);\n\n const cancelFrame = useCallback(() => {\n if (frameRef.current === null) return;\n cancelAnimationFrame(frameRef.current);\n // Zerar junto com o cancelamento e obrigatorio: o unico outro ponto que\n // zera e o corpo do frame, que acabou de ser cancelado. Sem isto o guard de\n // scheduleFrame veria um id obsoleto e sairia cedo para sempre.\n frameRef.current = null;\n }, []);\n\n // O observer pode disparar mais de uma vez por frame; projecao e relato sao\n // coalescidos num unico frame.\n const scheduleFrame = useCallback(() => {\n if (frameRef.current !== null) return;\n frameRef.current = requestAnimationFrame(() => {\n frameRef.current = null;\n apply();\n emit();\n });\n }, [apply, emit]);\n\n const handleEntries = useCallback((entries: ResizeObserverEntry[]) => {\n for (const entry of entries) {\n if (entry.target === rootElRef.current) widthRef.current = Math.round(readInlineSize(entry));\n else if (entry.target === gridElRef.current) gridHeightRef.current = readBlockSize(entry);\n }\n // Deliberadamente NAO escreve no DOM aqui. Escrever --dash-cell-h durante a\n // entrega das observacoes mudaria a altura do grid e, por tabela, a da raiz\n // (que e flex column sem altura propria). A raiz esta numa profundidade\n // menor que a ultima entregue, entao vira \"skipped observation\" e o browser\n // emite o ErrorEvent \"ResizeObserver loop completed with undelivered\n // notifications\" — que o app hospedeiro captura como erro nao tratado.\n // Adiar para o frame seguinte fecha o laco limpo.\n scheduleFrame();\n }, [scheduleFrame]);\n\n const ensureObserver = useCallback(() => {\n if (observerRef.current) return observerRef.current;\n if (typeof ResizeObserver === 'undefined') return null;\n observerRef.current = new ResizeObserver(handleEntries);\n return observerRef.current;\n }, [handleEntries]);\n\n const rootRef = useCallback((element: HTMLDivElement | null) => {\n const observer = ensureObserver();\n if (rootElRef.current) observer?.unobserve(rootElRef.current);\n rootElRef.current = element;\n if (!element) return;\n observer?.observe(element);\n // Medicao e projecao sincronas, fora do laco do observer: sem elas o\n // primeiro frame usaria o fallback do CSS em vez da celula real.\n widthRef.current = Math.round(element.getBoundingClientRect().width);\n apply(true);\n scheduleFrame();\n }, [apply, ensureObserver, scheduleFrame]);\n\n const gridRef = useCallback((element: HTMLDivElement | null) => {\n const observer = ensureObserver();\n if (gridElRef.current) observer?.unobserve(gridElRef.current);\n gridElRef.current = element;\n if (!element) {\n gridHeightRef.current = 0;\n return;\n }\n observer?.observe(element);\n gridHeightRef.current = element.getBoundingClientRect().height;\n scheduleFrame();\n }, [ensureObserver, scheduleFrame]);\n\n // O effect e o dono do ciclo de vida do observer. Deixar so as ref callbacks\n // criando e um effect destruindo seria assimetrico: o StrictMode do React 18\n // roda o cleanup sem reanexar refs, e a raiz ficaria sem observacao pelo resto\n // da sessao — quebrando em dev exatamente a proporcao que o hook mantem.\n // observe() e idempotente, entao reobservar o que as refs ja pegaram e seguro.\n useEffect(() => {\n const observer = ensureObserver();\n if (rootElRef.current) observer?.observe(rootElRef.current);\n if (gridElRef.current) observer?.observe(gridElRef.current);\n return () => {\n observerRef.current?.disconnect();\n observerRef.current = null;\n cancelFrame();\n };\n }, [ensureObserver, cancelFrame]);\n\n // Trocar de layout muda o numero de colunas e, com ele, toda a geometria.\n // Roda fora do laco do observer, entao a escrita sincrona aqui e segura.\n useEffect(() => {\n if (!rootElRef.current) return;\n apply(true);\n scheduleFrame();\n }, [options.columns, options.cellAspect, options.stackBelow, apply, scheduleFrame]);\n\n return { rootRef, gridRef, stacked };\n}\n","// Purpose: Moldura comum a todos os widgets — titulo e estados nao-prontos.\n// Scope: Antes cada widget desenhava o proprio titulo (h4/span, quatro classes\n// diferentes) e o proprio \"Sem dados\". Aqui ficam a marcacao e as classes\n// unicas; o widget cuida so do seu conteudo.\n// Public API: WidgetFrame, WidgetState, WidgetStateKind\n\nimport type { ReactNode } from 'react';\n\n/** Estados em que o widget mostra uma mensagem no lugar do conteudo. */\nexport type WidgetStateKind = 'empty' | 'error' | 'loading' | 'unconfigured';\n\nconst STATE_MESSAGES: Record<WidgetStateKind, string> = {\n empty: 'Sem dados',\n error: 'Não foi possível carregar',\n loading: 'Carregando...',\n unconfigured: 'Widget não configurado',\n};\n\ninterface WidgetStateProps {\n kind: WidgetStateKind;\n /** Sobrescreve a mensagem padrao do estado. */\n message?: string;\n}\n\n/** Mensagem centralizada exibida no lugar do conteudo do widget. */\nexport function WidgetState({ kind, message }: WidgetStateProps) {\n return (\n <div className={`widget__state widget__state--${kind}`} role={kind === 'error' ? 'alert' : undefined}>\n {message || STATE_MESSAGES[kind]}\n </div>\n );\n}\n\ninterface WidgetFrameProps {\n /** Sufixo da classe do widget (`kpi` -> `.widget-kpi`). */\n name: string;\n title?: string;\n /** Quando definido, substitui o conteudo pela mensagem de estado. */\n state?: WidgetStateKind;\n stateMessage?: string;\n /** Renderizado entre o titulo e o conteudo (ex: barra de abas da tabela). */\n toolbar?: ReactNode;\n children?: ReactNode;\n}\n\n/**\n * Casca padrao de um widget: mesma hierarquia visual em todos os tipos.\n *\n * O titulo sai do payload computado ou da config; widgets sem titulo apenas o\n * omitem — o conteudo ocupa a altura toda, sem espacador vazio.\n */\nexport function WidgetFrame({ name, title, state, stateMessage, toolbar, children }: WidgetFrameProps) {\n return (\n <div className={`widget widget-${name}`}>\n {title && <span className=\"widget__title\">{title}</span>}\n {toolbar}\n {state ? <WidgetState kind={state} message={stateMessage} /> : children}\n </div>\n );\n}\n","// Purpose: Leitura do bloco de comparacoes que o backend devolve.\n// Scope: O card e o gauge consomem o MESMO payload — o card le a variacao, o\n// gauge le a proporcao no arco. Este modulo guarda o formato e a regra de\n// o que aparece, para que os dois nao divirjam.\n// Public API: ComputedComparison, TREND_ARROWS, visibleComparisons\n\nexport interface ComputedComparison {\n id?: string;\n label?: string | null;\n /** `unavailable` = configurada, mas sem como resolver (ex: desvio sem filtro de data). */\n status?: string;\n display?: string;\n baseline?: number | null;\n baseline_formatted?: string | null;\n delta?: number | null;\n delta_formatted?: string | null;\n variance_pct?: number | null;\n ratio?: number | null;\n /** Numero em destaque, ja formatado pelo backend conforme `display`. */\n formatted?: string | null;\n trend?: string | null;\n sentiment?: string | null;\n}\n\nexport const TREND_ARROWS: Record<string, string> = { up: '↑', down: '↓' };\n\n/**\n * Comparacoes que o dashboard publicado mostra.\n *\n * As indisponiveis somem em vez de virar \"-\": quem ve o dashboard nao configurou\n * nada e nao tem o que fazer com o aviso. Quem configurou ve a pendencia no\n * builder, que le o mesmo `status`.\n */\nexport function visibleComparisons(raw: unknown): ComputedComparison[] {\n if (!Array.isArray(raw)) return [];\n return (raw as ComputedComparison[]).filter(\n (c) => c && c.status === 'ok' && c.formatted && c.formatted !== '-',\n );\n}\n","// Purpose: Card com valor computado + comparacoes.\n// Scope: Renderiza titulo, valor e uma linha por comparacao. Todo numero e todo\n// texto vem prontos do backend — a primeira comparacao ganha destaque, as\n// demais seguem em linha compacta.\n// Public API: KPIWidget\n\nimport { WidgetFrame } from './WidgetFrame';\nimport type { ComputedComparison } from './comparison';\nimport { TREND_ARROWS, visibleComparisons } from './comparison';\n\ninterface Props {\n data: Record<string, unknown>;\n label?: string;\n}\n\nfunction ComparisonLine({ comparison, primary }: { comparison: ComputedComparison; primary: boolean }) {\n const sentiment = comparison.sentiment ?? 'neutral';\n const arrow = TREND_ARROWS[comparison.trend ?? ''] ?? '';\n\n return (\n <div className={`widget-kpi__trend widget-kpi__trend--${sentiment}${primary ? '' : ' widget-kpi__trend--muted'}`}>\n <span className=\"widget-kpi__variance\">{arrow} {comparison.formatted}</span>\n {comparison.label && <span className=\"widget-kpi__trend-label\">{comparison.label}</span>}\n </div>\n );\n}\n\nexport function KPIWidget({ data, label }: Props) {\n const title = label || String(data.label || '');\n const formatted = String(data.formatted || '-');\n const comparisons = visibleComparisons(data.comparisons);\n\n return (\n <WidgetFrame name=\"kpi\" title={title}>\n <span className=\"widget-kpi__value\">{formatted}</span>\n {comparisons.map((comparison, i) => (\n <ComparisonLine key={comparison.id || i} comparison={comparison} primary={i === 0} />\n ))}\n </WidgetFrame>\n );\n}\n","// Purpose: Gauge widget (progresso vs meta).\n// Scope: Semicirculo SVG com percentual, valores brutos e indicador de meta batida.\n// Public API: GaugeWidget\n\nimport { WidgetFrame } from './WidgetFrame';\nimport { formatCompact } from '../utils/format';\nimport { visibleComparisons } from './comparison';\n\ninterface Props {\n data: Record<string, unknown>;\n palette: string[];\n label?: string;\n}\n\nconst COLOR_EMPTY = 'var(--bg-elevated)';\n\n// Faixas de atingimento -> cor de preenchimento do arco\nconst FILL_THRESHOLDS: [number, string][] = [\n [1, 'var(--color-success)'],\n [0.7, ''], // vazio = cor da serie 1 (destaque do dashboard)\n [0.4, 'var(--color-warning)'],\n [0, 'var(--color-error)'],\n];\n\n/** Gera path SVG de um arco semicircular (de esquerda para direita, no topo). */\nfunction arcPath(cx: number, cy: number, r: number, fraction: number): string {\n if (fraction <= 0) return '';\n if (fraction >= 1) {\n // Semicirculo completo: dois arcos de 90° (SVG nao desenha arco de exatamente 180°)\n return `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx} ${cy - r} A ${r} ${r} 0 0 1 ${cx + r} ${cy}`;\n }\n const angle = fraction * Math.PI;\n return `M ${cx - r} ${cy} A ${r} ${r} 0 0 1 ${cx - r * Math.cos(angle)} ${cy - r * Math.sin(angle)}`;\n}\n\nexport function GaugeWidget({ data, palette, label: propLabel }: Props) {\n const title = propLabel || String(data.label || '');\n const ratio = typeof data.ratio === 'number' ? data.ratio : 0;\n const format = typeof data.format === 'string' ? data.format : undefined;\n\n // O backend ja formata valor e base na unidade do widget; o compacto so entra\n // como fallback para payloads antigos, sem os campos formatados.\n const valueFormatted = String(data.value_formatted || formatCompact(data.value, format));\n const ratioFormatted = String(data.formatted || '-');\n\n // O arco e a primeira comparacao; as demais viram texto sob ele\n const comparisons = visibleComparisons(data.comparisons);\n const [primary, ...extras] = comparisons;\n const targetFormatted = String(primary?.baseline_formatted || '-');\n const comparisonLabel = primary?.label ?? null;\n const exceeded = ratio >= 1;\n const clamped = Math.min(Math.max(ratio, 0), 1);\n\n const threshold = FILL_THRESHOLDS.find(([min]) => ratio >= min);\n const fillColor = threshold?.[1] || palette[0] || 'var(--color-info)';\n\n const cx = 50, cy = 50, r = 44, stroke = 10;\n\n return (\n <WidgetFrame name=\"gauge\" title={title}>\n <div className=\"widget-gauge__chart\">\n <svg viewBox=\"0 0 100 56\" preserveAspectRatio=\"xMidYMax meet\" role=\"img\" aria-label={`${ratioFormatted} da meta`}>\n <path d={arcPath(cx, cy, r, 1)} fill=\"none\" stroke={COLOR_EMPTY} strokeWidth={stroke} strokeLinecap=\"butt\" />\n {clamped > 0 && (\n <path d={arcPath(cx, cy, r, clamped)} fill=\"none\" stroke={fillColor} strokeWidth={stroke} strokeLinecap=\"butt\" />\n )}\n </svg>\n <div className=\"widget-gauge__center\">\n <span className=\"widget-gauge__percent\">{ratioFormatted}</span>\n <span className=\"widget-gauge__comparison\">{valueFormatted} / {targetFormatted}</span>\n {exceeded && <span className=\"widget-gauge__badge\">{comparisonLabel || 'Meta batida'}</span>}\n {!exceeded && comparisonLabel && <span className=\"widget-gauge__comparison\">{comparisonLabel}</span>}\n {extras.map((c, i) => (\n <span key={c.id || i} className=\"widget-gauge__comparison\">\n {c.formatted} {c.label}\n </span>\n ))}\n </div>\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Medida do container de um grafico.\n// Scope: Recharts precisa de width/height em pixels; o grid entrega tamanho via\n// CSS. Este hook faz a ponte com ResizeObserver. Compartilhado por chart e\n// composition — antes vivia dentro do ChartWidget.\n// Public API: useContainerSize\n\nimport { useState, useEffect } from 'react';\nimport type { RefObject } from 'react';\n\nexport function useContainerSize(ref: RefObject<HTMLDivElement | null>) {\n const [size, setSize] = useState({ width: 0, height: 0 });\n\n useEffect(() => {\n const el = ref.current;\n if (!el) return;\n\n const observer = new ResizeObserver(([entry]) => {\n const { width, height } = entry.contentRect;\n // Compara arredondado: subpixel de layout nao deve disparar re-render\n setSize((prev) =>\n prev.width !== Math.floor(width) || prev.height !== Math.floor(height)\n ? { width: Math.floor(width), height: Math.floor(height) }\n : prev\n );\n });\n observer.observe(el);\n return () => observer.disconnect();\n }, [ref]);\n\n return size;\n}\n","// Purpose: Chart widget cartesiano (bar/line/area via Recharts).\r\n// Scope: Renderiza com dados pre-calculados pelo backend + tooltip tematizado.\r\n// Public API: ChartWidget\r\n\r\nimport { useRef, type ComponentType, type ReactElement } from 'react';\r\nimport {\r\n BarChart, Bar,\r\n LineChart, Line,\r\n AreaChart, Area,\r\n XAxis, YAxis, CartesianGrid, Tooltip, Legend,\r\n} from 'recharts';\r\nimport { WidgetFrame, WidgetState } from './WidgetFrame';\r\nimport { useContainerSize } from '../hooks/useContainerSize';\r\n\r\nconst AXIS_STYLE = { fontSize: 10, fill: 'var(--text-muted)' };\r\nconst GRID_STROKE = 'var(--bg-elevated)';\r\n\r\n// Tooltip segue a paleta do dashboard via CSS variables (getPaletteCssVars)\r\nconst TOOLTIP_CONTENT_STYLE = {\r\n backgroundColor: 'var(--bg-elevated)',\r\n border: '1px solid var(--bg-paper)',\r\n borderRadius: '6px',\r\n color: 'var(--text-primary)',\r\n};\r\nconst TOOLTIP_LABEL_STYLE = {\r\n color: 'var(--text-primary)',\r\n fontWeight: 600,\r\n};\r\n\r\n// Usa `tooltipLabel` (versao verbose) do data point quando presente,\r\n// fallback para o label do eixo X (compacto).\r\nfunction tooltipLabelFormatter(label: unknown, payload: readonly unknown[]): string {\r\n const first = (Array.isArray(payload) ? payload[0] : undefined) as { payload?: Record<string, unknown> } | undefined;\r\n const verbose = first?.payload?.tooltipLabel;\r\n if (typeof verbose === 'string' && verbose) return verbose;\r\n return String(label ?? '');\r\n}\r\n\r\ninterface SeriesInfo { key: string; label: string }\r\n\r\n// Componente generico para charts cartesianos (bar/line/area)\r\nfunction CartesianChart({ Chart, chartData, xKey, series, palette, renderSeries, width, height }: {\r\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\r\n Chart: ComponentType<any>;\r\n chartData: Record<string, unknown>[];\r\n xKey: string;\r\n series: SeriesInfo[];\r\n palette: string[];\r\n renderSeries: (s: SeriesInfo, color: string, idx: number) => ReactElement;\r\n width: number;\r\n height: number;\r\n}) {\r\n return (\r\n <Chart data={chartData} width={width} height={height}>\r\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\r\n <XAxis dataKey={xKey} tick={AXIS_STYLE} />\r\n <YAxis tick={AXIS_STYLE} />\r\n <Tooltip\r\n contentStyle={TOOLTIP_CONTENT_STYLE}\r\n labelStyle={TOOLTIP_LABEL_STYLE}\r\n labelFormatter={tooltipLabelFormatter}\r\n cursor={{ fill: 'var(--bg-paper)', opacity: 0.3 }}\r\n />\r\n {series.length > 1 && <Legend />}\r\n {series.map((s, i) => renderSeries(s, palette[i % palette.length], i))}\r\n </Chart>\r\n );\r\n}\r\n\r\ninterface Props {\r\n data: Record<string, unknown>;\r\n palette: string[];\r\n label?: string;\r\n}\r\n\r\nexport function ChartWidget({ data, palette, label: propLabel }: Props) {\r\n const chartType = String(data.chartType || 'bar');\r\n const title = propLabel || String(data.label || '');\r\n const xKey = String(data.xKey || 'label');\r\n const series = (data.series || []) as SeriesInfo[];\r\n const chartData = (data.data || []) as Record<string, unknown>[];\r\n\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const { width, height } = useContainerSize(containerRef);\r\n\r\n const renderChart = () => {\r\n if (width <= 0 || height <= 0) return null;\r\n\r\n const common = { chartData, xKey, series, palette, width, height };\r\n\r\n if (chartType === 'line') {\r\n return (\r\n <CartesianChart {...common} Chart={LineChart} renderSeries={(s, color) => (\r\n <Line key={s.key} type=\"monotone\" dataKey={s.key} name={s.label}\r\n stroke={color} strokeWidth={2} dot={chartData.length <= 31} />\r\n )} />\r\n );\r\n }\r\n\r\n if (chartType === 'area') {\r\n return (\r\n <CartesianChart {...common} Chart={AreaChart} renderSeries={(s, color) => (\r\n <Area key={s.key} type=\"monotone\" dataKey={s.key} name={s.label}\r\n fill={color} stroke={color} fillOpacity={0.3} />\r\n )} />\r\n );\r\n }\r\n\r\n return (\r\n <CartesianChart {...common} Chart={BarChart} renderSeries={(s, color) => (\r\n <Bar key={s.key} dataKey={s.key} name={s.label}\r\n fill={color} radius={[3, 3, 0, 0]} />\r\n )} />\r\n );\r\n };\r\n\r\n return (\r\n <WidgetFrame name=\"chart\" title={title}>\r\n {/* Container sempre montado: mantem o ResizeObserver atado ao mesmo elemento\r\n mesmo no estado vazio, evitando que o grafico nao remonte ao voltar dados. */}\r\n <div ref={containerRef} className=\"widget-chart__container\">\r\n {chartData.length === 0 ? <WidgetState kind=\"empty\" /> : renderChart()}\r\n </div>\r\n </WidgetFrame>\r\n );\r\n}\r\n","// Purpose: Widget de composicao — reparte uma medida entre categorias.\n// Scope: Dois desenhos sobre o mesmo dado: pizza (partes de um todo) e ponte\n// (caminho de um ponto a outro). O servidor ja manda cada barra posicionada\n// (`base` onde comeca, `span` o quanto ocupa), entao aqui nao ha conta de\n// acumulado — so escolha de cor e traco.\n// Public API: CompositionWidget\n\nimport { useRef } from 'react';\nimport {\n BarChart, Bar, Cell,\n PieChart, Pie,\n XAxis, YAxis, CartesianGrid, Tooltip,\n} from 'recharts';\nimport { WidgetFrame, WidgetState } from './WidgetFrame';\nimport { useContainerSize } from '../hooks/useContainerSize';\nimport { formatCompact } from '../utils/format';\n\nconst AXIS_STYLE = { fontSize: 10, fill: 'var(--text-muted)' };\nconst GRID_STROKE = 'var(--bg-elevated)';\nconst TOOLTIP_CURSOR = { fill: 'var(--bg-paper)', opacity: 0.3 };\n\n/** Uma barra/fatia ja posicionada pelo servidor. */\ninterface CompositionBar {\n label: string;\n kind: 'slice' | 'anchor' | 'delta' | 'residual';\n value: number;\n base: number;\n span: number;\n formatted: string;\n}\n\ninterface Props {\n data: Record<string, unknown>;\n palette: string[];\n label?: string;\n}\n\n/**\n * Cor por papel da barra, nao por posicao: ancora e o patamar, delta positivo\n * soma, delta negativo subtrai, e o residuo e o que os dados nao explicam.\n */\nfunction barColor(bar: CompositionBar): string {\n if (bar.kind === 'anchor') return 'var(--color-accent)';\n if (bar.kind === 'residual') return 'var(--color-warning)';\n return bar.value < 0 ? 'var(--color-error)' : 'var(--color-success)';\n}\n\ninterface TooltipProps {\n active?: boolean;\n payload?: { payload?: CompositionBar }[];\n}\n\n/**\n * Hover unico da pizza e da ponte: rotulo em negrito e, embaixo, o valor\n * formatado pelo servidor.\n *\n * O padrao do Recharts lista uma linha por serie — na ponte sao duas (`base`\n * invisivel e `span`), o que repetia a mesma categoria e mostrava a extensao da\n * barra em vez do valor. Lendo o `payload` da barra tocada, as duas formas caem\n * na mesma leitura e o valor aparece sempre.\n */\nfunction CompositionTooltip({ active, payload }: TooltipProps) {\n const bar = active ? payload?.[0]?.payload : undefined;\n if (!bar) return null;\n\n return (\n <div className=\"widget-composition__tooltip\">\n <span className=\"widget-composition__tooltip-label\">{bar.label}</span>\n <span className=\"widget-composition__tooltip-value\">{bar.formatted}</span>\n </div>\n );\n}\n\nexport function CompositionWidget({ data, palette, label: propLabel }: Props) {\n const title = propLabel || String(data.label || '');\n const display = String(data.display || 'pie');\n const bars = (data.data || []) as CompositionBar[];\n const format = typeof data.format === 'string' ? data.format : undefined;\n\n const containerRef = useRef<HTMLDivElement>(null);\n const { width, height } = useContainerSize(containerRef);\n\n const renderBridge = () => (\n <BarChart data={bars} width={width} height={height}>\n <CartesianGrid strokeDasharray=\"3 3\" stroke={GRID_STROKE} />\n <XAxis dataKey=\"label\" tick={AXIS_STYLE} interval={0} />\n <YAxis tick={AXIS_STYLE} tickFormatter={(v) => formatCompact(v, format)} />\n <Tooltip content={<CompositionTooltip />} cursor={TOOLTIP_CURSOR} />\n {/* A primeira barra so eleva a segunda ate `base`: e o truque que faz a\n barra flutuar sem componente dedicado. */}\n <Bar dataKey=\"base\" stackId=\"bridge\" fill=\"none\" fillOpacity={0} isAnimationActive={false} />\n <Bar dataKey=\"span\" stackId=\"bridge\" radius={[3, 3, 0, 0]}>\n {bars.map((bar, i) => <Cell key={i} fill={barColor(bar)} />)}\n </Bar>\n </BarChart>\n );\n\n const renderPie = () => (\n <PieChart width={width} height={height}>\n <Pie\n data={bars}\n dataKey=\"value\"\n nameKey=\"label\"\n cx=\"50%\" cy=\"50%\" outerRadius=\"75%\"\n label={({ name, percent }: { name: string; percent: number }) =>\n `${name}: ${(percent * 100).toFixed(0)}%`\n }\n labelLine={false}\n >\n {bars.map((_, i) => <Cell key={i} fill={palette[i % palette.length]} />)}\n </Pie>\n <Tooltip content={<CompositionTooltip />} />\n </PieChart>\n );\n\n return (\n <WidgetFrame name=\"composition\" title={title}>\n {/* Container sempre montado: mantem o ResizeObserver atado ao mesmo elemento\n mesmo no estado vazio, evitando que o grafico nao remonte ao voltar dados. */}\n <div ref={containerRef} className=\"widget-composition__container\">\n {bars.length === 0 || width <= 0 || height <= 0\n ? <WidgetState kind=\"empty\" />\n : (display === 'bridge' ? renderBridge() : renderPie())}\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Widget de tabela — mostra linhas x colunas do dataset.\n// Scope: Renderiza data.columns (cabecalho) + data.rows (linhas), formatando cada\n// celula pelo format da coluna (via utils/format, o mesmo dos demais widgets).\n// Colore colunas de porcentagem (verde/vermelho). `data.overflow` decide o\n// que fazer com o que passa da altura: rolar ou cortar.\n// Public API: TableWidget\n\nimport { useRef } from 'react';\nimport { WidgetFrame } from './WidgetFrame';\nimport { useContainerSize } from '../hooks/useContainerSize';\nimport { formatValue, isNumericFormat } from '../utils/format';\n\ninterface TableColumn {\n key: string;\n label?: string;\n format?: string;\n}\n\ninterface Props {\n data: Record<string, unknown>;\n label?: string;\n}\n\n/** Classe de tendencia para colunas percentuais (positivo verde, negativo vermelho). */\nfunction trendClass(value: unknown, format?: string): string {\n if (format !== 'percentage') return '';\n const n = Number(value);\n if (Number.isNaN(n) || n === 0) return '';\n return n > 0 ? ' widget-table__td--up' : ' widget-table__td--down';\n}\n\n/**\n * Quantas linhas cabem inteiras na altura disponivel.\n *\n * A altura vem de uma linha ja desenhada, e nao de uma constante: a fonte da\n * tabela escala com o container. Mede a PRIMEIRA linha em vez da altura total do\n * corpo — o total encolhe assim que o corte acontece, e dividi-lo pelo numero\n * de linhas daria uma altura cada vez menor a cada medida.\n *\n * Sem medida ainda (primeiro render), devolve todas: cortar antes de medir\n * faria linhas piscarem na tela.\n */\nfunction fittingRows(total: number, availableHeight: number, head: HTMLElement | null, firstRow: Element | null): number {\n const rowHeight = (firstRow as HTMLElement | null)?.offsetHeight ?? 0;\n if (total === 0 || availableHeight <= 0 || rowHeight <= 0) return total;\n\n const fits = Math.floor((availableHeight - (head?.offsetHeight ?? 0)) / rowHeight);\n return Math.max(0, Math.min(total, fits));\n}\n\nexport function TableWidget({ data, label }: Props) {\n const columns = (data.columns as TableColumn[]) || [];\n const rows = (data.rows as Record<string, unknown>[]) || [];\n const clip = data.overflow === 'clip';\n // A numeracao e posicional: acompanha a ordem em que a linha e desenhada, e\n // por isso e contada aqui em vez de vir como coluna de dado.\n const numbered = data.indexColumn === true;\n const title = label || String(data.label || '');\n\n const containerRef = useRef<HTMLDivElement>(null);\n const headRef = useRef<HTMLTableSectionElement>(null);\n const bodyRef = useRef<HTMLTableSectionElement>(null);\n const { height } = useContainerSize(containerRef);\n\n const visible = clip\n ? rows.slice(0, fittingRows(\n rows.length, height, headRef.current, bodyRef.current?.firstElementChild ?? null,\n ))\n : rows;\n\n if (columns.length === 0) {\n return (\n <WidgetFrame\n name=\"table\"\n title={title}\n state=\"unconfigured\"\n stateMessage=\"Configure as colunas da tabela.\"\n />\n );\n }\n\n return (\n <WidgetFrame name=\"table\" title={title}>\n <div\n ref={containerRef}\n className={`widget-table__scroll${clip ? ' widget-table__scroll--clip' : ''}`}\n >\n {/* `--fill` estica as linhas para ocupar a altura que sobra. Fica de fora\n quando o corte esta ativo: a linha esticada mudaria a altura que\n decide quantas cabem, e a conta oscilaria a cada medida. */}\n <table\n className={`widget-table__table${clip && visible.length < rows.length ? '' : ' widget-table__table--fill'}`}\n >\n <thead ref={headRef}>\n <tr>\n {numbered && <th className=\"widget-table__th widget-table__th--index\">#</th>}\n {columns.map((c) => (\n <th\n key={c.key}\n className={`widget-table__th${isNumericFormat(c.format) ? ' widget-table__th--num' : ''}`}\n >\n {c.label || c.key}\n </th>\n ))}\n </tr>\n </thead>\n <tbody ref={bodyRef}>\n {visible.length === 0 ? (\n <tr>\n <td\n className=\"widget-table__td widget-table__td--placeholder\"\n colSpan={columns.length + (numbered ? 1 : 0)}\n >\n Sem dados\n </td>\n </tr>\n ) : (\n visible.map((row, i) => (\n <tr key={i}>\n {numbered && <td className=\"widget-table__td widget-table__td--index\">{i + 1}</td>}\n {columns.map((c) => {\n const raw = row[c.key];\n const numeric = isNumericFormat(c.format) ? ' widget-table__td--num' : '';\n return (\n <td key={c.key} className={`widget-table__td${numeric}${trendClass(raw, c.format)}`}>\n {formatValue(raw, c.format)}\n </td>\n );\n })}\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n </WidgetFrame>\n );\n}\n","// Purpose: Widget de filtro interativo no grid (date_range, select, multi_select).\r\n// Scope: Modos temporais (range, monthly, weekly, yearly), select unico, multi-select.\r\n// Modo categorico padrao (select/checkbox) ou lista com busca (searchable).\r\n// Public API: FilterWidget\r\n\r\nimport type { FilterConfig, DateFilterMode } from '../types';\r\nimport {\r\n MONTH_NAMES_SHORT, getFullYearRange, getMonthRange,\r\n getMonthWeeks, parseMonthWeekFromRange,\r\n parseYearFromRange, parseMonthFromRange, getYearRange,\r\n} from '../utils/date';\r\nimport { DashboardDatePicker } from '../components/DashboardDatePicker';\r\nimport { SearchableSelect } from '../components/SearchableSelect';\r\nimport { MULTI_VALUE_SEPARATOR } from '../types';\r\n\r\ninterface Props {\r\n config: FilterConfig;\r\n value: string;\r\n options?: string[];\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}\r\n\r\n// -------Componente principal-------\r\n\r\nexport function FilterWidget({ config, value, options = [], dateBounds, onChange }: Props) {\r\n const filterType = config.filterType || 'select';\r\n const label = config.label || 'Filtro';\r\n const dateMode: DateFilterMode = config.dateFilterMode || 'range';\r\n\r\n return (\r\n <div className=\"widget-filter\">\r\n <label className=\"widget-filter__label\">{label}</label>\r\n {filterType === 'date_range' ? (\r\n dateMode === 'yearly' ? (\r\n <YearlyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : dateMode === 'monthly' ? (\r\n <MonthlyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : dateMode === 'weekly' ? (\r\n <WeeklyFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n ) : (\r\n <DateRangeFilter value={value} dateBounds={dateBounds} onChange={onChange} />\r\n )\r\n ) : (\r\n <SelectFilter\r\n value={value}\r\n options={options}\r\n multi={filterType === 'multi_select'}\r\n searchable={config.searchable || false}\r\n onChange={onChange}\r\n />\r\n )}\r\n </div>\r\n );\r\n}\r\n\r\n// -------DateRangeFilter (modo range puro)-------\r\n\r\nfunction DateRangeFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start, end] = value ? value.split('|') : ['', ''];\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--stacked\">\r\n <DashboardDatePicker\r\n value={start}\r\n minIso={dateBounds?.min}\r\n maxIso={end || dateBounds?.max}\r\n selectsStart\r\n startIso={start}\r\n endIso={end}\r\n placeholder=\"Data inicial\"\r\n onChange={(iso) => onChange(`${iso}|${end}`)}\r\n />\r\n <DashboardDatePicker\r\n value={end}\r\n minIso={start || dateBounds?.min}\r\n maxIso={dateBounds?.max}\r\n selectsEnd\r\n startIso={start}\r\n endIso={end}\r\n placeholder=\"Data final\"\r\n onChange={(iso) => onChange(`${start}|${iso}`)}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\n// -------YearlyFilter (modo anual)-------\r\n\r\nfunction YearlyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseYearFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const years = getYearRange(dateBounds);\r\n\r\n const handleYearChange = (year: number) => {\r\n const yr = getFullYearRange(year);\r\n onChange(`${yr.start}|${yr.end}`);\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--year\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => handleYearChange(parseInt(e.target.value))}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------MonthlyFilter (modo mensal)-------\r\n\r\nfunction MonthlyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseMonthFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const selectedMonth = parsed?.month ?? (now.getMonth() + 1);\r\n const years = getYearRange(dateBounds);\r\n\r\n const handleMonthChange = (year: number, month: number) => {\r\n const range = getMonthRange(year, month);\r\n onChange(`${range.start}|${range.end}`);\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--month\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedMonth}\r\n onChange={(e) => handleMonthChange(selectedYear, parseInt(e.target.value))}\r\n >\r\n {MONTH_NAMES_SHORT.map((name, i) => (\r\n <option key={i + 1} value={i + 1}>{name}</option>\r\n ))}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => handleMonthChange(parseInt(e.target.value), selectedMonth)}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------WeeklyFilter (modo semanal)-------\r\n\r\nfunction WeeklyFilter({ value, dateBounds, onChange }: {\r\n value: string;\r\n dateBounds?: { min: string | null; max: string | null } | null;\r\n onChange: (value: string) => void;\r\n}) {\r\n const [start] = value ? value.split('|') : [''];\r\n const parsed = parseMonthFromRange(start);\r\n const now = new Date();\r\n const selectedYear = parsed?.year ?? now.getFullYear();\r\n const selectedMonth = parsed?.month ?? (now.getMonth() + 1);\r\n const years = getYearRange(dateBounds);\r\n\r\n const monthWeeks = getMonthWeeks(selectedYear, selectedMonth);\r\n const selectedWeekIdx = parseMonthWeekFromRange(start, selectedYear, selectedMonth) || 1;\r\n\r\n return (\r\n <div className=\"widget-filter__date-range widget-filter__date-range--week\">\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedYear}\r\n onChange={(e) => {\r\n const y = parseInt(e.target.value);\r\n const weeks = getMonthWeeks(y, selectedMonth);\r\n const w = weeks[0];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {years.map((y) => <option key={y} value={y}>{y}</option>)}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedMonth}\r\n onChange={(e) => {\r\n const m = parseInt(e.target.value);\r\n const weeks = getMonthWeeks(selectedYear, m);\r\n const w = weeks[0];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {MONTH_NAMES_SHORT.map((name, i) => (\r\n <option key={i + 1} value={i + 1}>{name}</option>\r\n ))}\r\n </select>\r\n <select\r\n className=\"widget-filter__select\"\r\n value={selectedWeekIdx}\r\n onChange={(e) => {\r\n const w = monthWeeks[parseInt(e.target.value) - 1];\r\n if (w) onChange(`${w.start}|${w.end}`);\r\n }}\r\n >\r\n {monthWeeks.map((w) => (\r\n <option key={w.index} value={w.index}>{w.label}</option>\r\n ))}\r\n </select>\r\n </div>\r\n );\r\n}\r\n\r\n// -------SelectFilter (categorico)-------\r\n\r\nfunction SelectFilter({ value, options, multi, searchable, onChange }: {\r\n value: string;\r\n options: string[];\r\n multi: boolean;\r\n searchable: boolean;\r\n onChange: (value: string) => void;\r\n}) {\r\n // Modo lista com busca: unico componente cobre selecao unica e multipla\r\n if (searchable) {\r\n return (\r\n <SearchableSelect\r\n value={value}\r\n options={options}\r\n multi={multi}\r\n onChange={onChange}\r\n />\r\n );\r\n }\r\n\r\n if (multi) {\r\n const selected = value ? value.split(MULTI_VALUE_SEPARATOR) : [];\r\n const toggle = (opt: string) => {\r\n const next = selected.includes(opt)\r\n ? selected.filter((s) => s !== opt)\r\n : [...selected, opt];\r\n onChange(next.join(MULTI_VALUE_SEPARATOR));\r\n };\r\n\r\n return (\r\n <div className=\"widget-filter__multi\">\r\n {/* Limpar filtro: desmarca tudo. Vazio = todos selecionados (sem filtro). */}\r\n {selected.length > 0 && (\r\n <button\r\n type=\"button\"\r\n className=\"widget-filter__multi-clear\"\r\n onClick={() => onChange('')}\r\n >\r\n Limpar filtro\r\n </button>\r\n )}\r\n {options.map((opt) => (\r\n <label key={opt} className=\"widget-filter__multi-option\">\r\n <input\r\n type=\"checkbox\"\r\n checked={selected.includes(opt)}\r\n onChange={() => toggle(opt)}\r\n />\r\n {opt}\r\n </label>\r\n ))}\r\n </div>\r\n );\r\n }\r\n\r\n return (\r\n <select\r\n className=\"widget-filter__select\"\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n >\r\n <option value=\"\">Todos</option>\r\n {options.map((opt) => (\r\n <option key={opt} value={opt}>{opt}</option>\r\n ))}\r\n </select>\r\n );\r\n}\r\n","// Purpose: Widget de variavel editavel no grid (what-if scenarios).\n// Scope: Input numerico com label, formato e opcao de bloqueio.\n// Public API: VariableWidget\n\nimport type { VariableConfig } from '../types';\n\ninterface Props {\n config: VariableConfig;\n value: number;\n onChange: (value: number) => void;\n}\n\nconst FORMAT_SUFFIX: Record<string, string> = {\n currency: 'R$',\n percentage: '%',\n};\n\nexport function VariableWidget({ config, value, onChange }: Props) {\n const label = config.label || 'Variavel';\n const locked = config.locked || false;\n const fmt = config.variableFormat || 'number';\n const suffix = FORMAT_SUFFIX[fmt] || '';\n\n return (\n <div className={`widget-variable ${locked ? 'widget-variable--locked' : ''}`}>\n <label className=\"widget-variable__label\">{label}</label>\n <div className=\"widget-variable__input-wrapper\">\n <input\n className=\"widget-variable__input\"\n type=\"number\"\n value={value}\n onChange={(e) => onChange(parseFloat(e.target.value) || 0)}\n disabled={locked}\n step={fmt === 'integer' ? 1 : 0.01}\n />\n {suffix && <span className=\"widget-variable__suffix\">{suffix}</span>}\n </div>\n {locked && <span className=\"widget-variable__lock-icon\" title=\"Bloqueado\">🔒</span>}\n </div>\n );\n}\n","// Purpose: Widget de paleta de cores editavel no grid.\n// Scope: Permite ao usuario do dashboard trocar a paleta em runtime. Respeita bloqueio.\n// Public API: ColorPaletteWidget\n\nimport type { PaletteConfig } from '../types';\nimport { ColorPaletteSelector } from '../components/ColorPaletteSelector';\n\ninterface Props {\n config: PaletteConfig;\n palette: string[];\n onChange: (colors: string[]) => void;\n}\n\nexport function ColorPaletteWidget({ config, palette, onChange }: Props) {\n const label = config.label || 'Cores';\n const locked = config.locked || false;\n\n return (\n <div className={`widget-palette ${locked ? 'widget-palette--locked' : ''}`}>\n <label className=\"widget-palette__label\">{label}</label>\n <ColorPaletteSelector selected={palette} onSelect={onChange} customMode disabled={locked} />\n {locked && <span className=\"widget-palette__lock-icon\" title=\"Bloqueado\">🔒</span>}\n </div>\n );\n}\n","// Purpose: Dispatch de rendering por tipo de widget (dados + controle).\r\n// Scope: Recebe computed data e/ou config, renderiza widget correto.\r\n// Public API: WidgetRenderer\r\n\r\nimport type { WidgetType, AnyWidgetConfig, FilterConfig, VariableConfig, PaletteConfig } from '../types';\r\nimport { getSeries } from '../palettes';\r\nimport { KPIWidget } from './KPIWidget';\r\nimport { GaugeWidget } from './GaugeWidget';\r\nimport { ChartWidget } from './ChartWidget';\r\nimport { CompositionWidget } from './CompositionWidget';\r\nimport { TableWidget } from './TableWidget';\r\nimport { FilterWidget } from './FilterWidget';\r\nimport { VariableWidget } from './VariableWidget';\r\nimport { ColorPaletteWidget } from './ColorPaletteWidget';\r\nimport { WidgetFrame } from './WidgetFrame';\r\n\r\n// Codigos de erro do backend -> mensagem para o leitor do dashboard.\r\n// Codigo desconhecido cai na mensagem padrao de WidgetState.\r\nconst ERROR_MESSAGES: Record<string, string> = {\r\n failed_to_compute: 'Não foi possível calcular este widget',\r\n};\r\n\r\ninterface Props {\r\n type: WidgetType;\r\n computed: Record<string, unknown>;\r\n palette: string[];\r\n // Control widget props (opcionais)\r\n config?: AnyWidgetConfig;\r\n filterValue?: string;\r\n filterOptions?: string[];\r\n dateBounds?: { min: string; max: string } | null;\r\n onFilterChange?: (value: string) => void;\r\n variableValue?: number;\r\n onVariableChange?: (value: number) => void;\r\n onPaletteChange?: (colors: string[]) => void;\r\n}\r\n\r\nexport function WidgetRenderer({\r\n type, computed, palette, config,\r\n filterValue, filterOptions, dateBounds, onFilterChange,\r\n variableValue, onVariableChange,\r\n onPaletteChange,\r\n}: Props) {\r\n if (computed.error) {\r\n // O backend devolve um codigo tecnico (ex: \"failed_to_compute\") e loga o\r\n // detalhe server-side. Ao leitor do dashboard vai uma mensagem em pt-BR.\r\n return (\r\n <WidgetFrame\r\n name={type.replace('_', '-')}\r\n title={config?.label}\r\n state=\"error\"\r\n stateMessage={ERROR_MESSAGES[String(computed.error)]}\r\n />\r\n );\r\n }\r\n\r\n // Widgets de dados usam apenas as cores de series (5 primeiras).\r\n // UI colors sao aplicadas via CSS vars no grid container.\r\n const seriesColors = getSeries(palette);\r\n\r\n switch (type) {\r\n case 'kpi_card':\r\n return <KPIWidget data={computed} label={config?.label} />;\r\n case 'gauge':\r\n return <GaugeWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'chart':\r\n return <ChartWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'composition':\r\n return <CompositionWidget data={computed} palette={seriesColors} label={config?.label} />;\r\n case 'table':\r\n return <TableWidget data={computed} label={config?.label} />;\r\n case 'filter':\r\n return config && onFilterChange ? (\r\n <FilterWidget\r\n config={config as FilterConfig}\r\n value={filterValue || ''}\r\n options={filterOptions}\r\n dateBounds={dateBounds}\r\n onChange={onFilterChange}\r\n />\r\n ) : null;\r\n case 'variable': {\r\n const vc = config as VariableConfig | undefined;\r\n return vc && onVariableChange ? (\r\n <VariableWidget\r\n config={vc}\r\n value={variableValue ?? vc.variableValue ?? 0}\r\n onChange={onVariableChange}\r\n />\r\n ) : null;\r\n }\r\n case 'color_palette':\r\n return config && onPaletteChange ? (\r\n <ColorPaletteWidget\r\n config={config as PaletteConfig}\r\n palette={palette}\r\n onChange={onPaletteChange}\r\n />\r\n ) : null;\r\n default:\r\n return <WidgetFrame name=\"unknown\" state=\"unconfigured\" />;\r\n }\r\n}\r\n","// Purpose: Componente top-level que renderiza um dashboard completo.\n// Scope: Busca layout + render da API Action com o token, aplica paleta como CSS vars,\n// renderiza grid com widgets interativos (filtros + variaveis + paleta).\n// Public API: Dashboard, DashboardProps\n\nimport { useMemo } from 'react';\nimport type { CSSProperties, ReactNode } from 'react';\nimport { useDashboardData } from './hooks/useDashboardData';\nimport { useGridGeometry } from './hooks/useGridGeometry';\nimport { WidgetRenderer } from './widgets/WidgetRenderer';\nimport { getPaletteCssVars } from './palettes';\nimport { CONTROL_WIDGET_SET } from './types';\nimport type { WidgetDefinition } from './types';\nimport type { DashboardGeometry } from './utils/grid';\nimport {\n CELL_ASPECT, GRID_GAP_PX, GRID_PADDING_PX, MIN_CELL_HEIGHT_PX,\n computeGridHeight, computeWidgetAspect,\n} from './utils/grid';\n\nexport interface DashboardProps {\n /** Token Bearer de acesso ao dashboard. */\n token: string;\n /**\n * Proporcao largura/altura da celula do grid. Default 1 (celula quadrada).\n *\n * A largura da celula vem da largura do container dividida pelo numero de\n * colunas do layout; a altura e derivada desta proporcao. E o que mantem o\n * dashboard com a mesma forma em qualquer aplicacao que o embuta.\n */\n cellAspect?: number;\n /**\n * Largura de container, em px, abaixo da qual os widgets sao empilhados em\n * coluna unica, cada um preservando a propria proporcao. `'auto'` usa o\n * limiar natural do layout — o ponto em que a celula ficaria estreita demais\n * e a proporcao ja nao seria respeitada. Ausente: nunca empilha.\n */\n stackBelow?: number | 'auto';\n /**\n * Notificado a cada mudanca de geometria. A altura do dashboard varia com a\n * largura, entao um host de altura fixa deve usar `gridHeight` para se\n * dimensionar.\n */\n onGeometryChange?: (geometry: DashboardGeometry) => void;\n /** Desliga o aviso de corte emitido no console. */\n silenceWarnings?: boolean;\n /** Classe CSS adicional no container raiz. */\n className?: string;\n}\n\n/** Ordem de leitura — usada apenas ao empilhar, onde a ordem no DOM e a ordem visual. */\nconst byReadingOrder = (a: WidgetDefinition, b: WidgetDefinition) =>\n a.grid.y - b.grid.y || a.grid.x - b.grid.x;\n\nexport function Dashboard({\n token,\n cellAspect = CELL_ASPECT,\n stackBelow,\n onGeometryChange,\n silenceWarnings,\n className,\n}: DashboardProps) {\n const {\n layout, renderData, loading, error,\n filters, variables, palette,\n setFilter, setVariable, setPalette,\n } = useDashboardData(token);\n\n // Mede a raiz, nao o grid: a raiz existe desde o primeiro render (estados de\n // carga e erro tambem a usam), entao a largura ja e conhecida quando o grid\n // aparece — sem frame intermediario com a celula no tamanho minimo.\n const { rootRef, gridRef, stacked } = useGridGeometry({\n columns: layout?.gridColumns ?? 0,\n cellAspect,\n stackBelow,\n onGeometryChange,\n silenceWarnings,\n });\n\n const widgets = useMemo(() => {\n const list = layout?.widgets ?? [];\n return stacked ? [...list].sort(byReadingOrder) : list;\n }, [layout?.widgets, stacked]);\n\n // Estaticas, mas derivadas de utils/grid: mante-las fora do CSS garante que a\n // geometria tenha uma fonte so. O React as escreve uma vez e nao volta mais.\n const rootStyle = {\n '--dash-gap': `${GRID_GAP_PX}px`,\n '--dash-pad': `${GRID_PADDING_PX}px`,\n } as CSSProperties;\n\n const rootClass = ['preview-tab', className].filter(Boolean).join(' ');\n\n let body: ReactNode;\n\n if (error && !layout) {\n body = <div className=\"preview-tab__error\">{error}</div>;\n } else if (!layout) {\n body = <div className=\"preview-tab__loading\">Carregando dashboard...</div>;\n } else if (layout.widgets.length === 0) {\n body = <div className=\"preview-tab__empty\">Este dashboard nao possui widgets.</div>;\n } else {\n const widgetsData = renderData?.widgets ?? {};\n const dateBounds = renderData?.date_bounds ?? null;\n\n // --dash-cell-h e escrita na raiz pelo useGridGeometry, fora do React.\n // Aqui ficam apenas as medidas que mudam com o layout, nao com o resize.\n const gridStyle = {\n '--dash-cols': layout.gridColumns,\n '--dash-rows': layout.gridRows,\n ...getPaletteCssVars(palette),\n } as CSSProperties;\n\n const gridClass = ['preview-tab__grid', stacked && 'preview-tab__grid--stacked']\n .filter(Boolean).join(' ');\n\n body = (\n <>\n {error && !renderData && <div className=\"preview-tab__error\">{error}</div>}\n\n {renderData && (\n <div className={gridClass} style={gridStyle} ref={gridRef}>\n {widgets.map((widget) => {\n const isControl = CONTROL_WIDGET_SET.has(widget.type);\n const computed = widgetsData[widget.id];\n\n // Empilhado, a proporcao do widget vira aspect-ratio em CSS puro:\n // nao depende de medicao, entao o resize nao re-renderiza nada.\n // O piso evita que um widget largo e baixo (ex.: 30x2) vire uma\n // faixa de poucos pixels ao ocupar a largura inteira.\n const widgetStyle: CSSProperties = stacked\n ? {\n gridColumn: 1,\n aspectRatio: `${computeWidgetAspect(widget.grid.w, widget.grid.h, cellAspect)}`,\n minHeight: `${computeGridHeight(widget.grid.h, MIN_CELL_HEIGHT_PX, GRID_GAP_PX, 0)}px`,\n }\n : {\n gridColumn: `${widget.grid.x + 1} / span ${widget.grid.w}`,\n gridRow: `${widget.grid.y + 1} / span ${widget.grid.h}`,\n };\n\n const variableValue = widget.type === 'variable'\n ? variables[widget.id] ?? (computed?.value as number) ?? widget.config.variableValue ?? 0\n : undefined;\n\n return (\n <div\n key={widget.id}\n className={`preview-tab__widget ${isControl ? 'preview-tab__widget--control' : ''}`}\n style={widgetStyle}\n >\n {isControl || computed ? (\n <WidgetRenderer\n type={widget.type}\n computed={computed || {}}\n palette={palette}\n config={widget.config}\n filterValue={filters[widget.id] || ''}\n filterOptions={\n // Estruturais: vem do /layout (cacheavel), nao do /render —\n // recalcula-los a cada render custaria um DISTINCT por filtro.\n widget.type === 'filter' ? widget.config.availableValues ?? [] : []\n }\n dateBounds={dateBounds}\n onFilterChange={(val) => setFilter(widget.id, val)}\n variableValue={variableValue}\n onVariableChange={(val) => setVariable(widget.id, val)}\n onPaletteChange={setPalette}\n />\n ) : (\n <div className=\"preview-tab__widget-loading\">\n {loading ? 'Carregando...' : 'Sem dados'}\n </div>\n )}\n </div>\n );\n })}\n </div>\n )}\n\n {loading && renderData && (\n <div className=\"preview-tab__recalculating\">Atualizando...</div>\n )}\n </>\n );\n }\n\n return <div className={rootClass} style={rootStyle} ref={rootRef}>{body}</div>;\n}\n","// Purpose: Entrega de arquivo ao usuario a partir de um blob em memoria.\n// Scope: Usado pelo download de PDF do demonstrativo, cujo conteudo chega por\n// fetch autenticado — nao ha URL publica para apontar um link.\n// Public API: downloadBlob, toFileName\n\n/** Dispara o download de um blob com o nome informado. */\nexport function downloadBlob(blob: Blob, fileName: string): void {\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = fileName;\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n // Revogar no mesmo tick corta o download em alguns navegadores: o clique so\n // agenda a leitura da URL. Um turno de event loop basta para ela comecar.\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\n// Faixa Unicode das marcas de acentuacao combinantes.\nconst COMBINING_FIRST = 0x0300;\nconst COMBINING_LAST = 0x036f;\n\n/** Remove acentuacao preservando a letra base (\"Balanço\" -> \"Balanco\"). */\nfunction stripDiacritics(text: string): string {\n // normalize('NFD') separa a letra da marca de acentuacao; sobra descartar as marcas.\n return Array.from(text.normalize('NFD'))\n .filter((char) => {\n const code = char.codePointAt(0) ?? 0;\n return code < COMBINING_FIRST || code > COMBINING_LAST;\n })\n .join('');\n}\n\n/**\n * Converte um titulo em nome de arquivo seguro.\n *\n * Acentos viram a letra base e o que nao for alfanumerico vira hifen: o nome\n * atravessa sistemas de arquivos diferentes sem depender de normalizacao do SO.\n */\nexport function toFileName(title: string, extension: string): string {\n const slug = stripDiacritics(title)\n .replace(/[^a-zA-Z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .toLowerCase();\n return `${slug || 'documento'}.${extension}`;\n}\n","// Purpose: Hook que gerencia estado + fetch de um demonstrativo inteiro.\n// Scope: Carrega o layout uma vez e recomputa o documento com debounce quando a\n// janela ou os filtros mudam. Tambem entrega o PDF, que le a MESMA janela\n// do documento na tela — o arquivo baixado nunca mostra outro recorte.\n// Public API: useStatementData\n\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport {\n fetchStatementLayout, fetchStatementPdf, fetchStatementRender,\n} from '../api/fetcher';\nimport { buildQueryParams, syncFiltersFromApplied } from '../api/params';\nimport { downloadBlob, toFileName } from '../utils/download';\nimport type { StatementLayoutResponse, StatementRenderResponse } from '../types/statement';\n\nexport interface UseStatementDataResult {\n layout: StatementLayoutResponse | null;\n renderData: StatementRenderResponse | null;\n loading: boolean;\n error: string | null;\n /** Filtros selecionados (formato string por id — temporais como \"start|end\"). */\n filters: Record<string, string>;\n setFilter(filterId: string, value: string): void;\n downloadPdf(): void;\n downloading: boolean;\n}\n\nconst DEBOUNCE_MS = 300;\n\nexport function useStatementData(token: string): UseStatementDataResult {\n const [layout, setLayout] = useState<StatementLayoutResponse | null>(null);\n const [renderData, setRenderData] = useState<StatementRenderResponse | null>(null);\n const [filters, setFilters] = useState<Record<string, string>>({});\n const [loading, setLoading] = useState(true);\n const [error, setError] = useState<string | null>(null);\n const [downloading, setDownloading] = useState(false);\n\n const debounceRef = useRef<ReturnType<typeof setTimeout>>();\n const appliedSyncedRef = useRef(false);\n\n // -------Carrega o layout uma unica vez (por token)-------\n useEffect(() => {\n let cancelled = false;\n fetchStatementLayout(token)\n .then((res) => { if (!cancelled) setLayout(res); })\n .catch((err: Error) => { if (!cancelled) setError(err.message); });\n return () => { cancelled = true; };\n }, [token]);\n\n // -------Recomputa com debounce quando a janela ou os filtros mudam-------\n useEffect(() => {\n if (!layout) return;\n if (debounceRef.current) clearTimeout(debounceRef.current);\n\n debounceRef.current = setTimeout(() => {\n setLoading(true);\n fetchStatementRender(token, buildQueryParams(filters))\n .then((res) => {\n setRenderData(res);\n // Os defaults dos filtros sao resolvidos no backend; a primeira resposta\n // e a unica que pode ensina-los ao estado local.\n if (!appliedSyncedRef.current && res.applied) {\n appliedSyncedRef.current = true;\n setFilters((prev) => ({ ...syncFiltersFromApplied(res.applied), ...prev }));\n }\n setError(null);\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setLoading(false));\n }, DEBOUNCE_MS);\n\n return () => {\n if (debounceRef.current) clearTimeout(debounceRef.current);\n };\n }, [token, layout, filters]);\n\n const setFilter = useCallback((filterId: string, value: string) => {\n setFilters((prev) => ({ ...prev, [filterId]: value }));\n }, []);\n\n const downloadPdf = useCallback(() => {\n setDownloading(true);\n fetchStatementPdf(token, buildQueryParams(filters))\n .then((blob) => {\n downloadBlob(blob, toFileName(layout?.name ?? 'demonstrativo', 'pdf'));\n setError(null);\n })\n .catch((err: Error) => setError(err.message))\n .finally(() => setDownloading(false));\n }, [token, filters, layout?.name]);\n\n return {\n layout, renderData, loading, error,\n filters, setFilter,\n downloadPdf, downloading,\n };\n}\n","// Purpose: Componente top-level que renderiza um demonstrativo completo.\n// Scope: Busca layout + render da API Action com o token e desenha o documento\n// (linhas x colunas de periodo). NAO calcula nada: valores, formatacao e\n// analises chegam prontos do backend — e a mesma resposta que qualquer\n// consumidor da API recebe, entao o documento e identico em todo lugar.\n// Public API: Statement, StatementProps\n\nimport type { CSSProperties, ReactNode } from 'react';\nimport { useStatementData } from './hooks/useStatementData';\nimport { getPaletteCssVars } from './palettes';\nimport { formatValue } from './utils/format';\nimport { DashboardDatePicker } from './components/DashboardDatePicker';\nimport { SearchableSelect } from './components/SearchableSelect';\nimport { WINDOW_FILTER_ID } from './api/params';\nimport type { FilterDefinition } from './types';\nimport type { StatementComputedLine } from './types/statement';\n\nexport interface StatementProps {\n /** Token Bearer de acesso ao demonstrativo. */\n token: string;\n /**\n * Paleta de 15 cores, no mesmo formato do dashboard. Serve a quem embute os\n * dois lado a lado e quer a mesma identidade visual; ausente, usa a paleta\n * padrao da plataforma.\n */\n palette?: string[];\n /** Botao de download do PDF. Default true. */\n showDownload?: boolean;\n /** Classe CSS adicional no container raiz. */\n className?: string;\n}\n\ntype DateBounds = { min: string | null; max: string | null };\n\nconst LABEL_PADDING_PX = 8;\nconst INDENT_STEP_PX = 14;\n\n/** Recuo do rotulo conforme o nivel declarado na linha. */\nfunction labelStyle(indent: number): CSSProperties {\n return { paddingLeft: `${LABEL_PADDING_PX + indent * INDENT_STEP_PX}px` };\n}\n\n// -------Controles da barra-------\n\nfunction DateRangeControl({ label, value, bounds, onChange }: {\n label: string;\n value: string;\n bounds: DateBounds;\n onChange: (value: string) => void;\n}) {\n const [start, end] = value ? value.split('|') : ['', ''];\n\n return (\n <div className=\"stmt__filter stmt__filter--range\">\n <span className=\"stmt__filter-label\">{label}</span>\n <div className=\"stmt__filter-range\">\n <DashboardDatePicker\n value={start}\n minIso={bounds.min}\n maxIso={end || bounds.max}\n selectsStart\n startIso={start}\n endIso={end}\n placeholder=\"Início\"\n onChange={(iso) => onChange(`${iso}|${end}`)}\n />\n <DashboardDatePicker\n value={end}\n minIso={start || bounds.min}\n maxIso={bounds.max}\n selectsEnd\n startIso={start}\n endIso={end}\n placeholder=\"Fim\"\n onChange={(iso) => onChange(`${start}|${iso}`)}\n />\n </div>\n </div>\n );\n}\n\nfunction StatementFilter({ definition, value, options, bounds, onChange }: {\n definition: FilterDefinition;\n value: string;\n options: string[];\n bounds: DateBounds;\n onChange: (value: string) => void;\n}) {\n if (definition.type === 'date_range') {\n return (\n <DateRangeControl\n label={definition.label}\n value={value}\n bounds={bounds}\n onChange={onChange}\n />\n );\n }\n\n return (\n <div className=\"stmt__filter\">\n <span className=\"stmt__filter-label\">{definition.label}</span>\n <SearchableSelect\n value={value}\n options={options}\n multi={definition.type === 'multi_select'}\n onChange={onChange}\n />\n </div>\n );\n}\n\n// -------Linha do documento-------\n\nfunction StatementRow({ line, columnCount, showTotal, showVertical, showHorizontal }: {\n line: StatementComputedLine;\n columnCount: number;\n showTotal: boolean;\n showVertical: boolean;\n showHorizontal: boolean;\n}) {\n if (line.type === 'separator') {\n return (\n <tr className=\"stmt__row stmt__row--separator\">\n <td colSpan={columnCount} />\n </tr>\n );\n }\n\n // Cabecalho sem valores abre a secao ocupando a largura do documento. Com\n // valores, ele consolida o bloco e se desenha como qualquer outra linha —\n // mantendo a classe de cabecalho, que e o que o mantem lido como abertura.\n if (line.type === 'header' && line.formatted.length === 0) {\n return (\n <tr className=\"stmt__row stmt__row--header\">\n <th scope=\"row\" style={labelStyle(line.style.indent)}>{line.label}</th>\n <td colSpan={columnCount - 1} />\n </tr>\n );\n }\n\n const rowClass = [\n 'stmt__row',\n `stmt__row--${line.type}`,\n line.style.bold && 'stmt__row--bold',\n ].filter(Boolean).join(' ');\n\n return (\n <tr className={rowClass}>\n <th scope=\"row\" style={labelStyle(line.style.indent)}>{line.label}</th>\n\n {line.formatted.map((text, index) => {\n const horizontal = line.horizontalAnalysis[index];\n\n return (\n <td key={index} className=\"stmt__value\">\n <span className=\"stmt__number\">{text}</span>\n\n {showVertical && line.verticalAnalysis[index] != null && (\n <span className=\"stmt__aux\" title=\"Análise vertical\">\n {formatValue(line.verticalAnalysis[index], 'percentage')}\n </span>\n )}\n\n {showHorizontal && horizontal != null && (\n <span\n className={`stmt__aux stmt__aux--${horizontal < 0 ? 'down' : 'up'}`}\n title=\"Variação sobre o período anterior\"\n >\n {formatValue(horizontal, 'percentage')}\n </span>\n )}\n </td>\n );\n })}\n\n {showTotal && (\n <td className=\"stmt__value stmt__value--total\">\n <span className=\"stmt__number\">{line.totalFormatted ?? '-'}</span>\n </td>\n )}\n </tr>\n );\n}\n\n// -------Componente principal-------\n\nexport function Statement({ token, palette, showDownload = true, className }: StatementProps) {\n const {\n layout, renderData, loading, error,\n filters, setFilter, downloadPdf, downloading,\n } = useStatementData(token);\n\n const rootClass = ['stmt', className].filter(Boolean).join(' ');\n const rootStyle = getPaletteCssVars(palette) as CSSProperties;\n\n let body: ReactNode;\n\n if (error && !layout) {\n body = <div className=\"stmt__error\">{error}</div>;\n } else if (!layout) {\n body = <div className=\"stmt__state\">Carregando demonstrativo...</div>;\n } else {\n const bounds: DateBounds = renderData?.dateBounds ?? layout.dateBounds;\n const showTotal = layout.periods.showTotal;\n\n // A janela embutida so aparece quando o documento NAO declara um filtro de\n // data: as duas escreveriam o mesmo par de parametros na request, e o autor\n // que declarou um filtro ja decidiu como o recorte se escolhe.\n const hasDeclaredWindow = layout.filters.some((f) => f.type === 'date_range');\n\n const columns = renderData?.columns ?? [];\n const lines = renderData?.lines ?? [];\n const columnCount = 1 + columns.length + (showTotal ? 1 : 0);\n const showVertical = lines.some((line) => line.verticalAnalysis.length > 0);\n const showHorizontal = lines.some((line) => line.horizontalAnalysis.length > 0);\n\n body = (\n <>\n <div className=\"stmt__toolbar\">\n {!hasDeclaredWindow && (\n <DateRangeControl\n label=\"Período\"\n value={filters[WINDOW_FILTER_ID] ?? ''}\n bounds={bounds}\n onChange={(value) => setFilter(WINDOW_FILTER_ID, value)}\n />\n )}\n\n {layout.filters.map((definition) => (\n <StatementFilter\n key={definition.id}\n definition={definition}\n value={filters[definition.id] ?? ''}\n options={layout.filterOptions[definition.id] ?? []}\n bounds={bounds}\n onChange={(value) => setFilter(definition.id, value)}\n />\n ))}\n\n <div className=\"stmt__toolbar-end\">\n <span className=\"stmt__bounds\">\n Base: {bounds.min} a {bounds.max}\n </span>\n {showDownload && (\n <button\n type=\"button\"\n className=\"stmt__download\"\n onClick={downloadPdf}\n disabled={downloading || !renderData}\n title=\"Baixar o documento em PDF\"\n >\n {downloading ? 'Gerando...' : 'Baixar PDF'}\n </button>\n )}\n </div>\n </div>\n\n {error && <div className=\"stmt__error\">{error}</div>}\n\n {renderData?.truncated && (\n <div className=\"stmt__warning\">\n A janela pedida excede o limite de colunas: o documento mostra as\n primeiras {columns.length}. Escolha um período menor ou uma coluna\n mais larga.\n </div>\n )}\n\n {!renderData ? (\n <div className=\"stmt__state\">Calculando...</div>\n ) : columns.length === 0 ? (\n <div className=\"stmt__state\">\n Nenhum período na janela selecionada.\n </div>\n ) : lines.length === 0 ? (\n <div className=\"stmt__state\">Este demonstrativo não possui linhas.</div>\n ) : (\n <div className=\"stmt__scroll\">\n <table className=\"stmt__table\">\n <thead>\n <tr>\n <th className=\"stmt__corner\" scope=\"col\">{renderData.name}</th>\n {columns.map((column) => (\n <th key={column.key} scope=\"col\" title={`${column.start} a ${column.end}`}>\n {column.label}\n </th>\n ))}\n {showTotal && (\n <th scope=\"col\" className=\"stmt__total-head\">\n {layout.periods.totalLabel}\n </th>\n )}\n </tr>\n </thead>\n <tbody>\n {lines.map((line) => (\n <StatementRow\n key={line.id}\n line={line}\n columnCount={columnCount}\n showTotal={showTotal}\n showVertical={showVertical}\n showHorizontal={showHorizontal}\n />\n ))}\n </tbody>\n </table>\n </div>\n )}\n\n {loading && renderData && (\n <div className=\"stmt__recalculating\">Atualizando...</div>\n )}\n </>\n );\n }\n\n return <div className={rootClass} style={rootStyle}>{body}</div>;\n}\n"],"names":["WINDOW_FILTER_ID","buildQueryParams","filters","variables","params","key","val","start","end","syncFiltersFromApplied","applied","synced","id","d","MULTI_VALUE_SEPARATOR","DEBOUNCE_MS","useDashboardData","token","layout","setLayout","useState","renderData","setRenderData","setFilters","setVariables","localPalette","setLocalPalette","loading","setLoading","error","setError","debounceRef","useRef","appliedSyncedRef","useEffect","cancelled","fetchLayout","res","err","fetchRender","prev","setFilter","useCallback","widgetId","value","setVariable","setPalette","colors","palette","useMemo","readInlineSize","entry","_b","_a","readBlockSize","resolveStackThreshold","stackBelow","columns","aspect","computeStackThreshold","findClippingAncestor","element","node","overflowY","useGridGeometry","options","optionsRef","rootElRef","gridElRef","observerRef","frameRef","geometryRef","widthRef","gridHeightRef","stackedRef","warnedRef","appliedWidthRef","stacked","setStacked","warnIfClipped","geometry","grid","ancestor","emit","cellAspect","containerWidth","cellWidth","computeCellWidth","next","computeCellHeight","apply","force","root","width","threshold","nextStacked","cancelFrame","scheduleFrame","handleEntries","entries","ensureObserver","rootRef","observer","gridRef","STATE_MESSAGES","WidgetState","kind","message","jsx","WidgetFrame","name","title","state","stateMessage","toolbar","children","jsxs","TREND_ARROWS","visibleComparisons","raw","c","ComparisonLine","comparison","primary","sentiment","arrow","KPIWidget","data","label","formatted","comparisons","i","COLOR_EMPTY","FILL_THRESHOLDS","arcPath","cx","cy","r","fraction","angle","GaugeWidget","propLabel","ratio","format","valueFormatted","formatCompact","ratioFormatted","extras","targetFormatted","comparisonLabel","exceeded","clamped","min","fillColor","stroke","useContainerSize","ref","size","setSize","el","height","AXIS_STYLE","GRID_STROKE","TOOLTIP_CONTENT_STYLE","TOOLTIP_LABEL_STYLE","tooltipLabelFormatter","payload","first","verbose","CartesianChart","Chart","chartData","xKey","series","renderSeries","CartesianGrid","XAxis","YAxis","Tooltip","Legend","s","ChartWidget","chartType","containerRef","renderChart","common","LineChart","color","Line","AreaChart","Area","BarChart","Bar","TOOLTIP_CURSOR","barColor","bar","CompositionTooltip","active","CompositionWidget","display","bars","renderBridge","v","Cell","renderPie","PieChart","Pie","percent","_","trendClass","n","fittingRows","total","availableHeight","head","firstRow","rowHeight","fits","TableWidget","rows","clip","numbered","headRef","bodyRef","visible","isNumericFormat","row","numeric","formatValue","FilterWidget","config","dateBounds","onChange","filterType","dateMode","YearlyFilter","MonthlyFilter","WeeklyFilter","DateRangeFilter","SelectFilter","DashboardDatePicker","iso","parsed","parseYearFromRange","now","selectedYear","years","getYearRange","handleYearChange","year","yr","getFullYearRange","e","y","parseMonthFromRange","selectedMonth","handleMonthChange","month","range","getMonthRange","MONTH_NAMES_SHORT","monthWeeks","getMonthWeeks","selectedWeekIdx","parseMonthWeekFromRange","w","m","multi","searchable","SearchableSelect","selected","toggle","opt","FORMAT_SUFFIX","VariableWidget","locked","fmt","suffix","ColorPaletteWidget","ColorPaletteSelector","ERROR_MESSAGES","WidgetRenderer","type","computed","filterValue","filterOptions","onFilterChange","variableValue","onVariableChange","onPaletteChange","seriesColors","getSeries","vc","byReadingOrder","a","b","Dashboard","CELL_ASPECT","onGeometryChange","silenceWarnings","className","widgets","list","rootStyle","GRID_GAP_PX","GRID_PADDING_PX","rootClass","body","widgetsData","gridStyle","getPaletteCssVars","gridClass","Fragment","widget","isControl","CONTROL_WIDGET_SET","widgetStyle","computeWidgetAspect","computeGridHeight","MIN_CELL_HEIGHT_PX","downloadBlob","blob","fileName","url","anchor","COMBINING_FIRST","COMBINING_LAST","stripDiacritics","text","char","code","toFileName","extension","useStatementData","downloading","setDownloading","fetchStatementLayout","fetchStatementRender","filterId","downloadPdf","fetchStatementPdf","LABEL_PADDING_PX","INDENT_STEP_PX","labelStyle","indent","DateRangeControl","bounds","StatementFilter","definition","StatementRow","line","columnCount","showTotal","showVertical","showHorizontal","rowClass","index","horizontal","Statement","showDownload","hasDeclaredWindow","f","lines","column"],"mappings":"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"}
|
package/dist/styles.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
@charset "UTF-8";.react-datepicker__navigation-icon:before,.react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view--down-arrow{border-color:#ccc;border-style:solid;border-width:3px 3px 0 0;content:"";display:block;height:9px;position:absolute;top:6px;width:9px}.react-datepicker__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.react-datepicker-wrapper{display:inline-block;padding:0;border:0}.react-datepicker{font-family:Helvetica Neue,helvetica,arial,sans-serif;font-size:.8rem;background-color:#fff;color:#000;border:1px solid #aeaeae;border-radius:.3rem;display:inline-block;position:relative;line-height:initial}.react-datepicker--time-only .react-datepicker__time-container{border-left:0}.react-datepicker--time-only .react-datepicker__time,.react-datepicker--time-only .react-datepicker__time-box{border-bottom-left-radius:.375em;border-bottom-right-radius:.375em}.react-datepicker-popper{z-index:1;line-height:0}.react-datepicker-popper .react-datepicker__triangle{stroke:#aeaeae}.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle{fill:#f0f0f0;color:#f0f0f0}.react-datepicker-popper[data-placement^=top] .react-datepicker__triangle,.react-datepicker-popper--header-middle[data-placement^=bottom] .react-datepicker__triangle,.react-datepicker-popper--header-bottom[data-placement^=bottom] .react-datepicker__triangle{fill:#fff;color:#fff}.react-datepicker-popper--header-bottom[data-placement^=top] .react-datepicker__triangle{fill:#f0f0f0;color:#f0f0f0}.react-datepicker__header{text-align:center;background-color:#f0f0f0;border-bottom:1px solid #aeaeae;border-top-left-radius:.3rem;padding:8px 0;position:relative}.react-datepicker__header--time{padding-bottom:8px;padding-left:5px;padding-right:5px}.react-datepicker__header--time:not(.react-datepicker__header--time--only){border-top-left-radius:0}.react-datepicker__header:not(.react-datepicker__header--has-time-select,.react-datepicker__header--middle,.react-datepicker__header--bottom){border-top-right-radius:.3rem}.react-datepicker__header--middle{border-top:1px solid #aeaeae;border-radius:0;margin-top:4px}.react-datepicker__header--bottom{border-bottom:none;border-top:1px solid #aeaeae;border-radius:0 0 .3rem .3rem}.react-datepicker__header-wrapper{position:relative}.react-datepicker__header-wrapper .react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button){right:2px}.react-datepicker__year-dropdown-container--select,.react-datepicker__month-dropdown-container--select,.react-datepicker__month-year-dropdown-container--select,.react-datepicker__year-dropdown-container--scroll,.react-datepicker__month-dropdown-container--scroll,.react-datepicker__month-year-dropdown-container--scroll{display:inline-block;margin:0 15px}.react-datepicker__month-select,.react-datepicker__year-select,.react-datepicker__month-year-select{background-color:transparent;border:1px solid #aeaeae;border-radius:.3rem;color:inherit;cursor:pointer;font-family:inherit;font-size:inherit;margin-top:5px;padding:2px 5px}.react-datepicker__month-select:focus-visible,.react-datepicker__year-select:focus-visible,.react-datepicker__month-year-select:focus-visible{outline:auto 1px}.react-datepicker__current-month,.react-datepicker-time__header,.react-datepicker-year-header{margin-top:0;color:#000;font-weight:700;font-size:.944rem}h2.react-datepicker__current-month{padding:0;margin:0}.react-datepicker-time__header{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.react-datepicker__navigation{align-items:center;background:none;display:flex;justify-content:center;text-align:center;cursor:pointer;position:absolute;top:2px;padding:0;border:none;z-index:1;height:32px;width:32px;text-indent:-999em;overflow:hidden}.react-datepicker__navigation--previous{left:2px}.react-datepicker__navigation--next{right:2px}.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button){right:85px}.react-datepicker__navigation--years{position:relative;top:0;display:block;margin-left:auto;margin-right:auto}.react-datepicker__navigation--years-previous{top:4px}.react-datepicker__navigation--years-upcoming{top:-4px}.react-datepicker__navigation:hover *:before{border-color:#a6a6a6}.react-datepicker__navigation-icon{position:relative;top:-1px;font-size:20px;width:0}.react-datepicker__navigation-icon--next{left:-2px}.react-datepicker__navigation-icon--next:before{transform:rotate(45deg);left:-7px}.react-datepicker__navigation-icon--previous{right:-2px}.react-datepicker__navigation-icon--previous:before{transform:rotate(225deg);right:-7px}.react-datepicker__month-container{float:left}.react-datepicker__year{margin:.5em;text-align:center}.react-datepicker__year-wrapper{display:flex;flex-wrap:wrap;max-width:180px}.react-datepicker__year .react-datepicker__year-text{display:inline-block;width:5em;margin:2px}.react-datepicker__month{margin:.5em;text-align:center}.react-datepicker__month .react-datepicker__month-text,.react-datepicker__month .react-datepicker__quarter-text{display:inline-block;width:5em;margin:2px}.react-datepicker__input-time-container{clear:both;width:100%;float:left;margin:5px 0 10px 15px;text-align:left}.react-datepicker__input-time-container .react-datepicker-time__caption,.react-datepicker__input-time-container .react-datepicker-time__input-container{display:inline-block}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input{display:inline-block;margin-left:10px}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input{width:auto}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]::-webkit-inner-spin-button,.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]{-moz-appearance:textfield}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__delimiter{margin-left:5px;display:inline-block}.react-datepicker__time-container{float:right;border-left:1px solid #aeaeae;width:85px}.react-datepicker__time-container--with-today-button{display:inline;border:1px solid #aeaeae;border-radius:.375em;position:absolute;right:-87px;top:0}.react-datepicker__time-container .react-datepicker__time{position:relative;background:#fff;border-bottom-right-radius:.375em}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box{width:85px;overflow-x:hidden;margin:0 auto;text-align:center;border-bottom-right-radius:.375em}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list{list-style:none;margin:0;height:calc(195px + 1.0625em);overflow-y:scroll;padding-right:0;padding-left:0;width:100%;box-sizing:content-box}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item{height:30px;padding:5px 10px;white-space:nowrap}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:hover{cursor:pointer;background-color:#f0f0f0}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected{background-color:#216ba5;color:#fff;font-weight:700}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected:hover{background-color:#216ba5}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled{color:#ccc}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled:hover{cursor:default;background-color:transparent}.react-datepicker__week-number{color:#ccc;display:inline-block;width:2.125em;line-height:2.125em;text-align:center;margin:.208em}.react-datepicker__week-number.react-datepicker__week-number--clickable{cursor:pointer}.react-datepicker__week-number.react-datepicker__week-number--clickable:not(.react-datepicker__week-number--selected):hover{border-radius:.3rem;background-color:#f0f0f0}.react-datepicker__week-number--selected{border-radius:.3rem;background-color:#216ba5;color:#fff}.react-datepicker__week-number--selected:hover{background-color:#1d5d90}.react-datepicker__day-names{text-align:center;white-space:nowrap;margin-bottom:-8px}.react-datepicker__week{white-space:nowrap}.react-datepicker__day-name,.react-datepicker__day,.react-datepicker__time-name{color:#000;display:inline-block;width:2.125em;line-height:2.125em;text-align:center;margin:.208em}.react-datepicker__day-name--disabled,.react-datepicker__day--disabled,.react-datepicker__time-name--disabled{cursor:default;color:#ccc}.react-datepicker__day,.react-datepicker__month-text,.react-datepicker__quarter-text,.react-datepicker__year-text{cursor:pointer}.react-datepicker__day:not([aria-disabled=true]):hover,.react-datepicker__month-text:not([aria-disabled=true]):hover,.react-datepicker__quarter-text:not([aria-disabled=true]):hover,.react-datepicker__year-text:not([aria-disabled=true]):hover{border-radius:.3rem;background-color:#f0f0f0}.react-datepicker__day--today,.react-datepicker__month-text--today,.react-datepicker__quarter-text--today,.react-datepicker__year-text--today{font-weight:700}.react-datepicker__day--highlighted,.react-datepicker__month-text--highlighted,.react-datepicker__quarter-text--highlighted,.react-datepicker__year-text--highlighted{border-radius:.3rem;background-color:#3dcc4a;color:#fff}.react-datepicker__day--highlighted:not([aria-disabled=true]):hover,.react-datepicker__month-text--highlighted:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--highlighted:not([aria-disabled=true]):hover,.react-datepicker__year-text--highlighted:not([aria-disabled=true]):hover{background-color:#32be3f}.react-datepicker__day--highlighted-custom-1,.react-datepicker__month-text--highlighted-custom-1,.react-datepicker__quarter-text--highlighted-custom-1,.react-datepicker__year-text--highlighted-custom-1{color:#f0f}.react-datepicker__day--highlighted-custom-2,.react-datepicker__month-text--highlighted-custom-2,.react-datepicker__quarter-text--highlighted-custom-2,.react-datepicker__year-text--highlighted-custom-2{color:green}.react-datepicker__day--holidays,.react-datepicker__month-text--holidays,.react-datepicker__quarter-text--holidays,.react-datepicker__year-text--holidays{position:relative;border-radius:.3rem;background-color:#ff6803;color:#fff}.react-datepicker__day--holidays .overlay,.react-datepicker__month-text--holidays .overlay,.react-datepicker__quarter-text--holidays .overlay,.react-datepicker__year-text--holidays .overlay{position:absolute;bottom:100%;left:50%;transform:translate(-50%);background-color:#333;color:#fff;padding:4px;border-radius:4px;white-space:nowrap;visibility:hidden;opacity:0;transition:visibility 0s,opacity .3s ease-in-out}.react-datepicker__day--holidays:not([aria-disabled=true]):hover,.react-datepicker__month-text--holidays:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--holidays:not([aria-disabled=true]):hover,.react-datepicker__year-text--holidays:not([aria-disabled=true]):hover{background-color:#cf5300}.react-datepicker__day--holidays:hover .overlay,.react-datepicker__month-text--holidays:hover .overlay,.react-datepicker__quarter-text--holidays:hover .overlay,.react-datepicker__year-text--holidays:hover .overlay{visibility:visible;opacity:1}.react-datepicker__day--selected,.react-datepicker__day--in-selecting-range,.react-datepicker__day--in-range,.react-datepicker__month-text--selected,.react-datepicker__month-text--in-selecting-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--selected,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--selected,.react-datepicker__year-text--in-selecting-range,.react-datepicker__year-text--in-range{border-radius:.3rem;background-color:#216ba5;color:#fff}.react-datepicker__day--selected:not([aria-disabled=true]):hover,.react-datepicker__day--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__day--in-range:not([aria-disabled=true]):hover,.react-datepicker__month-text--selected:not([aria-disabled=true]):hover,.react-datepicker__month-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__month-text--in-range:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--selected:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--in-range:not([aria-disabled=true]):hover,.react-datepicker__year-text--selected:not([aria-disabled=true]):hover,.react-datepicker__year-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__year-text--in-range:not([aria-disabled=true]):hover{background-color:#1d5d90}.react-datepicker__day--keyboard-selected,.react-datepicker__month-text--keyboard-selected,.react-datepicker__quarter-text--keyboard-selected,.react-datepicker__year-text--keyboard-selected{border-radius:.3rem;background-color:#bad9f1;color:#000}.react-datepicker__day--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__month-text--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__year-text--keyboard-selected:not([aria-disabled=true]):hover{background-color:#1d5d90;color:#fff}.react-datepicker__day--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__month-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__quarter-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__year-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range){background-color:#216ba580}.react-datepicker__month--selecting-range .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__month-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__month-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__quarter-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__quarter-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__year-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__year-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range){background-color:#f0f0f0;color:#000}.react-datepicker__day--disabled,.react-datepicker__month-text--disabled,.react-datepicker__quarter-text--disabled,.react-datepicker__year-text--disabled{cursor:default;color:#ccc}.react-datepicker__day--disabled .overlay,.react-datepicker__month-text--disabled .overlay,.react-datepicker__quarter-text--disabled .overlay,.react-datepicker__year-text--disabled .overlay{position:absolute;bottom:70%;left:50%;transform:translate(-50%);background-color:#333;color:#fff;padding:4px;border-radius:4px;white-space:nowrap;visibility:hidden;opacity:0;transition:visibility 0s,opacity .3s ease-in-out}.react-datepicker__input-container{position:relative;display:inline-block;width:100%}.react-datepicker__input-container .react-datepicker__calendar-icon{position:absolute;padding:.625em;box-sizing:content-box}.react-datepicker__view-calendar-icon input{padding:6px 10px 5px 25px}.react-datepicker__year-read-view,.react-datepicker__month-read-view,.react-datepicker__month-year-read-view{border:1px solid transparent;border-radius:.3rem;position:relative}.react-datepicker__year-read-view:hover,.react-datepicker__month-read-view:hover,.react-datepicker__month-year-read-view:hover{cursor:pointer}.react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__year-read-view:hover .react-datepicker__month-read-view--down-arrow,.react-datepicker__month-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__month-year-read-view:hover .react-datepicker__month-read-view--down-arrow{border-top-color:#b3b3b3}.react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view--down-arrow{transform:rotate(135deg);right:-16px;top:0}.react-datepicker__year-dropdown,.react-datepicker__month-dropdown,.react-datepicker__month-year-dropdown{background-color:#f0f0f0;position:absolute;width:50%;left:25%;top:30px;z-index:1;text-align:center;border-radius:.3rem;border:1px solid #aeaeae}.react-datepicker__year-dropdown:hover,.react-datepicker__month-dropdown:hover,.react-datepicker__month-year-dropdown:hover{cursor:pointer}.react-datepicker__year-dropdown--scrollable,.react-datepicker__month-dropdown--scrollable,.react-datepicker__month-year-dropdown--scrollable{height:150px;overflow-y:scroll}.react-datepicker__year-option,.react-datepicker__month-option,.react-datepicker__month-year-option{line-height:20px;width:100%;display:block;margin-left:auto;margin-right:auto}.react-datepicker__year-option:first-of-type,.react-datepicker__month-option:first-of-type,.react-datepicker__month-year-option:first-of-type{border-top-left-radius:.3rem;border-top-right-radius:.3rem}.react-datepicker__year-option:last-of-type,.react-datepicker__month-option:last-of-type,.react-datepicker__month-year-option:last-of-type{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.react-datepicker__year-option:hover,.react-datepicker__month-option:hover,.react-datepicker__month-year-option:hover{background-color:#ccc}.react-datepicker__year-option:hover .react-datepicker__navigation--years-upcoming,.react-datepicker__month-option:hover .react-datepicker__navigation--years-upcoming,.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-upcoming{border-bottom-color:#b3b3b3}.react-datepicker__year-option:hover .react-datepicker__navigation--years-previous,.react-datepicker__month-option:hover .react-datepicker__navigation--years-previous,.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-previous{border-top-color:#b3b3b3}.react-datepicker__year-option--selected,.react-datepicker__month-option--selected,.react-datepicker__month-year-option--selected{position:absolute;left:15px}.react-datepicker__close-icon{cursor:pointer;background-color:transparent;border:0;outline:0;padding:0 6px 0 0;position:absolute;top:0;right:0;height:100%;display:table-cell;vertical-align:middle}.react-datepicker__close-icon:after{cursor:pointer;background-color:#216ba5;color:#fff;border-radius:50%;height:16px;width:16px;padding:2px;font-size:12px;line-height:1;text-align:center;display:table-cell;vertical-align:middle;content:"×"}.react-datepicker__close-icon--disabled{cursor:default}.react-datepicker__close-icon--disabled:after{cursor:default;background-color:#ccc}.react-datepicker__today-button{background:#f0f0f0;border-top:1px solid #aeaeae;cursor:pointer;text-align:center;font-weight:700;padding:5px 0;clear:left}.react-datepicker__portal{position:fixed;width:100vw;height:100vh;background-color:#000c;left:0;top:0;justify-content:center;align-items:center;display:flex;z-index:2147483647}.react-datepicker__children-container{width:17.25em;margin:.5em;padding-right:.25em;padding-left:.25em;height:auto}.react-datepicker__aria-live{position:absolute;clip-path:circle(0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;width:1px;white-space:nowrap}.react-datepicker__calendar-icon{width:1em;height:1em;vertical-align:-.125em}.react-datepicker-popper-offset{margin-top:-.7em}:where(.preview-tab,.stmt,.widget,.palette-selector,.ddp-field){--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 16px;--spacing-lg: 24px;--spacing-xl: 32px;--spacing-2xl: 48px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--transition-fast: .15s ease;--shadow-lg: 0 10px 25px rgba(0, 0, 0, .4)}.preview-tab{display:flex;flex-direction:column;gap:var(--spacing-md);position:relative}.preview-tab__empty{display:flex;align-items:center;justify-content:center;min-height:300px;color:var(--text-muted);font-size:.9rem;border:2px dashed var(--bg-elevated);border-radius:var(--radius-lg)}.preview-tab__loading{display:flex;align-items:center;justify-content:center;padding:var(--spacing-2xl) 0;color:var(--text-secondary)}.preview-tab__error{padding:var(--spacing-md);background:#f443361a;border:1px solid var(--color-error);border-radius:var(--radius-md);color:var(--color-error);font-size:.875rem;text-align:center}.preview-tab__grid{display:grid;grid-template-columns:repeat(var(--dash-cols, 30),1fr);grid-template-rows:repeat(var(--dash-rows, 10),var(--dash-cell-h, 40px));grid-auto-rows:var(--dash-cell-h, 40px);gap:var(--dash-gap, 6px);padding:var(--dash-pad, 16px);background:var(--bg-dark);border-radius:var(--radius-lg)}.preview-tab__grid--stacked{grid-template-columns:1fr;grid-template-rows:none;grid-auto-rows:auto}.preview-tab__widget{display:flex;background:var(--bg-elevated);border:1px solid rgba(255,255,255,.08);border-radius:var(--radius-md);overflow:hidden;min-height:0;container-type:size}.preview-tab__widget--control{background:var(--bg-elevated);border:1px dashed rgba(255,255,255,.15)}.preview-tab__widget-loading{display:flex;align-items:center;justify-content:center;height:100%;min-height:80px;color:var(--text-muted);font-size:.8125rem}.preview-tab__recalculating{position:fixed;bottom:var(--spacing-lg);right:var(--spacing-lg);padding:var(--spacing-sm) var(--spacing-lg);background:var(--bg-elevated);border:1px solid var(--action-orange);border-radius:var(--radius-md);color:var(--action-orange);font-size:.8125rem;font-weight:var(--font-weight-medium);box-shadow:var(--shadow-lg);z-index:50}.stmt{display:flex;flex-direction:column;gap:var(--spacing-md);position:relative;color:var(--text-primary)}.stmt__state{padding:var(--spacing-xl);text-align:center;font-size:.875rem;color:var(--text-secondary)}.stmt__error{padding:var(--spacing-md);background:#f443361a;border:1px solid var(--color-error);border-radius:var(--radius-md);color:var(--color-error);font-size:.875rem;text-align:center}.stmt__toolbar{display:flex;align-items:flex-end;flex-wrap:wrap;gap:var(--spacing-md)}.stmt__filter{display:flex;flex-direction:column;gap:var(--spacing-xs);min-width:180px}.stmt__filter-label{font-size:.6875rem;font-weight:var(--font-weight-medium);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}.stmt__filter-range{display:flex;align-items:center;gap:var(--spacing-sm)}.stmt__filter--range{min-width:320px}.stmt .widget-filter__search-field{width:100%;padding:var(--spacing-sm) var(--spacing-md);background:var(--bg-elevated);border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);color:var(--text-primary);font-size:.8125rem;box-sizing:border-box;cursor:text;transition:border-color var(--transition-fast)}.stmt .widget-filter__search-field:focus{outline:none;border-color:var(--action-orange)}.stmt .widget-filter__search-field::placeholder{color:var(--text-muted)}.stmt__toolbar-end{display:flex;align-items:center;gap:var(--spacing-md);margin-left:auto}.stmt__bounds{font-size:.6875rem;font-variant-numeric:tabular-nums;color:var(--text-muted)}.stmt__download{padding:var(--spacing-sm) var(--spacing-md);font-size:.75rem;font-weight:var(--font-weight-semibold);color:var(--action-orange);background:transparent;border:1px solid var(--action-orange);border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap;transition:background-color var(--transition-fast),color var(--transition-fast)}.stmt__download:hover:not(:disabled){background:var(--action-orange);color:var(--bg-dark)}.stmt__download:disabled{opacity:.4;cursor:not-allowed}.stmt__scroll{overflow-x:auto}.stmt__table{width:100%;border-collapse:collapse;font-size:.8125rem}.stmt__table thead th{position:sticky;top:0;z-index:1;padding:var(--spacing-sm);text-align:right;font-size:.6875rem;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);background:var(--bg-elevated);white-space:nowrap}.stmt__corner{position:sticky;left:0;z-index:2;text-align:left;text-transform:none;letter-spacing:normal;font-size:.8125rem;color:var(--text-primary)}.stmt__total-head{color:var(--action-orange)}.stmt__row th{position:sticky;left:0;padding:var(--spacing-xs) var(--spacing-sm);text-align:left;font-weight:var(--font-weight-normal);color:var(--text-secondary);white-space:nowrap;background:var(--bg-paper)}.stmt__value{padding:var(--spacing-xs) var(--spacing-sm);text-align:right;white-space:nowrap;color:var(--text-primary);font-variant-numeric:tabular-nums}.stmt__value--total{border-left:1px solid var(--bg-elevated);color:var(--action-orange)}.stmt__number{display:block}.stmt__aux{display:block;font-size:.625rem;color:var(--text-muted)}.stmt__aux--up{color:var(--action-green)}.stmt__aux--down{color:var(--color-error)}.stmt__row--data:hover,.stmt__row--formula:hover{background:var(--bg-elevated)}.stmt__row--formula th,.stmt__row--formula .stmt__value{border-top:1px solid var(--bg-elevated)}.stmt__row--bold th,.stmt__row--bold .stmt__value{font-weight:var(--font-weight-bold);color:var(--text-primary)}.stmt__row--header th{padding-top:var(--spacing-md);font-size:.6875rem;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.05em;color:var(--action-orange)}.stmt__row--separator td{height:var(--spacing-md)}.stmt__recalculating{position:fixed;bottom:var(--spacing-lg);right:var(--spacing-lg);padding:var(--spacing-sm) var(--spacing-lg);background:var(--bg-elevated);border:1px solid var(--action-orange);border-radius:var(--radius-md);color:var(--action-orange);font-size:.8125rem;font-weight:var(--font-weight-medium);box-shadow:var(--shadow-lg);z-index:50}.palette-selector{display:flex;flex-direction:column;gap:var(--spacing-sm)}.palette-selector--disabled{opacity:.5;pointer-events:none}.palette-selector__options{display:flex;flex-direction:column;gap:var(--spacing-xs)}.palette-selector__option{display:flex;flex-direction:column;gap:var(--spacing-xs);padding:var(--spacing-xs);background:transparent;border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);cursor:pointer;transition:border-color var(--transition-fast)}.palette-selector__option:hover:not(:disabled){border-color:var(--text-muted)}.palette-selector__option--active{border-color:var(--action-orange)}.palette-selector__bar{display:flex;width:100%;height:18px;border-radius:3px;overflow:hidden}.palette-selector__bar--theme{height:12px;opacity:.85}.palette-selector__swatch{flex:1;min-width:0}.palette-selector__label{font-size:.7rem;color:var(--text-muted);text-align:left}.palette-selector__custom{display:flex;flex-direction:column;gap:6px}.palette-selector__row{display:flex;flex-direction:column;gap:4px}.palette-selector__row-label{font-size:.6rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;font-weight:var(--font-weight-semibold)}.palette-selector__row-slots{display:flex;gap:4px;flex-wrap:wrap}.palette-selector__color-input{width:24px;height:24px;padding:0;border:1.5px solid rgba(255,255,255,.25);border-radius:var(--radius-sm);background:transparent;cursor:pointer;transition:border-color var(--transition-fast);flex-shrink:0}.palette-selector__color-input:hover:not(:disabled){border-color:#ffffff80}.palette-selector__color-input:hover:not(:disabled){border-color:var(--action-orange)}.palette-selector__color-input::-webkit-color-swatch-wrapper{padding:2px}.palette-selector__color-input::-webkit-color-swatch{border:none;border-radius:2px}.ddp-field{width:100%;min-width:0;display:block}.ddp-field .react-datepicker-wrapper,.ddp-field .react-datepicker__input-container{width:100%;display:block}.ddp-field .react-datepicker__input-container input{width:100%;padding:var(--spacing-sm) var(--spacing-md);background:var(--bg-elevated);border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);font-size:.8125rem;color:var(--text-primary);box-sizing:border-box;transition:border-color var(--transition-fast)}.ddp-field .react-datepicker__input-container input:focus{outline:none;border-color:var(--action-orange)}.ddp-field .react-datepicker__input-container input::placeholder{color:var(--text-muted)}.ddp-field .react-datepicker__input-container input:disabled{opacity:.6;cursor:not-allowed}.ddp-field .react-datepicker__month{min-height:168px}.react-datepicker-popper{z-index:1100!important}.widget{flex:1;display:flex;flex-direction:column;padding:var(--spacing-sm);background:var(--bg-elevated);border-radius:var(--radius-md);overflow:hidden;box-sizing:border-box;min-height:0;min-width:0}.widget__title{flex-shrink:0;margin:0 0 clamp(2px,1cqmin,8px);font-size:clamp(.5rem,4cqi,.9rem);font-weight:var(--font-weight-semibold);color:var(--text-secondary);line-height:1.2;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget__state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;padding:var(--spacing-xs);font-size:clamp(.45rem,2.5cqi,.85rem);color:var(--text-muted)}.widget__state--error{color:var(--color-error)}.widget-filter,.widget-palette{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(4px,1.5cqi,12px);padding:clamp(4px,1cqi,8px) clamp(6px,1.5cqi,12px);box-sizing:border-box;min-height:0;min-width:0;overflow:hidden}.widget-variable{flex:1;display:flex;flex-direction:column;justify-content:center;align-items:center;box-sizing:border-box;min-height:0;min-width:0;overflow:hidden}.widget-filter__label,.widget-palette__label,.widget-variable__label{flex-shrink:0;font-size:clamp(.45rem,6cqi,3rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-kpi{justify-content:center;align-items:center;text-align:center;gap:clamp(2px,1cqmin,10px);padding:clamp(4px,2cqmin,16px)}.widget-kpi .widget__title{margin:0;font-size:clamp(.45rem,min(12cqi,12cqb),6rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-kpi__value{font-size:clamp(.85rem,min(22cqi,22cqb),8rem);font-weight:var(--font-weight-bold);color:var(--text-primary);line-height:1.1;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}.widget-kpi__trend{display:flex;align-items:center;justify-content:center;gap:.35em .7em;font-size:clamp(.4rem,min(8cqi,8cqb),2rem);max-width:100%;overflow:hidden;flex-wrap:wrap}.widget-kpi__trend--good{color:var(--color-success)}.widget-kpi__trend--bad{color:var(--color-error)}.widget-kpi__trend--muted{opacity:.75;font-size:.9em}.widget-kpi__variance{font-weight:var(--font-weight-semibold);white-space:nowrap}.widget-kpi__trend-label{color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@container (max-width: 180px){.widget-kpi__trend-label{display:none}}@container (max-height: 70px){.widget-kpi .widget__title{display:none}}.widget-gauge{align-items:center;gap:0;overflow:hidden}.widget-gauge .widget__title{margin:0;font-size:clamp(.5rem,6cqi,3rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-gauge__chart{position:relative;width:100%;flex:1;min-height:0}.widget-gauge__chart svg{margin-top:5%;display:block;width:100%;height:100%}.widget-gauge__center{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;margin-top:25%}.widget-gauge__percent{font-size:clamp(.5rem,9cqi,4rem);font-weight:var(--font-weight-bold);color:var(--text-primary);line-height:1}.widget-gauge__comparison{font-size:clamp(.4rem,3.5cqi,2rem);color:var(--text-muted)}.widget-gauge__badge{font-size:clamp(.35rem,3cqi,1.25rem);font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.3px;padding:1px var(--spacing-xs);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.widget-chart{gap:var(--spacing-xs)}.widget-chart .widget__title{color:var(--text-primary)}.widget-chart__container{flex:1;min-height:0;overflow:hidden}.widget-composition{gap:var(--spacing-xs)}.widget-composition .widget__title{color:var(--text-primary)}.widget-composition__container{flex:1;min-height:0;overflow:hidden}.widget-composition__tooltip{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--bg-paper);border-radius:6px;background-color:var(--bg-elevated);font-size:.75rem;line-height:1.3}.widget-composition__tooltip-label{color:var(--text-primary);font-weight:var(--font-weight-semibold)}.widget-composition__tooltip-value{color:var(--text-secondary)}.widget-table{display:flex;flex-direction:column;gap:.4rem;height:100%;overflow:hidden;padding:.5rem .6rem;box-sizing:border-box}.widget-table__td--placeholder{color:var(--text-muted, #999);text-align:center;padding:.75rem .5rem}.widget-table__scroll{flex:1 1 auto;min-height:0;overflow:auto}.widget-table__scroll--clip{overflow:hidden}.widget-table__table{width:100%;border-collapse:collapse;font-size:clamp(.78rem,1.5cqmin,1.25rem)}.widget-table__table--fill{height:100%}.widget-table__th--index,.widget-table__td--index{width:1%;text-align:right;color:var(--text-muted, #999);font-variant-numeric:tabular-nums;white-space:nowrap}.widget-table__th{position:sticky;top:0;z-index:1;text-align:left;font-weight:600;color:var(--text-secondary, #ccc);background:var(--bg-elevated, #333);padding:.35rem .5rem;border-bottom:1px solid var(--border, rgba(255, 255, 255, .12));white-space:nowrap}.widget-table__th--num{text-align:right}.widget-table__td{padding:.3rem .5rem;color:var(--text-primary, #f5f5f5);border-bottom:1px solid var(--border, rgba(255, 255, 255, .06));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:26ch}.widget-table__td--num{text-align:right;font-variant-numeric:tabular-nums}.widget-table__td--up{color:var(--color-success, #a4c639);font-weight:600}.widget-table__td--down{color:var(--color-error, #e5534b);font-weight:600}.widget-table__table tbody tr:hover{background:#ffffff08}.widget-filter__date-range{display:flex;align-items:center;gap:clamp(2px,1cqi,8px);flex:1;min-width:0}.widget-filter__date-range--stacked{flex-direction:column;align-items:stretch;gap:clamp(4px,1.5cqmin,10px);width:100%;padding:clamp(2px,1cqmin,8px) 0}.widget-filter__date-range .ddp-field{flex:1;min-width:0;width:100%}.widget-filter__date-range .ddp-field .react-datepicker__input-container input,.widget-filter__select{padding:clamp(8px,4cqmin,22px) clamp(6px,1.5cqmin,12px);font-size:clamp(.5rem,10cqmin,2rem);background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);color:var(--text-primary);flex:1;min-width:0;width:100%;box-sizing:border-box;text-align:center;font-variant-numeric:tabular-nums}.widget-filter__date-sep{font-size:clamp(.35rem,2.5cqi,.8rem);color:var(--text-muted)}.widget-filter__multi{display:flex;flex-direction:column;align-items:stretch;justify-content:space-around;gap:clamp(4px,1.5cqmin,14px);flex:1;min-height:0;width:100%;padding:clamp(6px,2cqmin,14px) clamp(4px,2cqmin,12px);box-sizing:border-box;overflow-y:auto}.widget-filter__multi::-webkit-scrollbar{width:6px}.widget-filter__multi::-webkit-scrollbar-track{background:transparent}.widget-filter__multi::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}.widget-filter__multi::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.widget-filter__multi-clear{flex-shrink:0;width:100%;padding:clamp(3px,1cqmin,8px) clamp(8px,2.5cqmin,14px);background:transparent;border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);color:var(--action-orange);font-size:clamp(.4rem,7cqmin,1rem);font-weight:var(--font-weight-semibold);text-align:center;cursor:pointer;transition:background-color var(--transition-fast),border-color var(--transition-fast)}.widget-filter__multi-clear:hover{background-color:var(--bg-elevated);border-color:var(--action-orange)}.widget-filter__multi-option{display:flex;align-items:center;gap:clamp(6px,4cqmin,14px);padding:clamp(4px,1.5cqmin,12px) clamp(8px,2.5cqmin,14px);height:clamp(20px,18cqb,120px);background:var(--bg-paper);border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);cursor:pointer;transition:border-color var(--transition-fast),background-color var(--transition-fast);font-size:clamp(.45rem,8cqmin,1.2rem);font-weight:var(--font-weight-medium);color:var(--text-primary);line-height:1;flex-shrink:0;box-sizing:border-box}.widget-filter__multi-option:hover{border-color:var(--text-muted);background-color:var(--bg-elevated)}.widget-filter__multi-option:has(input[type=checkbox]:checked){border-color:var(--text-muted);background-color:var(--bg-elevated)}.widget-filter__multi-option input[type=checkbox]{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:clamp(12px,7cqmin,22px);height:clamp(12px,7cqmin,22px);border:1.5px solid var(--text-muted);border-radius:3px;background:var(--bg-elevated);cursor:pointer;position:relative;flex-shrink:0;transition:border-color var(--transition-fast),background-color var(--transition-fast);margin:0}.widget-filter__multi-option input[type=checkbox]:hover{border-color:var(--action-orange)}.widget-filter__multi-option input[type=checkbox]:checked{background:var(--action-orange);border-color:var(--action-orange)}.widget-filter__multi-option input[type=checkbox]:checked:after{content:"";position:absolute;left:30%;top:8%;width:30%;height:60%;border:solid var(--bg-dark);border-width:0 2px 2px 0;transform:rotate(45deg)}.widget-filter__select{width:95%;max-height:45%;margin-top:2%;flex:1;font-size:clamp(.4rem,5cqi,1.5rem);font-weight:var(--font-weight-semibold);color:var(--text-primary);text-align:left;padding:clamp(8px,4cqi,22px) clamp(6px,1.5cqi,12px);min-width:0;box-sizing:border-box}.widget-filter>.widget-filter__select,.widget-filter__date-range--year .widget-filter__select,.widget-filter__date-range--month .widget-filter__select,.widget-filter__date-range--week .widget-filter__select{text-align:center;text-align-last:center;font-weight:var(--font-weight-semibold);color:var(--text-primary);background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none;transition:border-color var(--transition-fast),background-color var(--transition-fast);box-sizing:border-box;width:100%;margin-top:0;max-height:none;padding:clamp(2px,.8cqmin,6px) clamp(6px,1.5cqmin,12px);line-height:1}.widget-filter>.widget-filter__select:hover,.widget-filter>.widget-filter__select:focus,.widget-filter__date-range--year .widget-filter__select:hover,.widget-filter__date-range--year .widget-filter__select:focus,.widget-filter__date-range--month .widget-filter__select:hover,.widget-filter__date-range--month .widget-filter__select:focus,.widget-filter__date-range--week .widget-filter__select:hover,.widget-filter__date-range--week .widget-filter__select:focus{outline:none;border-color:var(--action-orange);background-color:var(--bg-elevated)}.widget-filter>.widget-filter__select option,.widget-filter__date-range--year .widget-filter__select option,.widget-filter__date-range--month .widget-filter__select option,.widget-filter__date-range--week .widget-filter__select option{background:var(--bg-paper);color:var(--text-primary);font-size:.875rem;font-weight:var(--font-weight-normal);text-align:left;padding:6px 10px}.widget-filter>.widget-filter__select{flex:0 1 auto;height:clamp(50px,22cqmin,140px);max-height:75%;margin-block:auto;align-self:center;font-size:clamp(.6rem,12cqmin,2.2rem)}.widget-filter__date-range--year,.widget-filter__date-range--month,.widget-filter__date-range--week{display:flex;flex-direction:column;align-items:stretch;justify-content:center;gap:clamp(6px,2.5cqmin,16px);flex:1;width:100%;padding:clamp(6px,2cqmin,16px) clamp(4px,2cqmin,14px);box-sizing:border-box}.widget-filter__date-range--year .widget-filter__select{flex:0 1 auto;height:clamp(50px,22cqmin,140px);font-size:clamp(.6rem,12cqmin,2.2rem)}.widget-filter__date-range--month .widget-filter__select{flex:0 1 auto;height:clamp(30px,10cqmin,66px);font-size:clamp(.5rem,10cqmin,1.4rem)}.widget-filter__date-range--week .widget-filter__select{flex:0 1 auto;height:clamp(22px,12cqmin,48px);font-size:clamp(.45rem,8cqmin,3rem)}.widget-filter__search{position:relative;display:flex;align-items:center;flex:1;min-width:0;width:100%;padding:clamp(2px,1cqmin,8px) 0}.widget-filter .widget-filter__search-field{width:100%;padding:clamp(6px,3cqmin,18px) clamp(8px,2cqmin,14px);background:var(--bg-dark);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);color:var(--text-primary);font-size:clamp(.55rem,10cqmin,1.8rem);font-weight:var(--font-weight-semibold);text-align:center;box-sizing:border-box;cursor:text;transition:border-color var(--transition-fast),background-color var(--transition-fast)}.widget-filter .widget-filter__search-field::placeholder{color:var(--text-muted);font-weight:var(--font-weight-normal)}.widget-filter .widget-filter__search-field:hover,.widget-filter .widget-filter__search-field:focus{outline:none;border-color:var(--action-orange);background-color:var(--bg-paper)}.widget-filter__search-panel{z-index:10000;display:flex;flex-direction:column;background:var(--bg-paper);border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);box-shadow:var(--shadow-md, 0 8px 28px rgba(0, 0, 0, .45));overflow:hidden}.widget-filter__search-list{display:flex;flex-direction:column;gap:2px;padding:6px;overflow-y:auto}.widget-filter__search-option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-left:3px solid transparent;border-radius:var(--radius-sm);color:var(--text-primary);font-size:.85rem;font-weight:var(--font-weight-medium);text-align:left;cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast)}.widget-filter__search-option:hover{background-color:var(--bg-elevated)}.widget-filter__search-option.is-selected{background-color:var(--bg-elevated);border-left-color:var(--action-orange);color:var(--action-orange)}.widget-filter__search-check{flex-shrink:0;width:1em;color:var(--action-orange);font-weight:var(--font-weight-semibold)}.widget-filter__search-option input[type=checkbox]{width:16px;height:16px;flex-shrink:0;accent-color:var(--action-orange);cursor:pointer}.widget-filter__search-clear{width:100%;margin-bottom:4px;padding:8px 10px;background:transparent;border:none;border-bottom:1px solid var(--bg-elevated);border-radius:0;color:var(--action-orange);font-size:.8rem;font-weight:var(--font-weight-semibold);text-align:left;cursor:pointer;transition:background-color var(--transition-fast)}.widget-filter__search-clear:hover{background-color:var(--bg-elevated)}.widget-filter__search-empty{padding:12px;color:var(--text-muted);font-size:.85rem;text-align:center}.widget-filter__search-list::-webkit-scrollbar{width:6px}.widget-filter__search-list::-webkit-scrollbar-track{background:transparent}.widget-filter__search-list::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}.widget-filter__search-list::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.widget-variable__input-wrapper{display:flex;align-items:center;margin-top:2%;width:90%;background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);overflow:hidden}.widget-variable__input{flex:1;font-size:clamp(.4rem,5cqi,1.5rem);font-weight:var(--font-weight-semibold);background:transparent;border:none;outline:none;color:var(--text-primary);text-align:left;padding:clamp(2px,1cqi,6px) clamp(4px,1.5cqi,8px);min-width:0;box-sizing:border-box}.widget-variable__input::-webkit-outer-spin-button,.widget-variable__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.widget-variable__input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}.widget-variable__input:disabled{opacity:.6;cursor:not-allowed}.widget-variable__suffix{font-size:clamp(.4rem,4cqi,1.25rem);color:var(--text-muted);white-space:nowrap;padding:0 clamp(4px,1.5cqi,8px);border-left:1px solid rgba(255,255,255,.1);flex-shrink:0}.widget-variable__lock-icon{font-size:clamp(.45rem,2.5cqi,.75rem)}.widget-variable--locked .widget-variable__input-wrapper{border-style:dashed}.widget-palette{flex-direction:column;justify-content:flex-start;align-items:stretch;padding:clamp(4px,1.5cqmin,12px);gap:clamp(2px,1cqmin,8px);overflow:auto}.widget-palette__label{text-align:center;flex-shrink:0}.widget-palette__lock-icon{font-size:clamp(.45rem,2.5cqmin,.75rem);align-self:center}.widget-palette--locked .palette-selector__color-input{opacity:.6;cursor:not-allowed}.widget-palette .palette-selector{gap:clamp(2px,3cqmin,28px);flex:1;min-height:0;justify-content:center}.widget-palette .palette-selector__row{gap:clamp(1px,1.2cqmin,10px);min-height:0}.widget-palette .palette-selector__row-label{font-size:clamp(.35rem,1.8cqmin,.7rem);line-height:1}.widget-palette .palette-selector__row-slots{gap:clamp(1px,.8cqmin,6px);flex-wrap:nowrap;justify-content:space-between;width:100%;min-height:0}.widget-palette .palette-selector__color-input{flex:1 1 0;min-width:0;min-height:0;width:auto;height:clamp(8px,10cqmin,60px);border:1px solid rgba(255,255,255,.2);padding:0}.widget-palette .palette-selector__color-input:hover:not(:disabled){border-color:#fff6}
|
|
1
|
+
@charset "UTF-8";.react-datepicker__navigation-icon:before,.react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view--down-arrow{border-color:#ccc;border-style:solid;border-width:3px 3px 0 0;content:"";display:block;height:9px;position:absolute;top:6px;width:9px}.react-datepicker__sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.react-datepicker-wrapper{display:inline-block;padding:0;border:0}.react-datepicker{font-family:Helvetica Neue,helvetica,arial,sans-serif;font-size:.8rem;background-color:#fff;color:#000;border:1px solid #aeaeae;border-radius:.3rem;display:inline-block;position:relative;line-height:initial}.react-datepicker--time-only .react-datepicker__time-container{border-left:0}.react-datepicker--time-only .react-datepicker__time,.react-datepicker--time-only .react-datepicker__time-box{border-bottom-left-radius:.375em;border-bottom-right-radius:.375em}.react-datepicker-popper{z-index:1;line-height:0}.react-datepicker-popper .react-datepicker__triangle{stroke:#aeaeae}.react-datepicker-popper[data-placement^=bottom] .react-datepicker__triangle{fill:#f0f0f0;color:#f0f0f0}.react-datepicker-popper[data-placement^=top] .react-datepicker__triangle,.react-datepicker-popper--header-middle[data-placement^=bottom] .react-datepicker__triangle,.react-datepicker-popper--header-bottom[data-placement^=bottom] .react-datepicker__triangle{fill:#fff;color:#fff}.react-datepicker-popper--header-bottom[data-placement^=top] .react-datepicker__triangle{fill:#f0f0f0;color:#f0f0f0}.react-datepicker__header{text-align:center;background-color:#f0f0f0;border-bottom:1px solid #aeaeae;border-top-left-radius:.3rem;padding:8px 0;position:relative}.react-datepicker__header--time{padding-bottom:8px;padding-left:5px;padding-right:5px}.react-datepicker__header--time:not(.react-datepicker__header--time--only){border-top-left-radius:0}.react-datepicker__header:not(.react-datepicker__header--has-time-select,.react-datepicker__header--middle,.react-datepicker__header--bottom){border-top-right-radius:.3rem}.react-datepicker__header--middle{border-top:1px solid #aeaeae;border-radius:0;margin-top:4px}.react-datepicker__header--bottom{border-bottom:none;border-top:1px solid #aeaeae;border-radius:0 0 .3rem .3rem}.react-datepicker__header-wrapper{position:relative}.react-datepicker__header-wrapper .react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button){right:2px}.react-datepicker__year-dropdown-container--select,.react-datepicker__month-dropdown-container--select,.react-datepicker__month-year-dropdown-container--select,.react-datepicker__year-dropdown-container--scroll,.react-datepicker__month-dropdown-container--scroll,.react-datepicker__month-year-dropdown-container--scroll{display:inline-block;margin:0 15px}.react-datepicker__month-select,.react-datepicker__year-select,.react-datepicker__month-year-select{background-color:transparent;border:1px solid #aeaeae;border-radius:.3rem;color:inherit;cursor:pointer;font-family:inherit;font-size:inherit;margin-top:5px;padding:2px 5px}.react-datepicker__month-select:focus-visible,.react-datepicker__year-select:focus-visible,.react-datepicker__month-year-select:focus-visible{outline:auto 1px}.react-datepicker__current-month,.react-datepicker-time__header,.react-datepicker-year-header{margin-top:0;color:#000;font-weight:700;font-size:.944rem}h2.react-datepicker__current-month{padding:0;margin:0}.react-datepicker-time__header{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.react-datepicker__navigation{align-items:center;background:none;display:flex;justify-content:center;text-align:center;cursor:pointer;position:absolute;top:2px;padding:0;border:none;z-index:1;height:32px;width:32px;text-indent:-999em;overflow:hidden}.react-datepicker__navigation--previous{left:2px}.react-datepicker__navigation--next{right:2px}.react-datepicker__navigation--next--with-time:not(.react-datepicker__navigation--next--with-today-button){right:85px}.react-datepicker__navigation--years{position:relative;top:0;display:block;margin-left:auto;margin-right:auto}.react-datepicker__navigation--years-previous{top:4px}.react-datepicker__navigation--years-upcoming{top:-4px}.react-datepicker__navigation:hover *:before{border-color:#a6a6a6}.react-datepicker__navigation-icon{position:relative;top:-1px;font-size:20px;width:0}.react-datepicker__navigation-icon--next{left:-2px}.react-datepicker__navigation-icon--next:before{transform:rotate(45deg);left:-7px}.react-datepicker__navigation-icon--previous{right:-2px}.react-datepicker__navigation-icon--previous:before{transform:rotate(225deg);right:-7px}.react-datepicker__month-container{float:left}.react-datepicker__year{margin:.5em;text-align:center}.react-datepicker__year-wrapper{display:flex;flex-wrap:wrap;max-width:180px}.react-datepicker__year .react-datepicker__year-text{display:inline-block;width:5em;margin:2px}.react-datepicker__month{margin:.5em;text-align:center}.react-datepicker__month .react-datepicker__month-text,.react-datepicker__month .react-datepicker__quarter-text{display:inline-block;width:5em;margin:2px}.react-datepicker__input-time-container{clear:both;width:100%;float:left;margin:5px 0 10px 15px;text-align:left}.react-datepicker__input-time-container .react-datepicker-time__caption,.react-datepicker__input-time-container .react-datepicker-time__input-container{display:inline-block}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input{display:inline-block;margin-left:10px}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input{width:auto}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]::-webkit-inner-spin-button,.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]::-webkit-outer-spin-button{-webkit-appearance:none;margin:0}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__input input[type=time]{-moz-appearance:textfield}.react-datepicker__input-time-container .react-datepicker-time__input-container .react-datepicker-time__delimiter{margin-left:5px;display:inline-block}.react-datepicker__time-container{float:right;border-left:1px solid #aeaeae;width:85px}.react-datepicker__time-container--with-today-button{display:inline;border:1px solid #aeaeae;border-radius:.375em;position:absolute;right:-87px;top:0}.react-datepicker__time-container .react-datepicker__time{position:relative;background:#fff;border-bottom-right-radius:.375em}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box{width:85px;overflow-x:hidden;margin:0 auto;text-align:center;border-bottom-right-radius:.375em}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list{list-style:none;margin:0;height:calc(195px + 1.0625em);overflow-y:scroll;padding-right:0;padding-left:0;width:100%;box-sizing:content-box}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item{height:30px;padding:5px 10px;white-space:nowrap}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item:hover{cursor:pointer;background-color:#f0f0f0}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected{background-color:#216ba5;color:#fff;font-weight:700}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--selected:hover{background-color:#216ba5}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled{color:#ccc}.react-datepicker__time-container .react-datepicker__time .react-datepicker__time-box ul.react-datepicker__time-list li.react-datepicker__time-list-item--disabled:hover{cursor:default;background-color:transparent}.react-datepicker__week-number{color:#ccc;display:inline-block;width:2.125em;line-height:2.125em;text-align:center;margin:.208em}.react-datepicker__week-number.react-datepicker__week-number--clickable{cursor:pointer}.react-datepicker__week-number.react-datepicker__week-number--clickable:not(.react-datepicker__week-number--selected):hover{border-radius:.3rem;background-color:#f0f0f0}.react-datepicker__week-number--selected{border-radius:.3rem;background-color:#216ba5;color:#fff}.react-datepicker__week-number--selected:hover{background-color:#1d5d90}.react-datepicker__day-names{text-align:center;white-space:nowrap;margin-bottom:-8px}.react-datepicker__week{white-space:nowrap}.react-datepicker__day-name,.react-datepicker__day,.react-datepicker__time-name{color:#000;display:inline-block;width:2.125em;line-height:2.125em;text-align:center;margin:.208em}.react-datepicker__day-name--disabled,.react-datepicker__day--disabled,.react-datepicker__time-name--disabled{cursor:default;color:#ccc}.react-datepicker__day,.react-datepicker__month-text,.react-datepicker__quarter-text,.react-datepicker__year-text{cursor:pointer}.react-datepicker__day:not([aria-disabled=true]):hover,.react-datepicker__month-text:not([aria-disabled=true]):hover,.react-datepicker__quarter-text:not([aria-disabled=true]):hover,.react-datepicker__year-text:not([aria-disabled=true]):hover{border-radius:.3rem;background-color:#f0f0f0}.react-datepicker__day--today,.react-datepicker__month-text--today,.react-datepicker__quarter-text--today,.react-datepicker__year-text--today{font-weight:700}.react-datepicker__day--highlighted,.react-datepicker__month-text--highlighted,.react-datepicker__quarter-text--highlighted,.react-datepicker__year-text--highlighted{border-radius:.3rem;background-color:#3dcc4a;color:#fff}.react-datepicker__day--highlighted:not([aria-disabled=true]):hover,.react-datepicker__month-text--highlighted:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--highlighted:not([aria-disabled=true]):hover,.react-datepicker__year-text--highlighted:not([aria-disabled=true]):hover{background-color:#32be3f}.react-datepicker__day--highlighted-custom-1,.react-datepicker__month-text--highlighted-custom-1,.react-datepicker__quarter-text--highlighted-custom-1,.react-datepicker__year-text--highlighted-custom-1{color:#f0f}.react-datepicker__day--highlighted-custom-2,.react-datepicker__month-text--highlighted-custom-2,.react-datepicker__quarter-text--highlighted-custom-2,.react-datepicker__year-text--highlighted-custom-2{color:green}.react-datepicker__day--holidays,.react-datepicker__month-text--holidays,.react-datepicker__quarter-text--holidays,.react-datepicker__year-text--holidays{position:relative;border-radius:.3rem;background-color:#ff6803;color:#fff}.react-datepicker__day--holidays .overlay,.react-datepicker__month-text--holidays .overlay,.react-datepicker__quarter-text--holidays .overlay,.react-datepicker__year-text--holidays .overlay{position:absolute;bottom:100%;left:50%;transform:translate(-50%);background-color:#333;color:#fff;padding:4px;border-radius:4px;white-space:nowrap;visibility:hidden;opacity:0;transition:visibility 0s,opacity .3s ease-in-out}.react-datepicker__day--holidays:not([aria-disabled=true]):hover,.react-datepicker__month-text--holidays:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--holidays:not([aria-disabled=true]):hover,.react-datepicker__year-text--holidays:not([aria-disabled=true]):hover{background-color:#cf5300}.react-datepicker__day--holidays:hover .overlay,.react-datepicker__month-text--holidays:hover .overlay,.react-datepicker__quarter-text--holidays:hover .overlay,.react-datepicker__year-text--holidays:hover .overlay{visibility:visible;opacity:1}.react-datepicker__day--selected,.react-datepicker__day--in-selecting-range,.react-datepicker__day--in-range,.react-datepicker__month-text--selected,.react-datepicker__month-text--in-selecting-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--selected,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--selected,.react-datepicker__year-text--in-selecting-range,.react-datepicker__year-text--in-range{border-radius:.3rem;background-color:#216ba5;color:#fff}.react-datepicker__day--selected:not([aria-disabled=true]):hover,.react-datepicker__day--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__day--in-range:not([aria-disabled=true]):hover,.react-datepicker__month-text--selected:not([aria-disabled=true]):hover,.react-datepicker__month-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__month-text--in-range:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--selected:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--in-range:not([aria-disabled=true]):hover,.react-datepicker__year-text--selected:not([aria-disabled=true]):hover,.react-datepicker__year-text--in-selecting-range:not([aria-disabled=true]):hover,.react-datepicker__year-text--in-range:not([aria-disabled=true]):hover{background-color:#1d5d90}.react-datepicker__day--keyboard-selected,.react-datepicker__month-text--keyboard-selected,.react-datepicker__quarter-text--keyboard-selected,.react-datepicker__year-text--keyboard-selected{border-radius:.3rem;background-color:#bad9f1;color:#000}.react-datepicker__day--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__month-text--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__quarter-text--keyboard-selected:not([aria-disabled=true]):hover,.react-datepicker__year-text--keyboard-selected:not([aria-disabled=true]):hover{background-color:#1d5d90;color:#fff}.react-datepicker__day--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__month-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__quarter-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range),.react-datepicker__year-text--in-selecting-range:not(.react-datepicker__day--in-range,.react-datepicker__month-text--in-range,.react-datepicker__quarter-text--in-range,.react-datepicker__year-text--in-range){background-color:#216ba580}.react-datepicker__month--selecting-range .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__day--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__month-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__month-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__quarter-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__quarter-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__month--selecting-range .react-datepicker__year-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range),.react-datepicker__year--selecting-range .react-datepicker__year-text--in-range:not(.react-datepicker__day--in-selecting-range,.react-datepicker__month-text--in-selecting-range,.react-datepicker__quarter-text--in-selecting-range,.react-datepicker__year-text--in-selecting-range){background-color:#f0f0f0;color:#000}.react-datepicker__day--disabled,.react-datepicker__month-text--disabled,.react-datepicker__quarter-text--disabled,.react-datepicker__year-text--disabled{cursor:default;color:#ccc}.react-datepicker__day--disabled .overlay,.react-datepicker__month-text--disabled .overlay,.react-datepicker__quarter-text--disabled .overlay,.react-datepicker__year-text--disabled .overlay{position:absolute;bottom:70%;left:50%;transform:translate(-50%);background-color:#333;color:#fff;padding:4px;border-radius:4px;white-space:nowrap;visibility:hidden;opacity:0;transition:visibility 0s,opacity .3s ease-in-out}.react-datepicker__input-container{position:relative;display:inline-block;width:100%}.react-datepicker__input-container .react-datepicker__calendar-icon{position:absolute;padding:.625em;box-sizing:content-box}.react-datepicker__view-calendar-icon input{padding:6px 10px 5px 25px}.react-datepicker__year-read-view,.react-datepicker__month-read-view,.react-datepicker__month-year-read-view{border:1px solid transparent;border-radius:.3rem;position:relative}.react-datepicker__year-read-view:hover,.react-datepicker__month-read-view:hover,.react-datepicker__month-year-read-view:hover{cursor:pointer}.react-datepicker__year-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__year-read-view:hover .react-datepicker__month-read-view--down-arrow,.react-datepicker__month-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view:hover .react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view:hover .react-datepicker__year-read-view--down-arrow,.react-datepicker__month-year-read-view:hover .react-datepicker__month-read-view--down-arrow{border-top-color:#b3b3b3}.react-datepicker__year-read-view--down-arrow,.react-datepicker__month-read-view--down-arrow,.react-datepicker__month-year-read-view--down-arrow{transform:rotate(135deg);right:-16px;top:0}.react-datepicker__year-dropdown,.react-datepicker__month-dropdown,.react-datepicker__month-year-dropdown{background-color:#f0f0f0;position:absolute;width:50%;left:25%;top:30px;z-index:1;text-align:center;border-radius:.3rem;border:1px solid #aeaeae}.react-datepicker__year-dropdown:hover,.react-datepicker__month-dropdown:hover,.react-datepicker__month-year-dropdown:hover{cursor:pointer}.react-datepicker__year-dropdown--scrollable,.react-datepicker__month-dropdown--scrollable,.react-datepicker__month-year-dropdown--scrollable{height:150px;overflow-y:scroll}.react-datepicker__year-option,.react-datepicker__month-option,.react-datepicker__month-year-option{line-height:20px;width:100%;display:block;margin-left:auto;margin-right:auto}.react-datepicker__year-option:first-of-type,.react-datepicker__month-option:first-of-type,.react-datepicker__month-year-option:first-of-type{border-top-left-radius:.3rem;border-top-right-radius:.3rem}.react-datepicker__year-option:last-of-type,.react-datepicker__month-option:last-of-type,.react-datepicker__month-year-option:last-of-type{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;border-bottom-left-radius:.3rem;border-bottom-right-radius:.3rem}.react-datepicker__year-option:hover,.react-datepicker__month-option:hover,.react-datepicker__month-year-option:hover{background-color:#ccc}.react-datepicker__year-option:hover .react-datepicker__navigation--years-upcoming,.react-datepicker__month-option:hover .react-datepicker__navigation--years-upcoming,.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-upcoming{border-bottom-color:#b3b3b3}.react-datepicker__year-option:hover .react-datepicker__navigation--years-previous,.react-datepicker__month-option:hover .react-datepicker__navigation--years-previous,.react-datepicker__month-year-option:hover .react-datepicker__navigation--years-previous{border-top-color:#b3b3b3}.react-datepicker__year-option--selected,.react-datepicker__month-option--selected,.react-datepicker__month-year-option--selected{position:absolute;left:15px}.react-datepicker__close-icon{cursor:pointer;background-color:transparent;border:0;outline:0;padding:0 6px 0 0;position:absolute;top:0;right:0;height:100%;display:table-cell;vertical-align:middle}.react-datepicker__close-icon:after{cursor:pointer;background-color:#216ba5;color:#fff;border-radius:50%;height:16px;width:16px;padding:2px;font-size:12px;line-height:1;text-align:center;display:table-cell;vertical-align:middle;content:"×"}.react-datepicker__close-icon--disabled{cursor:default}.react-datepicker__close-icon--disabled:after{cursor:default;background-color:#ccc}.react-datepicker__today-button{background:#f0f0f0;border-top:1px solid #aeaeae;cursor:pointer;text-align:center;font-weight:700;padding:5px 0;clear:left}.react-datepicker__portal{position:fixed;width:100vw;height:100vh;background-color:#000c;left:0;top:0;justify-content:center;align-items:center;display:flex;z-index:2147483647}.react-datepicker__children-container{width:17.25em;margin:.5em;padding-right:.25em;padding-left:.25em;height:auto}.react-datepicker__aria-live{position:absolute;clip-path:circle(0);border:0;height:1px;margin:-1px;overflow:hidden;padding:0;width:1px;white-space:nowrap}.react-datepicker__calendar-icon{width:1em;height:1em;vertical-align:-.125em}.react-datepicker-popper-offset{margin-top:-.7em}:where(.preview-tab,.stmt,.widget,.palette-selector,.ddp-field){--spacing-xs: 4px;--spacing-sm: 8px;--spacing-md: 16px;--spacing-lg: 24px;--spacing-xl: 32px;--spacing-2xl: 48px;--radius-sm: 4px;--radius-md: 8px;--radius-lg: 12px;--font-weight-normal: 400;--font-weight-medium: 500;--font-weight-semibold: 600;--font-weight-bold: 700;--transition-fast: .15s ease;--shadow-lg: 0 10px 25px rgba(0, 0, 0, .4)}.preview-tab{display:flex;flex-direction:column;gap:var(--spacing-md);position:relative}.preview-tab__empty{display:flex;align-items:center;justify-content:center;min-height:300px;color:var(--text-muted);font-size:.9rem;border:2px dashed var(--bg-elevated);border-radius:var(--radius-lg)}.preview-tab__loading{display:flex;align-items:center;justify-content:center;padding:var(--spacing-2xl) 0;color:var(--text-secondary)}.preview-tab__error{padding:var(--spacing-md);background:#f443361a;border:1px solid var(--color-error);border-radius:var(--radius-md);color:var(--color-error);font-size:.875rem;text-align:center}.preview-tab__grid{display:grid;grid-template-columns:repeat(var(--dash-cols, 30),1fr);grid-template-rows:repeat(var(--dash-rows, 10),var(--dash-cell-h, 40px));grid-auto-rows:var(--dash-cell-h, 40px);gap:var(--dash-gap, 6px);padding:var(--dash-pad, 16px);background:var(--bg-dark);border-radius:var(--radius-lg)}.preview-tab__grid--stacked{grid-template-columns:1fr;grid-template-rows:none;grid-auto-rows:auto}.preview-tab__widget{display:flex;background:var(--bg-elevated);border:1px solid rgba(255,255,255,.08);border-radius:var(--radius-md);overflow:hidden;min-height:0;container-type:size}.preview-tab__widget--control{background:var(--bg-elevated);border:1px dashed rgba(255,255,255,.15)}.preview-tab__widget-loading{display:flex;align-items:center;justify-content:center;height:100%;min-height:80px;color:var(--text-muted);font-size:.8125rem}.preview-tab__recalculating{position:fixed;bottom:var(--spacing-lg);right:var(--spacing-lg);padding:var(--spacing-sm) var(--spacing-lg);background:var(--bg-elevated);border:1px solid var(--action-orange);border-radius:var(--radius-md);color:var(--action-orange);font-size:.8125rem;font-weight:var(--font-weight-medium);box-shadow:var(--shadow-lg);z-index:50}.stmt{display:flex;flex-direction:column;gap:var(--spacing-md);position:relative;color:var(--text-primary)}.stmt__state{padding:var(--spacing-xl);text-align:center;font-size:.875rem;color:var(--text-secondary)}.stmt__error{padding:var(--spacing-md);background:#f443361a;border:1px solid var(--color-error);border-radius:var(--radius-md);color:var(--color-error);font-size:.875rem;text-align:center}.stmt__warning{padding:var(--spacing-sm) var(--spacing-md);background:#f59e0b1f;border:1px solid var(--color-warning);border-radius:var(--radius-md);color:var(--color-warning);font-size:.8125rem;line-height:1.5}.stmt__toolbar{display:flex;align-items:flex-end;flex-wrap:wrap;gap:var(--spacing-md)}.stmt__filter{display:flex;flex-direction:column;gap:var(--spacing-xs);min-width:180px}.stmt__filter-label{font-size:.6875rem;font-weight:var(--font-weight-medium);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted)}.stmt__filter-range{display:flex;align-items:center;gap:var(--spacing-sm)}.stmt__filter--range{min-width:320px}.stmt .widget-filter__search-field{width:100%;padding:var(--spacing-sm) var(--spacing-md);background:var(--bg-elevated);border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);color:var(--text-primary);font-size:.8125rem;box-sizing:border-box;cursor:text;transition:border-color var(--transition-fast)}.stmt .widget-filter__search-field:focus{outline:none;border-color:var(--action-orange)}.stmt .widget-filter__search-field::placeholder{color:var(--text-muted)}.stmt__toolbar-end{display:flex;align-items:center;gap:var(--spacing-md);margin-left:auto}.stmt__bounds{font-size:.6875rem;font-variant-numeric:tabular-nums;color:var(--text-muted)}.stmt__download{padding:var(--spacing-sm) var(--spacing-md);font-size:.75rem;font-weight:var(--font-weight-semibold);color:var(--action-orange);background:transparent;border:1px solid var(--action-orange);border-radius:var(--radius-sm);cursor:pointer;white-space:nowrap;transition:background-color var(--transition-fast),color var(--transition-fast)}.stmt__download:hover:not(:disabled){background:var(--action-orange);color:var(--bg-dark)}.stmt__download:disabled{opacity:.4;cursor:not-allowed}.stmt__scroll{overflow-x:auto}.stmt__table{width:100%;border-collapse:collapse;font-size:.8125rem}.stmt__table thead th{position:sticky;top:0;z-index:1;padding:var(--spacing-sm);text-align:right;font-size:.6875rem;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.04em;color:var(--text-muted);background:var(--bg-elevated);white-space:nowrap}.stmt__corner{position:sticky;left:0;z-index:2;text-align:left;text-transform:none;letter-spacing:normal;font-size:.8125rem;color:var(--text-primary)}.stmt__total-head{color:var(--action-orange)}.stmt__row th{position:sticky;left:0;padding:var(--spacing-xs) var(--spacing-sm);text-align:left;font-weight:var(--font-weight-normal);color:var(--text-secondary);white-space:nowrap;background:var(--bg-paper)}.stmt__value{padding:var(--spacing-xs) var(--spacing-sm);text-align:right;white-space:nowrap;color:var(--text-primary);font-variant-numeric:tabular-nums}.stmt__value--total{border-left:1px solid var(--bg-elevated);color:var(--action-orange)}.stmt__number{display:block}.stmt__aux{display:block;font-size:.625rem;color:var(--text-muted)}.stmt__aux--up{color:var(--action-green)}.stmt__aux--down{color:var(--color-error)}.stmt__row--data:hover,.stmt__row--formula:hover{background:var(--bg-elevated)}.stmt__row--formula th,.stmt__row--formula .stmt__value{border-top:1px solid var(--bg-elevated)}.stmt__row--bold th,.stmt__row--bold .stmt__value{font-weight:var(--font-weight-bold);color:var(--text-primary)}.stmt__row--header th{padding-top:var(--spacing-md);font-size:.6875rem;font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.05em;color:var(--action-orange)}.stmt__row--header .stmt__value{padding-top:var(--spacing-md);font-weight:var(--font-weight-semibold);color:var(--action-orange)}.stmt__row--separator td{height:var(--spacing-md)}.stmt__recalculating{position:fixed;bottom:var(--spacing-lg);right:var(--spacing-lg);padding:var(--spacing-sm) var(--spacing-lg);background:var(--bg-elevated);border:1px solid var(--action-orange);border-radius:var(--radius-md);color:var(--action-orange);font-size:.8125rem;font-weight:var(--font-weight-medium);box-shadow:var(--shadow-lg);z-index:50}.palette-selector{display:flex;flex-direction:column;gap:var(--spacing-sm)}.palette-selector--disabled{opacity:.5;pointer-events:none}.palette-selector__options{display:flex;flex-direction:column;gap:var(--spacing-xs)}.palette-selector__option{display:flex;flex-direction:column;gap:var(--spacing-xs);padding:var(--spacing-xs);background:transparent;border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);cursor:pointer;transition:border-color var(--transition-fast)}.palette-selector__option:hover:not(:disabled){border-color:var(--text-muted)}.palette-selector__option--active{border-color:var(--action-orange)}.palette-selector__bar{display:flex;width:100%;height:18px;border-radius:3px;overflow:hidden}.palette-selector__bar--theme{height:12px;opacity:.85}.palette-selector__swatch{flex:1;min-width:0}.palette-selector__label{font-size:.7rem;color:var(--text-muted);text-align:left}.palette-selector__custom{display:flex;flex-direction:column;gap:6px}.palette-selector__row{display:flex;flex-direction:column;gap:4px}.palette-selector__row-label{font-size:.6rem;color:var(--text-muted);text-transform:uppercase;letter-spacing:.5px;font-weight:var(--font-weight-semibold)}.palette-selector__row-slots{display:flex;gap:4px;flex-wrap:wrap}.palette-selector__color-input{width:24px;height:24px;padding:0;border:1.5px solid rgba(255,255,255,.25);border-radius:var(--radius-sm);background:transparent;cursor:pointer;transition:border-color var(--transition-fast);flex-shrink:0}.palette-selector__color-input:hover:not(:disabled){border-color:#ffffff80}.palette-selector__color-input:hover:not(:disabled){border-color:var(--action-orange)}.palette-selector__color-input::-webkit-color-swatch-wrapper{padding:2px}.palette-selector__color-input::-webkit-color-swatch{border:none;border-radius:2px}.ddp-field{width:100%;min-width:0;display:block}.ddp-field .react-datepicker-wrapper,.ddp-field .react-datepicker__input-container{width:100%;display:block}.ddp-field .react-datepicker__input-container input{width:100%;padding:var(--spacing-sm) var(--spacing-md);background:var(--bg-elevated);border:1.5px solid var(--bg-elevated);border-radius:var(--radius-sm);font-size:.8125rem;color:var(--text-primary);box-sizing:border-box;transition:border-color var(--transition-fast)}.ddp-field .react-datepicker__input-container input:focus{outline:none;border-color:var(--action-orange)}.ddp-field .react-datepicker__input-container input::placeholder{color:var(--text-muted)}.ddp-field .react-datepicker__input-container input:disabled{opacity:.6;cursor:not-allowed}.ddp-field .react-datepicker__month{min-height:168px}.react-datepicker-popper{z-index:1100!important}.widget{flex:1;display:flex;flex-direction:column;padding:var(--spacing-sm);background:var(--bg-elevated);border-radius:var(--radius-md);overflow:hidden;box-sizing:border-box;min-height:0;min-width:0}.widget__title{flex-shrink:0;margin:0 0 clamp(2px,1cqmin,8px);font-size:clamp(.5rem,4cqi,.9rem);font-weight:var(--font-weight-semibold);color:var(--text-secondary);line-height:1.2;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.widget__state{flex:1;display:flex;align-items:center;justify-content:center;text-align:center;padding:var(--spacing-xs);font-size:clamp(.45rem,2.5cqi,.85rem);color:var(--text-muted)}.widget__state--error{color:var(--color-error)}.widget-filter,.widget-palette{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-start;gap:clamp(4px,1.5cqi,12px);padding:clamp(4px,1cqi,8px) clamp(6px,1.5cqi,12px);box-sizing:border-box;min-height:0;min-width:0;overflow:hidden}.widget-variable{flex:1;display:flex;flex-direction:column;justify-content:center;align-items:center;box-sizing:border-box;min-height:0;min-width:0;overflow:hidden}.widget-filter__label,.widget-palette__label,.widget-variable__label{flex-shrink:0;font-size:clamp(.45rem,6cqi,3rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-kpi{justify-content:center;align-items:center;text-align:center;gap:clamp(2px,1cqmin,10px);padding:clamp(4px,2cqmin,16px)}.widget-kpi .widget__title{margin:0;font-size:clamp(.45rem,min(12cqi,12cqb),6rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-kpi__value{font-size:clamp(.85rem,min(22cqi,22cqb),8rem);font-weight:var(--font-weight-bold);color:var(--text-primary);line-height:1.1;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-variant-numeric:tabular-nums}.widget-kpi__trend{display:flex;align-items:center;justify-content:center;gap:.35em .7em;font-size:clamp(.4rem,min(8cqi,8cqb),2rem);max-width:100%;overflow:hidden;flex-wrap:wrap}.widget-kpi__trend--good{color:var(--color-success)}.widget-kpi__trend--bad{color:var(--color-error)}.widget-kpi__trend--muted{opacity:.75;font-size:.9em}.widget-kpi__variance{font-weight:var(--font-weight-semibold);white-space:nowrap}.widget-kpi__trend-label{color:var(--text-muted);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@container (max-width: 180px){.widget-kpi__trend-label{display:none}}@container (max-height: 70px){.widget-kpi .widget__title{display:none}}.widget-gauge{align-items:center;gap:0;overflow:hidden}.widget-gauge .widget__title{margin:0;font-size:clamp(.5rem,6cqi,3rem);color:var(--text-muted);font-weight:var(--font-weight-medium)}.widget-gauge__chart{position:relative;width:100%;flex:1;min-height:0}.widget-gauge__chart svg{margin-top:5%;display:block;width:100%;height:100%}.widget-gauge__center{position:absolute;top:0;right:0;bottom:0;left:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:2px;margin-top:25%}.widget-gauge__percent{font-size:clamp(.5rem,9cqi,4rem);font-weight:var(--font-weight-bold);color:var(--text-primary);line-height:1}.widget-gauge__comparison{font-size:clamp(.4rem,3.5cqi,2rem);color:var(--text-muted)}.widget-gauge__badge{font-size:clamp(.35rem,3cqi,1.25rem);font-weight:var(--font-weight-semibold);text-transform:uppercase;letter-spacing:.3px;padding:1px var(--spacing-xs);border-radius:var(--radius-sm);background:color-mix(in srgb,var(--color-success) 15%,transparent);color:var(--color-success)}.widget-chart{gap:var(--spacing-xs)}.widget-chart .widget__title{color:var(--text-primary)}.widget-chart__container{flex:1;min-height:0;overflow:hidden}.widget-composition{gap:var(--spacing-xs)}.widget-composition .widget__title{color:var(--text-primary)}.widget-composition__container{flex:1;min-height:0;overflow:hidden}.widget-composition__tooltip{display:flex;flex-direction:column;gap:2px;padding:6px 10px;border:1px solid var(--bg-paper);border-radius:6px;background-color:var(--bg-elevated);font-size:.75rem;line-height:1.3}.widget-composition__tooltip-label{color:var(--text-primary);font-weight:var(--font-weight-semibold)}.widget-composition__tooltip-value{color:var(--text-secondary)}.widget-table{display:flex;flex-direction:column;gap:.4rem;height:100%;overflow:hidden;padding:.5rem .6rem;box-sizing:border-box}.widget-table__td--placeholder{color:var(--text-muted, #999);text-align:center;padding:.75rem .5rem}.widget-table__scroll{flex:1 1 auto;min-height:0;overflow:auto}.widget-table__scroll--clip{overflow:hidden}.widget-table__table{width:100%;border-collapse:collapse;font-size:clamp(.78rem,1.5cqmin,1.25rem)}.widget-table__table--fill{height:100%}.widget-table__th--index,.widget-table__td--index{width:1%;text-align:right;color:var(--text-muted, #999);font-variant-numeric:tabular-nums;white-space:nowrap}.widget-table__th{position:sticky;top:0;z-index:1;text-align:left;font-weight:600;color:var(--text-secondary, #ccc);background:var(--bg-elevated, #333);padding:.35rem .5rem;border-bottom:1px solid var(--border, rgba(255, 255, 255, .12));white-space:nowrap}.widget-table__th--num{text-align:right}.widget-table__td{padding:.3rem .5rem;color:var(--text-primary, #f5f5f5);border-bottom:1px solid var(--border, rgba(255, 255, 255, .06));white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:26ch}.widget-table__td--num{text-align:right;font-variant-numeric:tabular-nums}.widget-table__td--up{color:var(--color-success, #a4c639);font-weight:600}.widget-table__td--down{color:var(--color-error, #e5534b);font-weight:600}.widget-table__table tbody tr:hover{background:#ffffff08}.widget-filter__date-range{display:flex;align-items:center;gap:clamp(2px,1cqi,8px);flex:1;min-width:0}.widget-filter__date-range--stacked{flex-direction:column;align-items:stretch;gap:clamp(4px,1.5cqmin,10px);width:100%;padding:clamp(2px,1cqmin,8px) 0}.widget-filter__date-range .ddp-field{flex:1;min-width:0;width:100%}.widget-filter__date-range .ddp-field .react-datepicker__input-container input,.widget-filter__select{padding:clamp(8px,4cqmin,22px) clamp(6px,1.5cqmin,12px);font-size:clamp(.5rem,10cqmin,2rem);background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);color:var(--text-primary);flex:1;min-width:0;width:100%;box-sizing:border-box;text-align:center;font-variant-numeric:tabular-nums}.widget-filter__date-sep{font-size:clamp(.35rem,2.5cqi,.8rem);color:var(--text-muted)}.widget-filter__multi{display:flex;flex-direction:column;align-items:stretch;justify-content:space-around;gap:clamp(4px,1.5cqmin,14px);flex:1;min-height:0;width:100%;padding:clamp(6px,2cqmin,14px) clamp(4px,2cqmin,12px);box-sizing:border-box;overflow-y:auto}.widget-filter__multi::-webkit-scrollbar{width:6px}.widget-filter__multi::-webkit-scrollbar-track{background:transparent}.widget-filter__multi::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}.widget-filter__multi::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.widget-filter__multi-clear{flex-shrink:0;width:100%;padding:clamp(3px,1cqmin,8px) clamp(8px,2.5cqmin,14px);background:transparent;border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);color:var(--action-orange);font-size:clamp(.4rem,7cqmin,1rem);font-weight:var(--font-weight-semibold);text-align:center;cursor:pointer;transition:background-color var(--transition-fast),border-color var(--transition-fast)}.widget-filter__multi-clear:hover{background-color:var(--bg-elevated);border-color:var(--action-orange)}.widget-filter__multi-option{display:flex;align-items:center;gap:clamp(6px,4cqmin,14px);padding:clamp(4px,1.5cqmin,12px) clamp(8px,2.5cqmin,14px);height:clamp(20px,18cqb,120px);background:var(--bg-paper);border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);cursor:pointer;transition:border-color var(--transition-fast),background-color var(--transition-fast);font-size:clamp(.45rem,8cqmin,1.2rem);font-weight:var(--font-weight-medium);color:var(--text-primary);line-height:1;flex-shrink:0;box-sizing:border-box}.widget-filter__multi-option:hover{border-color:var(--text-muted);background-color:var(--bg-elevated)}.widget-filter__multi-option:has(input[type=checkbox]:checked){border-color:var(--text-muted);background-color:var(--bg-elevated)}.widget-filter__multi-option input[type=checkbox]{appearance:none;-webkit-appearance:none;-moz-appearance:none;width:clamp(12px,7cqmin,22px);height:clamp(12px,7cqmin,22px);border:1.5px solid var(--text-muted);border-radius:3px;background:var(--bg-elevated);cursor:pointer;position:relative;flex-shrink:0;transition:border-color var(--transition-fast),background-color var(--transition-fast);margin:0}.widget-filter__multi-option input[type=checkbox]:hover{border-color:var(--action-orange)}.widget-filter__multi-option input[type=checkbox]:checked{background:var(--action-orange);border-color:var(--action-orange)}.widget-filter__multi-option input[type=checkbox]:checked:after{content:"";position:absolute;left:30%;top:8%;width:30%;height:60%;border:solid var(--bg-dark);border-width:0 2px 2px 0;transform:rotate(45deg)}.widget-filter__select{width:95%;max-height:45%;margin-top:2%;flex:1;font-size:clamp(.4rem,5cqi,1.5rem);font-weight:var(--font-weight-semibold);color:var(--text-primary);text-align:left;padding:clamp(8px,4cqi,22px) clamp(6px,1.5cqi,12px);min-width:0;box-sizing:border-box}.widget-filter>.widget-filter__select,.widget-filter__date-range--year .widget-filter__select,.widget-filter__date-range--month .widget-filter__select,.widget-filter__date-range--week .widget-filter__select{text-align:center;text-align-last:center;font-weight:var(--font-weight-semibold);color:var(--text-primary);background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);cursor:pointer;appearance:none;-webkit-appearance:none;-moz-appearance:none;background-image:none;transition:border-color var(--transition-fast),background-color var(--transition-fast);box-sizing:border-box;width:100%;margin-top:0;max-height:none;padding:clamp(2px,.8cqmin,6px) clamp(6px,1.5cqmin,12px);line-height:1}.widget-filter>.widget-filter__select:hover,.widget-filter>.widget-filter__select:focus,.widget-filter__date-range--year .widget-filter__select:hover,.widget-filter__date-range--year .widget-filter__select:focus,.widget-filter__date-range--month .widget-filter__select:hover,.widget-filter__date-range--month .widget-filter__select:focus,.widget-filter__date-range--week .widget-filter__select:hover,.widget-filter__date-range--week .widget-filter__select:focus{outline:none;border-color:var(--action-orange);background-color:var(--bg-elevated)}.widget-filter>.widget-filter__select option,.widget-filter__date-range--year .widget-filter__select option,.widget-filter__date-range--month .widget-filter__select option,.widget-filter__date-range--week .widget-filter__select option{background:var(--bg-paper);color:var(--text-primary);font-size:.875rem;font-weight:var(--font-weight-normal);text-align:left;padding:6px 10px}.widget-filter>.widget-filter__select{flex:0 1 auto;height:clamp(50px,22cqmin,140px);max-height:75%;margin-block:auto;align-self:center;font-size:clamp(.6rem,12cqmin,2.2rem)}.widget-filter__date-range--year,.widget-filter__date-range--month,.widget-filter__date-range--week{display:flex;flex-direction:column;align-items:stretch;justify-content:center;gap:clamp(6px,2.5cqmin,16px);flex:1;width:100%;padding:clamp(6px,2cqmin,16px) clamp(4px,2cqmin,14px);box-sizing:border-box}.widget-filter__date-range--year .widget-filter__select{flex:0 1 auto;height:clamp(50px,22cqmin,140px);font-size:clamp(.6rem,12cqmin,2.2rem)}.widget-filter__date-range--month .widget-filter__select{flex:0 1 auto;height:clamp(30px,10cqmin,66px);font-size:clamp(.5rem,10cqmin,1.4rem)}.widget-filter__date-range--week .widget-filter__select{flex:0 1 auto;height:clamp(22px,12cqmin,48px);font-size:clamp(.45rem,8cqmin,3rem)}.widget-filter__search{position:relative;display:flex;align-items:center;flex:1;min-width:0;width:100%;padding:clamp(2px,1cqmin,8px) 0}.widget-filter .widget-filter__search-field{width:100%;padding:clamp(6px,3cqmin,18px) clamp(8px,2cqmin,14px);background:var(--bg-dark);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);color:var(--text-primary);font-size:clamp(.55rem,10cqmin,1.8rem);font-weight:var(--font-weight-semibold);text-align:center;box-sizing:border-box;cursor:text;transition:border-color var(--transition-fast),background-color var(--transition-fast)}.widget-filter .widget-filter__search-field::placeholder{color:var(--text-muted);font-weight:var(--font-weight-normal)}.widget-filter .widget-filter__search-field:hover,.widget-filter .widget-filter__search-field:focus{outline:none;border-color:var(--action-orange);background-color:var(--bg-paper)}.widget-filter__search-panel{z-index:10000;display:flex;flex-direction:column;background:var(--bg-paper);border:1px solid var(--bg-elevated);border-radius:var(--radius-sm);box-shadow:var(--shadow-md, 0 8px 28px rgba(0, 0, 0, .45));overflow:hidden}.widget-filter__search-list{display:flex;flex-direction:column;gap:2px;padding:6px;overflow-y:auto}.widget-filter__search-option{display:flex;align-items:center;gap:8px;width:100%;padding:8px 10px;background:transparent;border:none;border-left:3px solid transparent;border-radius:var(--radius-sm);color:var(--text-primary);font-size:.85rem;font-weight:var(--font-weight-medium);text-align:left;cursor:pointer;transition:background-color var(--transition-fast),color var(--transition-fast)}.widget-filter__search-option:hover{background-color:var(--bg-elevated)}.widget-filter__search-option.is-selected{background-color:var(--bg-elevated);border-left-color:var(--action-orange);color:var(--action-orange)}.widget-filter__search-check{flex-shrink:0;width:1em;color:var(--action-orange);font-weight:var(--font-weight-semibold)}.widget-filter__search-option input[type=checkbox]{width:16px;height:16px;flex-shrink:0;accent-color:var(--action-orange);cursor:pointer}.widget-filter__search-clear{width:100%;margin-bottom:4px;padding:8px 10px;background:transparent;border:none;border-bottom:1px solid var(--bg-elevated);border-radius:0;color:var(--action-orange);font-size:.8rem;font-weight:var(--font-weight-semibold);text-align:left;cursor:pointer;transition:background-color var(--transition-fast)}.widget-filter__search-clear:hover{background-color:var(--bg-elevated)}.widget-filter__search-empty{padding:12px;color:var(--text-muted);font-size:.85rem;text-align:center}.widget-filter__search-list::-webkit-scrollbar{width:6px}.widget-filter__search-list::-webkit-scrollbar-track{background:transparent}.widget-filter__search-list::-webkit-scrollbar-thumb{background:var(--bg-elevated);border-radius:3px}.widget-filter__search-list::-webkit-scrollbar-thumb:hover{background:var(--text-muted)}.widget-variable__input-wrapper{display:flex;align-items:center;margin-top:2%;width:90%;background:var(--bg-paper);border:1px solid rgba(255,255,255,.1);border-radius:var(--radius-sm);overflow:hidden}.widget-variable__input{flex:1;font-size:clamp(.4rem,5cqi,1.5rem);font-weight:var(--font-weight-semibold);background:transparent;border:none;outline:none;color:var(--text-primary);text-align:left;padding:clamp(2px,1cqi,6px) clamp(4px,1.5cqi,8px);min-width:0;box-sizing:border-box}.widget-variable__input::-webkit-outer-spin-button,.widget-variable__input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.widget-variable__input[type=number]{-moz-appearance:textfield;-webkit-appearance:textfield;appearance:textfield}.widget-variable__input:disabled{opacity:.6;cursor:not-allowed}.widget-variable__suffix{font-size:clamp(.4rem,4cqi,1.25rem);color:var(--text-muted);white-space:nowrap;padding:0 clamp(4px,1.5cqi,8px);border-left:1px solid rgba(255,255,255,.1);flex-shrink:0}.widget-variable__lock-icon{font-size:clamp(.45rem,2.5cqi,.75rem)}.widget-variable--locked .widget-variable__input-wrapper{border-style:dashed}.widget-palette{flex-direction:column;justify-content:flex-start;align-items:stretch;padding:clamp(4px,1.5cqmin,12px);gap:clamp(2px,1cqmin,8px);overflow:auto}.widget-palette__label{text-align:center;flex-shrink:0}.widget-palette__lock-icon{font-size:clamp(.45rem,2.5cqmin,.75rem);align-self:center}.widget-palette--locked .palette-selector__color-input{opacity:.6;cursor:not-allowed}.widget-palette .palette-selector{gap:clamp(2px,3cqmin,28px);flex:1;min-height:0;justify-content:center}.widget-palette .palette-selector__row{gap:clamp(1px,1.2cqmin,10px);min-height:0}.widget-palette .palette-selector__row-label{font-size:clamp(.35rem,1.8cqmin,.7rem);line-height:1}.widget-palette .palette-selector__row-slots{gap:clamp(1px,.8cqmin,6px);flex-wrap:nowrap;justify-content:space-between;width:100%;min-height:0}.widget-palette .palette-selector__color-input{flex:1 1 0;min-width:0;min-height:0;width:auto;height:clamp(8px,10cqmin,60px);border:1px solid rgba(255,255,255,.2);padding:0}.widget-palette .palette-selector__color-input:hover:not(:disabled){border-color:#fff6}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { FilterDefinition, FormatType } from './index';
|
|
2
2
|
/** Natureza da linha. Apenas `data` e `formula` produzem numero. */
|
|
3
3
|
export type StatementLineType = 'data' | 'formula' | 'header' | 'separator';
|
|
4
|
-
export type PeriodGranularity = 'month' | 'quarter' | 'year';
|
|
4
|
+
export type PeriodGranularity = 'day' | 'week' | 'month' | 'quarter' | 'year';
|
|
5
5
|
export interface StatementLineStyle {
|
|
6
6
|
/** Nivel de recuo do rotulo (0 a 6). */
|
|
7
7
|
indent: number;
|
|
@@ -66,6 +66,12 @@ export interface StatementRenderResponse {
|
|
|
66
66
|
applied: Record<string, unknown>;
|
|
67
67
|
columns: StatementPeriodColumn[];
|
|
68
68
|
lines: StatementComputedLine[];
|
|
69
|
+
/**
|
|
70
|
+
* A janela pediu mais colunas do que o teto permite e o documento mostra as
|
|
71
|
+
* primeiras. Precisa ser exibido: num documento financeiro, terminar antes do
|
|
72
|
+
* periodo pedido sem avisar e afirmar um total que nao foi somado.
|
|
73
|
+
*/
|
|
74
|
+
truncated?: boolean;
|
|
69
75
|
}
|
|
70
76
|
export interface StatementLayoutResponse {
|
|
71
77
|
name: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@actionexec/dashboards",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.1",
|
|
4
4
|
"description": "Biblioteca de renderizacao de dashboards da plataforma Action — componente <Dashboard> unico, consumindo /external/dashboards.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|