@actionexec/dashboards 0.16.0 → 0.16.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/internals.js CHANGED
@@ -1,5 +1,5 @@
1
- import { T as L, F as T } from "./ColorPaletteSelector-CxUQv9E9.js";
2
- import { H as I, I as R, x as r, J as n, K as P, L as D, t as m, N as F, C as g, O as M, P as N, Q as i, R as C, U as G, V as c, W as U, D as W, X as h, Y as l, Z as p, _ as u, $ as B, w as Y, G as d, a0 as H, a1 as k, y as X, a2 as f, k as V, M as b, a3 as $, a4 as w, a5 as x, a6 as j, a7 as y, S as q, a8 as v, a9 as J, aa as K, ab as Q, c as Z, b as z, u as aa, d as sa, v as ea, ac as Ea, ad as _a, e as La, g as Ta, o as ta, ae as Sa, n as Aa, l as Oa, s as oa, q as Ia, af as Ra, ag as ra, h as na, i as Pa, ah as Da, j as ma, m as Fa, ai as ga, p as Ma, r as Na, aj as ia } from "./ColorPaletteSelector-CxUQv9E9.js";
1
+ import { T as L, F as T } from "./ColorPaletteSelector-nBO_fbbj.js";
2
+ import { H as I, I as R, x as r, J as n, K as P, L as D, t as m, N as F, C as g, O as M, P as N, Q as i, R as C, U as G, V as c, W as U, D as W, X as h, Y as l, Z as p, _ as u, $ as B, w as Y, G as d, a0 as H, a1 as k, y as X, a2 as f, k as V, M as b, a3 as $, a4 as w, a5 as x, a6 as j, a7 as y, S as q, a8 as v, a9 as J, aa as K, ab as Q, c as Z, b as z, u as aa, d as sa, v as ea, ac as Ea, ad as _a, e as La, g as Ta, o as ta, ae as Sa, n as Aa, l as Oa, s as oa, q as Ia, af as Ra, ag as ra, h as na, i as Pa, ah as Da, j as ma, m as Fa, ai as ga, p as Ma, r as Na, aj as ia } from "./ColorPaletteSelector-nBO_fbbj.js";
3
3
  const t = "−";
4
4
  function A(a) {
5
5
  const s = a.amount ?? 0;
@@ -0,0 +1 @@
1
+ export {};
@@ -15,5 +15,17 @@ interface Props {
15
15
  onVariableChange?: (value: number) => void;
16
16
  onPaletteChange?: (colors: string[]) => void;
17
17
  }
18
- export declare function WidgetRenderer({ type, computed, palette, config, filterValue, filterOptions, dateBounds, onFilterChange, variableValue, onVariableChange, onPaletteChange, }: Props): import("react/jsx-runtime").JSX.Element | null;
18
+ declare function WidgetRendererBase({ type, computed, palette, config, filterValue, filterOptions, dateBounds, onFilterChange, variableValue, onVariableChange, onPaletteChange, }: Props): import("react/jsx-runtime").JSX.Element | null;
19
+ /**
20
+ * Memoizado: um dashboard redesenha TODOS os widgets a cada mudanca de estado
21
+ * da tela — digitar numa variavel, arrastar um filtro, o container mudar de
22
+ * largura. Sem isto, cada uma dessas mexidas redesenhava tambem os graficos,
23
+ * que sao os widgets mais caros da tela, para chegar exatamente ao mesmo
24
+ * resultado.
25
+ *
26
+ * A memoizacao so vale se as props chegarem estaveis: `Dashboard` guarda os
27
+ * handlers por widget e usa constantes de modulo no lugar de `{}` e `[]`
28
+ * literais, que nasceriam diferentes a cada render.
29
+ */
30
+ export declare const WidgetRenderer: import("react").MemoExoticComponent<typeof WidgetRendererBase>;
19
31
  export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actionexec/dashboards",
3
- "version": "0.16.0",
3
+ "version": "0.16.2",
4
4
  "description": "Biblioteca de renderizacao de dashboards da plataforma Action — componente <Dashboard> unico, consumindo /external/dashboards.",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1 +0,0 @@
1
- {"version":3,"file":"ColorPaletteSelector-CxUQv9E9.js","sources":["../src/api/fetcher.ts","../src/palettes/index.ts","../src/types/index.ts","../src/utils/grid.ts","../src/utils/format.ts","../src/utils/date.ts","../src/components/DashboardDatePicker.tsx","../src/components/SearchableSelect.tsx","../src/components/ColorPaletteSelector.tsx"],"sourcesContent":["// Purpose: Client HTTP interno da API Action (endpoints /external/*).\n// Scope: Infraestrutura da lib — nao exportado no index publico. Consumidor\n// externo usa <Dashboard token /> ou <Statement token />, que encapsulam tudo.\n// Uma base de URL so para as duas verticais: `setApiUrl` aponta ambas.\n// Public API (interno): fetchLayout, fetchRender, fetchStatementLayout,\n// fetchStatementRender, fetchStatementPdf, ApiError, setApiUrl\n\nimport type { LayoutResponse, RenderResponse } from '../types';\nimport type { StatementLayoutResponse, StatementRenderResponse } from '../types/statement';\n\nconst DEFAULT_API_URL = 'https://action-data-api-7mbrztperq-rj.a.run.app';\n\nconst DASHBOARDS_PREFIX = '/external/dashboards';\nconst STATEMENTS_PREFIX = '/external/statements';\n\n// URL efetiva — pode ser sobrescrita via `setApiUrl` (uso interno em dev).\nlet apiUrl = DEFAULT_API_URL;\n\n/** Sobrescreve a URL base da API. Destinado ao builder da plataforma em dev —\n * consumidores externos nao devem chamar (usam a URL de producao por default). */\nexport function setApiUrl(url: string): void {\n apiUrl = url.replace(/\\/$/, '');\n}\n\nexport class ApiError extends Error {\n constructor(\n message: string,\n public status?: number,\n public payload?: unknown,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\n/** Requisicao autenticada; lanca ApiError fora da faixa 2xx. */\nasync function request(\n prefix: string,\n path: string,\n token: string,\n params?: Record<string, string>,\n): Promise<Response> {\n const url = new URL(`${apiUrl}${prefix}${path}`);\n if (params) {\n for (const [k, v] of Object.entries(params)) url.searchParams.set(k, v);\n }\n\n const res = await fetch(url.toString(), {\n headers: { Authorization: `Bearer ${token}` },\n });\n\n if (!res.ok) {\n let payload: unknown;\n try { payload = await res.json(); } catch { /* non-json */ }\n throw new ApiError(\n `Requisicao falhou (${res.status}) em ${path}`,\n res.status,\n payload,\n );\n }\n return res;\n}\n\nasync function get<T>(\n prefix: string,\n path: string,\n token: string,\n params?: Record<string, string>,\n): Promise<T> {\n const res = await request(prefix, path, token, params);\n return (await res.json()) as T;\n}\n\n// -------Dashboards-------\n\nexport const fetchLayout = (token: string) =>\n get<LayoutResponse>(DASHBOARDS_PREFIX, '/layout', token);\n\nexport const fetchRender = (token: string, params?: Record<string, string>) =>\n get<RenderResponse>(DASHBOARDS_PREFIX, '/render', token, params);\n\n// -------Demonstrativos-------\n\nexport const fetchStatementLayout = (token: string) =>\n get<StatementLayoutResponse>(STATEMENTS_PREFIX, '/layout', token);\n\nexport const fetchStatementRender = (token: string, params?: Record<string, string>) =>\n get<StatementRenderResponse>(STATEMENTS_PREFIX, '/render', token, params);\n\n/**\n * Baixa o documento em PDF.\n *\n * Vem como blob, e nao como link direto, porque o token viaja no cabecalho\n * Authorization: um `<a href>` exigiria o token na URL, que fica no historico do\n * navegador, no Referer e nos logs de acesso.\n */\nexport const fetchStatementPdf = async (\n token: string,\n params?: Record<string, string>,\n): Promise<Blob> => {\n const res = await request(STATEMENTS_PREFIX, '/pdf', token, params);\n return res.blob();\n};\n","// Purpose: Paletas de cores completas para dashboards (series de dados + cores de UI).\n// Scope: Define paletas com 13 slots semanticos (5 series + 8 cores de UI) e helpers\n// para extrair series e gerar CSS variables aplicaveis ao escopo do dashboard.\n// Public API: PALETTES, PaletteKey, Palette, getSeries, getPaletteCssVars,\n// SLOT_INDEX, SLOT_LABELS, DEFAULT_PALETTE_COLORS, ensurePaletteShape\n\nexport interface Palette {\n label: string;\n colors: string[]; // 13 cores ordenadas pelos slots semanticos\n}\n\nexport type PaletteKey = 'action' | 'westCoast' | 'mono' | 'ocean' | 'princess';\n\n// -------Slots semanticos (indices fixos no array de cores)-------\n//\n// Convencao posicional para manter o storage como string[] (compativel com schemas\n// Pydantic e o tipo `PaletteConfig.paletteColors`). Cada paleta deve ter 13 cores.\n\nexport const SLOT_INDEX = {\n series0: 0,\n series1: 1,\n series2: 2,\n series3: 3,\n series4: 4,\n bgDark: 5,\n bgPaper: 6,\n bgElevated: 7,\n textPrimary: 8,\n textMuted: 9,\n accent: 10,\n success: 11,\n error: 12,\n // Alerta e informacao tem slot proprio: derivá-los de cores de serie fazia\n // trocar a cor de uma serie mudar o significado semantico de \"atencao\".\n warning: 13,\n info: 14,\n} as const;\n\nexport const SERIES_COUNT = 5;\nexport const TOTAL_SLOTS = 15;\n\nexport const SLOT_LABELS: Record<keyof typeof SLOT_INDEX, string> = {\n series0: 'Série 1',\n series1: 'Série 2',\n series2: 'Série 3',\n series3: 'Série 4',\n series4: 'Série 5',\n bgDark: 'Fundo Escuro',\n bgPaper: 'Fundo Cartão',\n bgElevated: 'Fundo Elevado',\n textPrimary: 'Texto Primário',\n textMuted: 'Texto Secundário',\n accent: 'Destaque',\n success: 'Sucesso',\n error: 'Erro',\n warning: 'Alerta',\n info: 'Informação',\n};\n\n// -------Presets-------\n\nexport const PALETTES: Record<PaletteKey, Palette> = {\n action: {\n label: 'Action',\n colors: [\n '#ff6b00', '#a3e635', '#e3f544', '#65ffd1', '#ff0404',\n '#1a1a1a',\n '#262626',\n '#333333',\n '#f5f5f5',\n '#999999',\n '#ff6b00',\n '#a3e635',\n '#ef4444',\n '#f59e0b',\n '#38bdf8',\n ],\n },\n westCoast: {\n label: 'West Coast',\n colors: [\n '#a3b86c', '#c89b3c', '#8b6f47', '#6b8e23', '#d2691e',\n '#1f1a14',\n '#2a241b',\n '#3a3225',\n '#e8dcc4',\n '#a89878',\n '#c89b3c',\n '#a3b86c',\n '#c44536',\n '#d99a2b',\n '#7c9bb5',\n ],\n },\n mono: {\n label: 'Monocromático',\n colors: [\n '#f8fafc', '#cbd5e1', '#94a3b8', '#64748b', '#475569',\n '#0a0a0a',\n '#171717',\n '#262626',\n '#fafafa',\n '#a3a3a3',\n '#e5e5e5',\n '#cbd5e1',\n '#ef4444',\n '#facc15',\n '#7dd3fc',\n ],\n },\n ocean: {\n label: 'Ocean',\n colors: [\n '#0ea5e9', '#06b6d4', '#0891b2', '#3b82f6', '#22d3ee',\n '#0a1929',\n '#0f2740',\n '#173554',\n '#e0f2fe',\n '#7dd3fc',\n '#22d3ee',\n '#10b981',\n '#f43f5e',\n '#fbbf24',\n '#60a5fa',\n ],\n },\n princess: {\n label: 'Cute Pink',\n colors: [\n '#ff79bc', '#a855f7', '#f472b6', '#d946ef', '#fb7185',\n '#fff0f6',\n '#ffe4ec',\n '#ffffff',\n '#ff4099',\n '#ffadd5',\n '#ec4899',\n '#10b981',\n '#e11d48',\n '#f59e0b',\n '#8b5cf6',\n ],\n },\n};\n\nexport const DEFAULT_PALETTE: PaletteKey = 'action';\n\n// Array de cores default expandido (13 slots)\nexport const DEFAULT_PALETTE_COLORS: string[] = PALETTES.action.colors;\n\n// -------Helpers-------\n\n/** Garante que a paleta tem TOTAL_SLOTS cores. Preenche faltantes com fallback do default. */\nexport function ensurePaletteShape(colors?: string[]): string[] {\n const fallback = DEFAULT_PALETTE_COLORS;\n if (!colors || colors.length === 0) return [...fallback];\n if (colors.length >= TOTAL_SLOTS) return colors.slice(0, TOTAL_SLOTS);\n const result = [...colors];\n for (let i = colors.length; i < TOTAL_SLOTS; i++) result.push(fallback[i]);\n return result;\n}\n\n/** Extrai apenas as cores de series (uso em charts/gauge). */\nexport function getSeries(colors?: string[]): string[] {\n const full = ensurePaletteShape(colors);\n return full.slice(0, SERIES_COUNT);\n}\n\n/** Gera objeto de CSS variables para aplicar inline no escopo do dashboard. */\nexport function getPaletteCssVars(colors?: string[]): Record<string, string> {\n const c = ensurePaletteShape(colors);\n return {\n '--bg-dark': c[SLOT_INDEX.bgDark],\n '--bg-paper': c[SLOT_INDEX.bgPaper],\n '--bg-elevated': c[SLOT_INDEX.bgElevated],\n '--text-primary': c[SLOT_INDEX.textPrimary],\n '--text-secondary': c[SLOT_INDEX.textMuted],\n '--text-muted': c[SLOT_INDEX.textMuted],\n '--color-accent': c[SLOT_INDEX.accent],\n '--color-success': c[SLOT_INDEX.success],\n '--color-error': c[SLOT_INDEX.error],\n '--color-warning': c[SLOT_INDEX.warning],\n '--color-info': c[SLOT_INDEX.info],\n // Aliases historicos, mantidos para nao quebrar CSS de consumidores.\n '--action-orange': c[SLOT_INDEX.accent],\n '--action-green': c[SLOT_INDEX.success],\n };\n}\n","// Purpose: Tipos compartilhados entre backend Python (schemas Pydantic) e frontend.\r\n// Scope: Union discriminada de WidgetDefinition, configs por tipo, respostas da API.\r\n// Public API: Todos os tipos e interfaces exportados + defaults + labels.\r\n\r\nimport { DEFAULT_PALETTE_COLORS } from '../palettes';\r\n\r\n// -------Enums como string literals-------\r\n\r\nexport type AggregationType = 'sum' | 'avg' | 'count' | 'min' | 'max' | 'count_distinct';\r\n/** Como ler a diferença entre o valor do widget e a linha de base. */\r\nexport type ComparisonDisplay = 'variance' | 'difference' | 'ratio' | 'value';\r\n\r\n/** Sentido do indicador: separa a direção (a seta) do julgamento (a cor). */\r\nexport type GoodWhen = 'higher' | 'lower' | 'neutral';\r\nexport type FilterType = 'date_range' | 'select' | 'multi_select';\r\nexport type WidgetType = 'kpi_card' | 'gauge' | 'chart' | 'composition' | 'filter' | 'variable' | 'color_palette' | 'table';\r\nexport type DataWidgetType = 'kpi_card' | 'gauge' | 'chart' | 'composition' | 'table';\r\nexport type ControlWidgetType = 'filter' | 'variable' | 'color_palette';\r\n// Pizza nao esta aqui: virou o widget `composition`, que reparte uma medida\r\n// entre as categorias de uma coluna e nao tem eixo X.\r\nexport type ChartType = 'bar' | 'line' | 'area';\r\nexport type CompositionDisplay = 'pie' | 'bridge';\r\nexport type BridgeDirection = 'ascending' | 'descending';\r\nexport type FormatType = 'currency' | 'number' | 'integer' | 'percentage' | 'date' | 'text';\r\nexport type DateFilterMode = 'range' | 'monthly' | 'weekly' | 'yearly';\r\nexport type Granularity = 'day' | 'week' | 'month' | 'year' | 'weekday';\r\n\r\n// -------Pedacos compartilhados pelos configs-------\r\n\r\nexport interface FilterDefinition {\r\n id: string;\r\n type: FilterType;\r\n label: string;\r\n column?: string | null;\r\n defaultValue?: unknown;\r\n /**\r\n * Como o leitor escolhe a janela, em filtros `date_range`. Ausente é `range`.\r\n *\r\n * No dashboard o modo vem da config do widget de filtro; aqui ele viaja na\r\n * própria definição porque o demonstrativo não tem widgets — a barra dele é\r\n * montada direto das definições que o layout declara.\r\n */\r\n dateFilterMode?: DateFilterMode;\r\n}\r\n\r\nexport interface TargetDefinition {\r\n id: string;\r\n label: string;\r\n value: number;\r\n format: FormatType;\r\n}\r\n\r\nexport interface GridPosition {\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\n/**\r\n * Uma linha de base para o valor do widget, e como ler a diferença.\r\n *\r\n * A base é sempre uma fórmula — a mesma plataforma do valor principal. Não há\r\n * tipos de comparação: \"mês anterior\" é a fórmula do widget com desvio nos\r\n * operandos, e \"vs meta\" é uma fórmula de um operando de variável.\r\n */\r\nexport interface Comparison {\r\n id: string;\r\n label?: string;\r\n formula: KpiTerm[];\r\n display?: ComparisonDisplay;\r\n goodWhen?: GoodWhen;\r\n}\r\n\r\nexport interface AggregationStep {\r\n aggregation: AggregationType;\r\n groupBy: string;\r\n groupGranularity?: Granularity;\r\n}\r\n\r\nexport interface ColumnExpressionTerm {\r\n column: string;\r\n operator?: '+' | '-' | '*' | '/';\r\n}\r\n\r\n// -------Filtro proprio do widget-------\r\n\r\nexport type FilterOperator =\r\n | 'eq' | 'neq' | 'in' | 'not_in'\r\n | 'gt' | 'gte' | 'lt' | 'lte' | 'between'\r\n | 'contains' | 'not_contains' | 'is_empty' | 'not_empty';\r\n\r\nexport interface FilterCondition {\r\n column: string;\r\n op?: FilterOperator;\r\n /** Escalar, lista (in/not_in), par [min, max] (between) ou ausente (is_empty/not_empty). */\r\n value?: unknown;\r\n}\r\n\r\nexport interface WidgetFilter {\r\n conditions: FilterCondition[];\r\n /** all = E entre as condicoes; any = OU. Default: all. */\r\n match?: 'all' | 'any';\r\n}\r\n\r\nexport type TimeOffsetUnit = 'day' | 'week' | 'month' | 'quarter' | 'year';\r\nexport type TimeOffsetMode = 'calendar' | 'window';\r\n\r\n/**\r\n * Desvio da janela de data lida por UM operando.\r\n *\r\n * `amount` negativo olha para tras. Em `calendar` as duas pontas da janela\r\n * recuam `amount` unidades — e o \"mesmo periodo no mes anterior\". Em `window` a\r\n * janela recua blocos contiguos de mesma duracao, e `unit` nao participa.\r\n */\r\nexport interface TimeOffset {\r\n amount: number;\r\n unit?: TimeOffsetUnit;\r\n mode?: TimeOffsetMode;\r\n}\r\n\r\n/**\r\n * Um numero dentro da formula. Tres origens, nesta ordem de precedencia:\r\n * `constant`, `variableId` (widget `variable`) e a cadeia sobre `column`.\r\n */\r\nexport interface KpiOperand {\r\n column?: string;\r\n columnExpression?: ColumnExpressionTerm[];\r\n /** Id de um widget `variable` — valor ajustavel por quem ve o dashboard. */\r\n variableId?: string;\r\n intermediateSteps?: AggregationStep[];\r\n finalAggregation?: AggregationType;\r\n constant?: number;\r\n /** Move a janela de data deste operando, sem afetar os demais termos. */\r\n timeOffset?: TimeOffset;\r\n}\r\n\r\nexport interface KpiTerm {\r\n operand: KpiOperand;\r\n operator?: '+' | '-' | '*' | '/'; // undefined apenas no primeiro termo\r\n}\r\n\r\nexport interface ChartSeriesConfig {\r\n label: string;\r\n // Formula simples\r\n column?: string;\r\n aggregation?: AggregationType;\r\n // Formula composta (pipeline identico ao KPI card, avaliado por grupo do eixo X)\r\n kpiTerms?: KpiTerm[];\r\n}\r\n\r\nexport interface ChartAxisConfig {\r\n column: string;\r\n granularity: Granularity;\r\n}\r\n\r\n// -------Config por tipo de widget-------\r\n\r\n// IDs de widgets de filtro que NAO se aplicam ao widget (default: todos aplicam).\r\n// Compartilhado pelos widgets de dados (kpi_card, gauge, chart).\r\nexport interface WidgetFilterTargeting {\r\n excludedFilters?: string[];\r\n}\r\n\r\nexport interface KpiCardConfig extends WidgetFilterTargeting {\r\n label: string;\r\n format?: FormatType;\r\n column?: string;\r\n aggregation?: AggregationType;\r\n groupBy?: string;\r\n groupGranularity?: Granularity;\r\n outerAggregation?: AggregationType;\r\n kpiTerms?: KpiTerm[];\r\n comparisons?: Comparison[];\r\n filterExpression?: WidgetFilter;\r\n}\r\n\r\n/**\r\n * O gauge não tem conceito próprio de meta: o arco é a primeira comparação lida\r\n * como proporção. Mesma config e mesmo motor do card.\r\n */\r\nexport interface GaugeConfig extends WidgetFilterTargeting {\r\n label: string;\r\n format?: FormatType;\r\n column?: string;\r\n aggregation?: AggregationType;\r\n kpiTerms?: KpiTerm[];\r\n comparisons?: Comparison[];\r\n groupBy?: string;\r\n groupGranularity?: Granularity;\r\n outerAggregation?: AggregationType;\r\n filterExpression?: WidgetFilter;\r\n}\r\n\r\nexport interface ChartConfig extends WidgetFilterTargeting {\r\n label: string;\r\n chartType?: ChartType;\r\n xAxis?: ChartAxisConfig;\r\n series?: ChartSeriesConfig[];\r\n format?: FormatType;\r\n filterExpression?: WidgetFilter;\r\n}\r\n\r\n/**\r\n * Categoria curada da coluna de decomposicao.\r\n *\r\n * `value` e o valor bruto no dataset (`DESP_ADM`, `03.02.001`); `label` e o que\r\n * aparece na barra. A posicao na lista importa so na ponte.\r\n */\r\nexport interface CompositionCategory {\r\n value: string;\r\n label?: string;\r\n}\r\n\r\n/**\r\n * Decomposicao de UMA medida pelas categorias de UMA coluna.\r\n *\r\n * `categories` e a curadoria: quais entram, com que rotulo e — na ponte — em que\r\n * ordem. O que ficar de fora cai em \"Outros\", somado e nunca descartado.\r\n *\r\n * A ponte nao tem ancoras: `direction` decide as duas pontas.\r\n *\r\n * ascending 0 -> +cat1 -> +cat2 -> [total]\r\n * descending [total] -> -cat1 -> -cat2 -> 0\r\n *\r\n * Nos dois sentidos o total e a soma das proprias categorias, entao a ponte\r\n * fecha exatamente — nao ha sobra a explicar.\r\n */\r\nexport interface CompositionConfig extends WidgetFilterTargeting {\r\n label: string;\r\n display?: CompositionDisplay;\r\n categoryColumn?: string;\r\n /** Mesma plataforma de fórmula do KPI card, avaliada por categoria. */\r\n kpiTerms?: KpiTerm[];\r\n /** Vazio = todas as categorias encontradas, por valor decrescente. */\r\n categories?: CompositionCategory[];\r\n /** Nome da barra que agrupa o que ficou fora da curadoria (default \"Outros\"). */\r\n otherLabel?: string;\r\n format?: FormatType;\r\n // Somente ponte\r\n direction?: BridgeDirection;\r\n totalLabel?: string;\r\n filterExpression?: WidgetFilter;\r\n}\r\n\r\n/**\r\n * Coluna de tabela: a fonte da célula, antes de qualquer agregação.\r\n *\r\n * A agregação não vive aqui: cada nível declara o modo de cada coluna, porque a\r\n * mesma coluna pode somar num nível e ser mediada no seguinte.\r\n */\r\nexport interface TableColumnConfig {\r\n id: string;\r\n column?: string; // coluna do dataset reproduzida direto\r\n kpiTerms?: KpiTerm[]; // fórmula avaliada linha a linha\r\n label?: string; // rótulo do cabeçalho\r\n format?: FormatType; // formatação da célula\r\n}\r\n\r\n/**\r\n * Um nível de agregação: por quais colunas agrupa e como cada coluna colapsa.\r\n *\r\n * Os níveis se encadeiam na ordem declarada — o primeiro colapsa os registros, o\r\n * seguinte re-agrega o resultado do anterior. É o que separa \"soma por dia\" de\r\n * \"média das somas por dia\".\r\n */\r\nexport interface TableAggregationLevel {\r\n groupBy?: string[];\r\n /** Modo por id de coluna — a coluna pode ser uma fórmula, sem nome no dataset. */\r\n modes?: Record<string, AggregationType>;\r\n}\r\n\r\n/** Um nível de ordenamento: cita uma coluna da tabela ou uma do dataset. */\r\nexport interface TableSortLevel {\r\n columnId?: string;\r\n column?: string;\r\n direction?: 'asc' | 'desc';\r\n}\r\n\r\n/** O que fazer quando as linhas passam da altura do widget. */\r\nexport type TableOverflow = 'scroll' | 'clip';\r\n\r\nexport interface TableConfig extends WidgetFilterTargeting {\r\n label: string;\r\n columns?: TableColumnConfig[];\r\n /**\r\n * Níveis de agregação, aplicados em cadeia. Vazio = um registro por linha. As\r\n * colunas agrupadas não precisam estar entre as exibidas.\r\n */\r\n aggregations?: TableAggregationLevel[];\r\n sort?: TableSortLevel[];\r\n /** Coluna extra à esquerda com a posição da linha (1, 2, 3...). */\r\n indexColumn?: boolean;\r\n overflow?: TableOverflow;\r\n limit?: number; // maximo de linhas\r\n filterExpression?: WidgetFilter;\r\n}\r\n\r\nexport interface FilterConfig {\r\n label: string;\r\n filterType: FilterType;\r\n filterColumn?: string;\r\n defaultValue?: unknown;\r\n dateFilterMode?: DateFilterMode;\r\n // Apresentacao categorica: true = lista com busca por digitacao; ausente = padrao\r\n // (select unico / checkboxes). Aplica-se a select e multi_select; nao afeta a query.\r\n searchable?: boolean;\r\n // Valores distintos da coluna, preenchidos pelo /layout (select e multi_select).\r\n // Sao estruturais — nao mudam com os filtros aplicados —, por isso viajam no\r\n // layout cacheavel e nao no payload de /render.\r\n availableValues?: string[];\r\n}\r\n\r\nexport interface VariableConfig {\r\n label: string;\r\n variableValue?: number;\r\n variableFormat?: FormatType;\r\n locked?: boolean;\r\n}\r\n\r\nexport interface PaletteConfig {\r\n paletteColors: string[];\r\n label?: string;\r\n locked?: boolean;\r\n}\r\n\r\nexport type AnyWidgetConfig =\r\n | KpiCardConfig | GaugeConfig | ChartConfig | CompositionConfig | TableConfig\r\n | FilterConfig | VariableConfig | PaletteConfig;\r\n\r\n// -------Union discriminada de WidgetDefinition-------\r\n\r\nexport type WidgetDefinition =\r\n | { id: string; type: 'kpi_card'; grid: GridPosition; config: KpiCardConfig }\r\n | { id: string; type: 'gauge'; grid: GridPosition; config: GaugeConfig }\r\n | { id: string; type: 'chart'; grid: GridPosition; config: ChartConfig }\r\n | { id: string; type: 'composition'; grid: GridPosition; config: CompositionConfig }\r\n | { id: string; type: 'table'; grid: GridPosition; config: TableConfig }\r\n | { id: string; type: 'filter'; grid: GridPosition; config: FilterConfig }\r\n | { id: string; type: 'variable'; grid: GridPosition; config: VariableConfig }\r\n | { id: string; type: 'color_palette'; grid: GridPosition; config: PaletteConfig };\r\n\r\nexport type WidgetConfigOf<T extends WidgetType> = Extract<WidgetDefinition, { type: T }>['config'];\r\n\r\n// -------Layout completo-------\r\n\r\nexport interface DashboardLayout {\r\n gridColumns: number;\r\n gridRows: number;\r\n widgets: WidgetDefinition[];\r\n}\r\n\r\n// -------Respostas da API-------\r\n\r\nexport interface FilterValuesResponse {\r\n date_bounds: { min: string | null; max: string | null };\r\n filter_options: Record<string, string[]>;\r\n headers: string[];\r\n column_types: Record<string, string>;\r\n /** Apresentacao declarada por coluna (currency_brl, percent...). */\r\n column_presentations?: Record<string, string>;\r\n /** Coluna que é o eixo temporal do dataset — a que os filtros de data recortam. */\r\n date_column?: string | null;\r\n}\r\n\r\nexport interface RenderResponse {\r\n date_bounds: { min: string; max: string };\r\n applied: Record<string, unknown>;\r\n widgets: Record<string, Record<string, unknown>>;\r\n}\r\n\r\nexport interface LayoutResponse {\r\n name: string;\r\n palette: string[];\r\n gridColumns: number;\r\n gridRows: number;\r\n dateBounds: { min: string; max: string };\r\n widgets: WidgetDefinition[];\r\n}\r\n\r\n// -------Defaults-------\r\n\r\n// Re-export para compatibilidade com codigo existente que importa de dashboardLayout\r\nexport const DEFAULT_PALETTE = DEFAULT_PALETTE_COLORS;\r\n\r\nexport const DEFAULT_GRID_COLUMNS = 30;\r\nexport const DEFAULT_GRID_ROWS = 10;\r\n\r\nexport const EMPTY_LAYOUT: DashboardLayout = {\r\n gridColumns: DEFAULT_GRID_COLUMNS,\r\n gridRows: DEFAULT_GRID_ROWS,\r\n widgets: [],\r\n};\r\n\r\nexport const WIDGET_TYPE_LABELS: Record<WidgetType, string> = {\r\n kpi_card: 'Card',\r\n gauge: 'Gauge',\r\n chart: 'Gráfico',\r\n composition: 'Composição',\r\n table: 'Tabela',\r\n filter: 'Filtro',\r\n variable: 'Variável',\r\n color_palette: 'Paleta de Cores',\r\n};\r\n\r\nexport const DATA_WIDGET_TYPES: DataWidgetType[] = ['kpi_card', 'gauge', 'chart', 'composition', 'table'];\r\nexport const CONTROL_WIDGET_TYPES: ControlWidgetType[] = ['filter', 'variable', 'color_palette'];\r\nexport const CONTROL_WIDGET_SET = new Set<WidgetType>(['filter', 'variable', 'color_palette']);\r\n\r\n// Singular e plural: o desvio aparece como \"−1 mês\" e \"−2 meses\"\r\nexport const TIME_OFFSET_UNIT_LABELS: Record<TimeOffsetUnit, [string, string]> = {\r\n day: ['dia', 'dias'],\r\n week: ['semana', 'semanas'],\r\n month: ['mês', 'meses'],\r\n quarter: ['trimestre', 'trimestres'],\r\n year: ['ano', 'anos'],\r\n};\r\n\r\n// A unidade do modo `window` e a duracao do proprio periodo filtrado: \"−1 período\"\r\n// recua um bloco do tamanho do recorte de datas em vigor.\r\nexport const TIME_OFFSET_WINDOW_LABEL: [string, string] = ['período', 'períodos'];\r\n\r\nexport const AGGREGATION_LABELS: Record<AggregationType, string> = {\r\n sum: 'Soma',\r\n avg: 'Média',\r\n count: 'Contagem',\r\n min: 'Mínimo',\r\n max: 'Máximo',\r\n count_distinct: 'Contagem Distinta',\r\n};\r\n\r\nexport const FORMAT_LABELS: Record<FormatType, string> = {\r\n currency: 'Moeda (R$)',\r\n number: 'Número',\r\n integer: 'Inteiro',\r\n percentage: 'Porcentagem',\r\n date: 'Data',\r\n text: 'Texto',\r\n};\r\n\r\n// Subset de formatos numericos — usado nos configs de KPI, Gauge, Variable\r\nexport const NUMERIC_FORMAT_OPTIONS = Object.entries(FORMAT_LABELS)\r\n .filter(([k]) => k !== 'date' && k !== 'text') as [FormatType, string][];\r\n\r\nexport const COMPARISON_DISPLAY_LABELS: Record<ComparisonDisplay, string> = {\r\n variance: 'Variação %',\r\n difference: 'Diferença',\r\n ratio: 'Proporção',\r\n value: 'Base',\r\n};\r\n\r\nexport const TABLE_OVERFLOW_LABELS: Record<TableOverflow, string> = {\r\n scroll: 'Rolar',\r\n clip: 'Cortar',\r\n};\r\n\r\nexport const GOOD_WHEN_LABELS: Record<GoodWhen, string> = {\r\n higher: 'Positivo',\r\n lower: 'Negativo',\r\n neutral: 'Neutro',\r\n};\r\n\r\nexport const FILTER_OPERATOR_LABELS: Record<FilterOperator, string> = {\r\n eq: 'Igual a',\r\n neq: 'Diferente de',\r\n in: 'Está entre os valores',\r\n not_in: 'Não está entre os valores',\r\n gt: 'Maior que',\r\n gte: 'Maior ou igual a',\r\n lt: 'Menor que',\r\n lte: 'Menor ou igual a',\r\n between: 'Entre (faixa numérica)',\r\n contains: 'Contém',\r\n not_contains: 'Não contém',\r\n is_empty: 'Está vazio',\r\n not_empty: 'Não está vazio',\r\n};\r\n\r\n/** Operadores que dispensam valor — a condição se resolve só pela coluna. */\r\nexport const VALUELESS_FILTER_OPERATORS: FilterOperator[] = ['is_empty', 'not_empty'];\r\n\r\n/** Operadores cujo valor é uma lista de opções. */\r\nexport const LIST_FILTER_OPERATORS: FilterOperator[] = ['in', 'not_in'];\r\n\r\nexport const CHART_TYPE_LABELS: Record<ChartType, string> = {\r\n bar: 'Barras',\r\n line: 'Linhas',\r\n area: 'Área',\r\n};\r\n\r\nexport const COMPOSITION_DISPLAY_LABELS: Record<CompositionDisplay, string> = {\r\n pie: 'Pizza',\r\n bridge: 'Ponte',\r\n};\r\n\r\nexport const BRIDGE_DIRECTION_LABELS: Record<BridgeDirection, string> = {\r\n descending: 'Descendente',\r\n ascending: 'Ascendente',\r\n};\r\n\r\n\r\nexport const FILTER_TYPE_LABELS: Record<FilterType, string> = {\r\n date_range: 'Periodo',\r\n select: 'Seleção Única',\r\n multi_select: 'Seleção Múltipla',\r\n};\r\n\r\n// Separador interno dos valores de filtros multi_select. Usa o caractere de controle\r\n// Unit Separator (U+001F), que nunca aparece em nomes de produtos — evita a colisao\r\n// que a virgula causava quando o proprio valor continha virgula.\r\n// DEVE ser identico ao separador usado no backend (filters.py).\r\nexport const MULTI_VALUE_SEPARATOR = '\\u001f';\r\n\r\n// -------Default grid sizes por tipo de widget-------\r\n\r\nexport const DEFAULT_GRID: Record<WidgetType, GridPosition> = {\r\n kpi_card: { x: 0, y: 0, w: 6, h: 3 },\r\n gauge: { x: 0, y: 0, w: 6, h: 5 },\r\n chart: { x: 0, y: 0, w: 6, h: 6 },\r\n composition: { x: 0, y: 0, w: 6, h: 6 },\r\n table: { x: 0, y: 0, w: 12, h: 7 },\r\n filter: { x: 0, y: 0, w: 4, h: 2 },\r\n variable: { x: 0, y: 0, w: 4, h: 2 },\r\n color_palette: { x: 0, y: 0, w: 4, h: 2 },\r\n};\r\n\r\nexport const DEFAULT_CONFIG: { [K in WidgetType]: Partial<WidgetConfigOf<K>> } = {\r\n kpi_card: { label: 'Novo card', aggregation: 'sum', format: 'number' },\r\n gauge: { label: 'Novo Gauge', aggregation: 'sum' },\r\n chart: { label: 'Novo gráfico', chartType: 'bar', xAxis: { column: '', granularity: 'day' }, series: [] },\r\n composition: {\r\n label: 'Nova composição', display: 'pie',\r\n categories: [], direction: 'descending',\r\n },\r\n table: { label: 'Nova Tabela', columns: [] },\r\n filter: { label: 'Novo Filtro', filterType: 'select' },\r\n variable: { label: 'Nova Variavel', variableValue: 0, variableFormat: 'number', locked: false },\r\n color_palette: { label: 'Paleta de Cores', paletteColors: DEFAULT_PALETTE, locked: false },\r\n};\r\n","// Purpose: Geometria do grid — fonte unica compartilhada pelo runtime (Dashboard)\n// e pelo editor de layout da plataforma Action (CanvasEditor).\n// Scope: Constantes de espacamento e funcoes puras que projetam celulas do grid\n// em pixels. Nenhuma dependencia de React ou DOM.\n// Public API: GRID_GAP_PX, GRID_PADDING_PX, CELL_ASPECT, MIN_CELL_HEIGHT_PX,\n// MAX_CELL_HEIGHT_PX, computeCellWidth, computeCellHeight,\n// computeGridHeight, computeWidgetAspect, computeStackThreshold,\n// DashboardGeometry.\n\n/** Espaco entre celulas, em px. Absoluto de proposito: ver nota de proporcao abaixo. */\nexport const GRID_GAP_PX = 6;\n\n/** Recuo interno do grid, em px. Deve espelhar --spacing-md dos tokens. */\nexport const GRID_PADDING_PX = 16;\n\n/**\n * Proporcao largura/altura da celula. 1 = celula quadrada.\n *\n * A largura da celula e sempre fluida (largura disponivel / numero de colunas).\n * Fixar a proporcao faz a altura acompanhar, de modo que o dashboard mantenha\n * a mesma forma em qualquer aplicacao que o embuta — que e o unico jeito de o\n * editor ser WYSIWYG.\n *\n * O valor 1 nao e arbitrario: com 30 colunas num container de 1440px a coluna\n * mede ~41px, praticamente a altura de linha fixa de 40px usada ate a v0.6.\n * Adotar celula quadrada preserva a aparencia dos dashboards ja montados.\n */\nexport const CELL_ASPECT = 1;\n\n/**\n * Trilhos de seguranca da altura da celula.\n *\n * Fora dessa faixa a proporcao deixa de valer de proposito: abaixo do minimo o\n * dashboard seria pequeno demais para ser lido (container estreito), acima do\n * maximo seria alto demais para caber na viewport (monitor ultrawide). Uma forma\n * levemente distorcida e preferivel a um dashboard inutilizavel.\n *\n * Com 30 colunas, os limites entram abaixo de ~930px e acima de ~2600px de\n * container — ou seja, a proporcao se mantem intacta em toda a faixa de desktop.\n */\nexport const MIN_CELL_HEIGHT_PX = 24;\nexport const MAX_CELL_HEIGHT_PX = 80;\n\nconst clamp = (value: number, min: number, max: number) => Math.min(Math.max(value, min), max);\n\n/**\n * Medida utilizavel: positiva e finita.\n *\n * `cellAspect` e prop publica tipada `number`, e o numero de colunas vem da API —\n * nenhum dos dois barra NaN ou Infinity. Sem esta guarda um NaN atravessa\n * `value <= 0` (que e falso para NaN) e contamina todo o calculo ate virar\n * `--dash-cell-h: NaNpx`, que invalida a declaracao e derruba o grid inteiro.\n */\nconst isUsable = (value: number) => Number.isFinite(value) && value > 0;\n\n/**\n * Largura de uma coluna do grid.\n *\n * `outerWidth` e a largura de borda do elemento do grid (inclui o recuo interno).\n * Identica a formula do react-grid-layout (calcGridColWidth), o que garante que\n * editor e runtime cheguem ao mesmo numero.\n */\nexport function computeCellWidth(\n outerWidth: number,\n columns: number,\n gap: number = GRID_GAP_PX,\n padding: number = GRID_PADDING_PX,\n): number {\n if (!isUsable(columns) || !Number.isFinite(outerWidth)) return 0;\n const available = outerWidth - padding * 2 - gap * (columns - 1);\n return Math.max(0, available / columns);\n}\n\n/** Altura de linha que preserva a proporcao da celula, respeitando os trilhos. */\nexport function computeCellHeight(cellWidth: number, aspect: number = CELL_ASPECT): number {\n if (!isUsable(cellWidth) || !isUsable(aspect)) return MIN_CELL_HEIGHT_PX;\n return clamp(cellWidth / aspect, MIN_CELL_HEIGHT_PX, MAX_CELL_HEIGHT_PX);\n}\n\n/** Altura total ocupada por `rows` linhas, incluindo gaps e recuo interno. */\nexport function computeGridHeight(\n rows: number,\n cellHeight: number,\n gap: number = GRID_GAP_PX,\n padding: number = GRID_PADDING_PX,\n): number {\n if (rows <= 0) return padding * 2;\n return rows * cellHeight + (rows - 1) * gap + padding * 2;\n}\n\n/**\n * Proporcao largura/altura de um widget de `w` x `h` celulas.\n *\n * Ignora o gap interno do widget de proposito: incluir o termo tornaria a\n * proporcao dependente da largura da celula, e portanto nao seria constante.\n * O desvio e o mesmo ~2% que a celula quadrada ja tem, e em troca a proporcao\n * pode ser expressa em CSS puro (`aspect-ratio`), sem medicao.\n */\nexport function computeWidgetAspect(w: number, h: number, aspect: number = CELL_ASPECT): number {\n if (!isUsable(w) || !isUsable(h) || !isUsable(aspect)) return 1;\n return (w * aspect) / h;\n}\n\n/**\n * Largura de container abaixo da qual a proporcao deixa de ser respeitada —\n * o ponto em que a celula bateria em MIN_CELL_HEIGHT_PX.\n *\n * E o limiar natural para trocar de modo: abaixo dele o layout em colunas ja\n * esta distorcido, e empilhar passa a ser a apresentacao mais fiel.\n *\n * Depende da proporcao: como a altura e `cellWidth / aspect`, o piso e atingido\n * quando a largura da celula chega a `MIN_CELL_HEIGHT_PX * aspect`, nao a\n * MIN_CELL_HEIGHT_PX. Ignorar o aspect erraria o limiar para qualquer valor\n * diferente de 1 — com aspect 2 e 30 colunas, por 720px.\n */\nexport function computeStackThreshold(\n columns: number,\n aspect: number = CELL_ASPECT,\n gap: number = GRID_GAP_PX,\n padding: number = GRID_PADDING_PX,\n): number {\n if (!isUsable(columns) || !isUsable(aspect)) return 0;\n return MIN_CELL_HEIGHT_PX * aspect * columns + gap * (columns - 1) + padding * 2;\n}\n\n/** Geometria corrente do grid, reportada ao consumidor via `onGeometryChange`. */\nexport interface DashboardGeometry {\n /** Largura de borda do container do dashboard, em px. */\n containerWidth: number;\n /** Largura da celula do grid. Sem efeito enquanto `stacked` for true. */\n cellWidth: number;\n /** Altura da celula do grid. Sem efeito enquanto `stacked` for true. */\n cellHeight: number;\n /** Altura renderizada do grid, em px — o que o host precisa acomodar. */\n gridHeight: number;\n /** Se o dashboard esta renderizando em coluna unica. */\n stacked: boolean;\n}\n","// Purpose: Formatacao de valores exibidos pelos widgets.\n// Scope: Fonte unica de formatacao no frontend — antes cada widget tinha a sua,\n// e tabela e KPI divergiam no significado de `percentage`. Espelha\n// backend/app/dashboards/widgets/format.py: o backend ja manda `formatted`\n// pronto nos escalares; isto cobre o que e formatado no cliente (celulas de\n// tabela, eixos, rotulos compactos).\n// Public API: formatValue, formatCompact, PERCENTAGE_SCALE\n\nimport type { FormatType } from '../types';\n\nconst LOCALE = 'pt-BR';\n\n/**\n * Percentuais trafegam como fracao (0,153 = 15,3%), igual ao backend\n * (format_value multiplica por 100). Manter a mesma escala nos dois lados evita\n * que a mesma coluna apareca como \"15,3%\" num KPI e \"0%\" numa tabela.\n */\nexport const PERCENTAGE_SCALE = 100;\n\nconst NUMERIC_FORMATS: ReadonlySet<string> = new Set(['currency', 'number', 'integer', 'percentage']);\n\n/** True quando o formato representa um numero (alinhamento a direita, sort numerico). */\nexport function isNumericFormat(format?: string): boolean {\n return !!format && NUMERIC_FORMATS.has(format);\n}\n\n/** Converte para numero finito, ou null se o valor nao for numerico. */\nfunction toNumber(value: unknown): number | null {\n if (value === null || value === undefined || value === '') return null;\n const n = typeof value === 'number' ? value : Number(value);\n return Number.isFinite(n) ? n : null;\n}\n\n/**\n * Formata um valor conforme o tipo de formatacao do widget.\n *\n * `fallback` e devolvido quando o valor esta ausente; valores nao numericos em\n * formato numerico voltam como texto, para nao esconder dado sujo do dataset.\n */\nexport function formatValue(value: unknown, format?: FormatType | string, fallback = '-'): string {\n if (value === null || value === undefined || value === '') return fallback;\n\n const n = toNumber(value);\n if (n === null) return String(value);\n\n switch (format) {\n case 'currency':\n return n.toLocaleString(LOCALE, { style: 'currency', currency: 'BRL' });\n case 'integer':\n return Math.round(n).toLocaleString(LOCALE);\n case 'percentage':\n return `${(n * PERCENTAGE_SCALE).toLocaleString(LOCALE, { maximumFractionDigits: 1 })}%`;\n case 'number':\n return n.toLocaleString(LOCALE, { maximumFractionDigits: 2 });\n default:\n return String(value);\n }\n}\n\n/**\n * Versao abreviada para espacos estreitos (centro do gauge, rotulos de eixo).\n * Preserva o simbolo da moeda quando o formato e monetario.\n */\nexport function formatCompact(value: unknown, format?: FormatType | string): string {\n const n = toNumber(value);\n if (n === null) return '-';\n\n if (format === 'percentage') return formatValue(n, 'percentage');\n\n const prefix = format === 'currency' ? 'R$ ' : '';\n const abs = Math.abs(n);\n\n if (abs >= 1_000_000_000) return `${prefix}${(n / 1_000_000_000).toFixed(1)}B`;\n if (abs >= 1_000_000) return `${prefix}${(n / 1_000_000).toFixed(1)}M`;\n if (abs >= 1_000) return `${prefix}${(n / 1_000).toFixed(1)}K`;\n\n return `${prefix}${n.toLocaleString(LOCALE, { maximumFractionDigits: 2 })}`;\n}\n","// Purpose: Utilitarios de data para filtros temporais de dashboards.\r\n// Scope: Calculo de intervalos anuais/mensais/semanais, parse de ranges, ISO week.\r\n// Public API: MONTH_NAMES_*, getFullYearRange, getMonthRange, getWeekRange, getISOWeek,\r\n// getWeeksInMonth, parseYearFromRange, parseMonthFromRange, parseWeekFromRange,\r\n// getYearRange, getMonthWeeks, MonthWeek, RangeUnit, RangePeriod,\r\n// rangePeriods\r\n\r\nexport const MONTH_NAMES_SHORT = [\r\n 'Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun',\r\n 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez',\r\n];\r\n\r\nexport const MONTH_NAMES_FULL = [\r\n 'Janeiro', 'Fevereiro', 'Marco', 'Abril', 'Maio', 'Junho',\r\n 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro',\r\n];\r\n\r\nexport function getFullYearRange(year: number): { start: string; end: string } {\r\n return { start: `${year}-01-01`, end: `${year}-12-31` };\r\n}\r\n\r\nexport function parseYearFromRange(start: string): { year: number } | null {\r\n if (!start) return null;\r\n const m = start.match(/^(\\d{4})/);\r\n return m ? { year: parseInt(m[1]) } : null;\r\n}\r\n\r\nexport function getMonthRange(year: number, month: number): { start: string; end: string } {\r\n const lastDay = new Date(year, month, 0).getDate();\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n return {\r\n start: `${year}-${pad(month)}-01`,\r\n end: `${year}-${pad(month)}-${pad(lastDay)}`,\r\n };\r\n}\r\n\r\nexport function getISOWeek(dt: Date): number {\r\n const d = new Date(Date.UTC(dt.getFullYear(), dt.getMonth(), dt.getDate()));\r\n d.setUTCDate(d.getUTCDate() + 4 - (d.getUTCDay() || 7));\r\n const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));\r\n return Math.ceil(((d.getTime() - yearStart.getTime()) / 86400000 + 1) / 7);\r\n}\r\n\r\nexport function getWeekRange(year: number, week: number): { start: string; end: string } {\r\n const jan4 = new Date(year, 0, 4);\r\n const dayOfWeek = (jan4.getDay() + 6) % 7;\r\n const firstMonday = new Date(jan4.getTime() - dayOfWeek * 86400000);\r\n const start = new Date(firstMonday.getTime() + (week - 1) * 7 * 86400000);\r\n const end = new Date(start.getTime() + 6 * 86400000);\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n const fmt = (d: Date) => `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`;\r\n return { start: fmt(start), end: fmt(end) };\r\n}\r\n\r\nexport function getWeeksInMonth(year: number, month: number): number[] {\r\n const weeks: Set<number> = new Set();\r\n const daysInMonth = new Date(year, month, 0).getDate();\r\n for (let d = 1; d <= daysInMonth; d++) {\r\n weeks.add(getISOWeek(new Date(year, month - 1, d)));\r\n }\r\n return Array.from(weeks).sort((a, b) => a - b);\r\n}\r\n\r\nexport interface MonthWeek {\r\n index: number;\r\n startDay: number;\r\n endDay: number;\r\n start: string;\r\n end: string;\r\n label: string;\r\n}\r\n\r\nexport function getMonthWeeks(year: number, month: number): MonthWeek[] {\r\n const daysInMonth = new Date(year, month, 0).getDate();\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n const weeks: MonthWeek[] = [];\r\n let day = 1;\r\n let index = 1;\r\n\r\n while (day <= daysInMonth) {\r\n const startDay = day;\r\n const endDay = Math.min(day + 6, daysInMonth);\r\n const start = `${year}-${pad(month)}-${pad(startDay)}`;\r\n const end = `${year}-${pad(month)}-${pad(endDay)}`;\r\n const label = `${index}° Semana (${pad(startDay)}/${pad(month)} - ${pad(endDay)}/${pad(month)})`;\r\n weeks.push({ index, startDay, endDay, start, end, label });\r\n day = endDay + 1;\r\n index++;\r\n }\r\n\r\n return weeks;\r\n}\r\n\r\nexport function parseMonthWeekFromRange(start: string, year: number, month: number): number {\r\n if (!start) return 1;\r\n const pad = (n: number) => String(n).padStart(2, '0');\r\n const dayMatch = start.match(new RegExp(`^${year}-${pad(month)}-(\\\\d{2})`));\r\n if (!dayMatch) return 1;\r\n const day = parseInt(dayMatch[1]);\r\n return Math.ceil(day / 7);\r\n}\r\n\r\nexport function parseMonthFromRange(start: string): { year: number; month: number } | null {\r\n if (!start) return null;\r\n const m = start.match(/^(\\d{4})-(\\d{2})/);\r\n return m ? { year: parseInt(m[1]), month: parseInt(m[2]) } : null;\r\n}\r\n\r\nexport function parseWeekFromRange(start: string): { year: number; week: number } | null {\r\n if (!start) return null;\r\n const d = new Date(start + 'T00:00:00');\r\n if (isNaN(d.getTime())) return null;\r\n return { year: d.getFullYear(), week: getISOWeek(d) };\r\n}\r\n\r\nexport function getYearRange(dateBounds?: { min: string | null; max: string | null } | null): number[] {\r\n const now = new Date();\r\n const minYear = dateBounds?.min ? parseInt(dateBounds.min.slice(0, 4)) : now.getFullYear() - 2;\r\n const maxYear = dateBounds?.max ? parseInt(dateBounds.max.slice(0, 4)) : now.getFullYear();\r\n const years: number[] = [];\r\n for (let y = maxYear; y >= minYear; y--) years.push(y);\r\n return years;\r\n}\r\n\r\n// -------Periodos de uma janela-------\r\n//\r\n// Servem ao intervalo livre do demonstrativo, que recorta na unidade das\r\n// COLUNAS em vez de em dias: num documento por mes, escolher a janela dia a dia\r\n// produz uma primeira e uma ultima coluna parciais que ninguem pediu.\r\n\r\nexport type RangeUnit = 'day' | 'week' | 'month' | 'year';\r\n\r\nexport interface RangePeriod {\r\n /** Chave estavel, tambem usada como valor do <option>. */\r\n key: string;\r\n /** Rotulo pt-BR curto, na mesma grafia dos cabecalhos de coluna. */\r\n label: string;\r\n /** Primeiro e ultimo dia do periodo (ISO). */\r\n start: string;\r\n end: string;\r\n}\r\n\r\nconst pad2 = (n: number) => String(n).padStart(2, '0');\r\n\r\nfunction isoOf(d: Date): string {\r\n return `${d.getFullYear()}-${pad2(d.getMonth() + 1)}-${pad2(d.getDate())}`;\r\n}\r\n\r\n/** Data local a partir de 'YYYY-MM-DD' — `new Date(iso)` interpretaria em UTC. */\r\nfunction fromIso(iso: string): Date {\r\n const [y, m, d] = iso.split('-').map(Number);\r\n return new Date(y, (m || 1) - 1, d || 1);\r\n}\r\n\r\nfunction periodOf(value: Date, unit: RangeUnit): RangePeriod {\r\n const y = value.getFullYear();\r\n\r\n if (unit === 'year') {\r\n return { key: `${y}`, label: `${y}`, start: `${y}-01-01`, end: `${y}-12-31` };\r\n }\r\n if (unit === 'month') {\r\n const m = value.getMonth() + 1;\r\n const range = getMonthRange(y, m);\r\n return {\r\n key: `${y}-${pad2(m)}`,\r\n label: `${MONTH_NAMES_SHORT[m - 1].toLowerCase()}/${pad2(y % 100)}`,\r\n ...range,\r\n };\r\n }\r\n if (unit === 'week') {\r\n const monday = new Date(value.getTime() - ((value.getDay() + 6) % 7) * 86400000);\r\n const sunday = new Date(monday.getTime() + 6 * 86400000);\r\n const week = getISOWeek(monday);\r\n return {\r\n key: `${monday.getFullYear()}-W${pad2(week)}`,\r\n label: `S${pad2(week)}/${pad2(monday.getFullYear() % 100)}`,\r\n start: isoOf(monday),\r\n end: isoOf(sunday),\r\n };\r\n }\r\n return {\r\n key: isoOf(value),\r\n label: `${pad2(value.getDate())}/${pad2(value.getMonth() + 1)}/${pad2(y % 100)}`,\r\n start: isoOf(value),\r\n end: isoOf(value),\r\n };\r\n}\r\n\r\n/** Teto de opcoes da lista. Uma base longa em dias renderiza milhares de <option>. */\r\nconst MAX_PERIOD_OPTIONS = 400;\r\n\r\n/**\r\n * Os periodos de `unit` que cobrem os limites da base, do mais recente ao mais\r\n * antigo — a mesma ordem do seletor de ano, e a que poe o periodo util no topo.\r\n *\r\n * Corta no teto a partir do MAIS RECENTE: numa base de dez anos em dias, as\r\n * opcoes uteis sao as do fim, e listar tudo travaria o <select>.\r\n */\r\nexport function rangePeriods(\r\n unit: RangeUnit,\r\n dateBounds?: { min: string | null; max: string | null } | null,\r\n): RangePeriod[] {\r\n const now = new Date();\r\n const min = dateBounds?.min ? fromIso(dateBounds.min) : new Date(now.getFullYear() - 1, 0, 1);\r\n const max = dateBounds?.max ? fromIso(dateBounds.max) : now;\r\n if (min > max) return [];\r\n\r\n const periods: RangePeriod[] = [];\r\n let cursor = periodOf(max, unit);\r\n\r\n while (periods.length < MAX_PERIOD_OPTIONS) {\r\n periods.push(cursor);\r\n const previous = fromIso(cursor.start);\r\n previous.setDate(previous.getDate() - 1);\r\n if (previous < min) break;\r\n cursor = periodOf(previous, unit);\r\n }\r\n\r\n return periods;\r\n}\r\n","// Purpose: Wrapper react-datepicker para dashboards.\n// Scope: Converte YYYY-MM-DD <-> Date, aplica estilos escopados via .ddp-field.\n// Public API: DashboardDatePicker, isoToDate, dateToIso\n\nimport DatePicker from 'react-datepicker';\nimport 'react-datepicker/dist/react-datepicker.css';\n\n// -------Helpers ISO <-> Date-------\n// Usam local-time para evitar timezone shift (toISOString() converte para UTC).\n\nexport function isoToDate(iso?: string | null): Date | null {\n if (!iso) return null;\n const [y, m, d] = iso.split('-').map(Number);\n if (!y || !m || !d) return null;\n return new Date(y, m - 1, d);\n}\n\nexport function dateToIso(date?: Date | null): string {\n if (!date) return '';\n const y = date.getFullYear();\n const m = String(date.getMonth() + 1).padStart(2, '0');\n const d = String(date.getDate()).padStart(2, '0');\n return `${y}-${m}-${d}`;\n}\n\n// -------Componente-------\n\ninterface Props {\n value: string; // 'YYYY-MM-DD' ou ''\n onChange: (iso: string) => void; // emite '' quando limpo\n minIso?: string | null;\n maxIso?: string | null;\n placeholder?: string;\n selectsStart?: boolean;\n selectsEnd?: boolean;\n startIso?: string | null;\n endIso?: string | null;\n className?: string;\n disabled?: boolean;\n}\n\nexport function DashboardDatePicker({\n value, onChange, minIso, maxIso, placeholder,\n selectsStart, selectsEnd, startIso, endIso, className, disabled,\n}: Props) {\n return (\n <div className={`ddp-field ${className ?? ''}`}>\n <DatePicker\n selected={isoToDate(value)}\n onChange={(d: Date | null) => onChange(dateToIso(d))}\n selectsStart={selectsStart}\n selectsEnd={selectsEnd}\n startDate={isoToDate(startIso) ?? undefined}\n endDate={isoToDate(endIso) ?? undefined}\n minDate={isoToDate(minIso) ?? undefined}\n maxDate={isoToDate(maxIso) ?? undefined}\n dateFormat=\"dd/MM/yyyy\"\n placeholderText={placeholder ?? 'Selecione...'}\n disabled={disabled}\n portalId=\"ddp-portal\"\n popperPlacement=\"bottom-start\"\n popperModifiers={[\n {\n name: 'flip',\n options: { fallbackPlacements: ['bottom-end', 'top-start', 'top-end'] },\n fn: (state) => state,\n },\n ]}\n />\n </div>\n );\n}\n","// Purpose: Seletor categorico com busca por digitacao (selecao unica e multipla).\r\n// Scope: Reaproveitado pelo FilterWidget (runtime) e pelo builder (valor padrao do filtro).\r\n// O proprio campo e a barra de busca (combobox): digitar filtra; a lista abre\r\n// abaixo em portal no document.body (escapa de overflow:hidden e nao rola o widget).\r\n// Formato de valor: unica = string da opcao ('' = Todos); multipla = csv das opcoes.\r\n// Public API: SearchableSelect\r\n\r\nimport { useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { MULTI_VALUE_SEPARATOR } from '../types';\r\n\r\ninterface Props {\r\n options: string[];\r\n value: string;\r\n multi: boolean;\r\n onChange: (value: string) => void;\r\n}\r\n\r\n// Posicao da lista em coordenadas de viewport (position: fixed)\r\ninterface PanelPos {\r\n left: number;\r\n width: number;\r\n top?: number;\r\n bottom?: number;\r\n maxHeight: number;\r\n}\r\n\r\nexport function SearchableSelect({ options, value, multi, onChange }: Props) {\r\n const [open, setOpen] = useState(false);\r\n const [query, setQuery] = useState('');\r\n const [pos, setPos] = useState<PanelPos | null>(null);\r\n const inputRef = useRef<HTMLInputElement>(null);\r\n const panelRef = useRef<HTMLDivElement>(null);\r\n\r\n const selected = useMemo(\r\n () => (value ? value.split(MULTI_VALUE_SEPARATOR).filter(Boolean) : []),\r\n [value],\r\n );\r\n\r\n const filtered = useMemo(() => {\r\n const q = query.trim().toLowerCase();\r\n if (!q) return options;\r\n return options.filter((opt) => opt.toLowerCase().includes(q));\r\n }, [options, query]);\r\n\r\n // Recalcula a posicao da lista a partir do retangulo do campo.\r\n // Abre para cima quando nao ha espaco suficiente abaixo.\r\n const reposition = () => {\r\n const el = inputRef.current;\r\n if (!el) return;\r\n const r = el.getBoundingClientRect();\r\n const gap = 4;\r\n const spaceBelow = window.innerHeight - r.bottom - gap;\r\n const spaceAbove = r.top - gap;\r\n const openUp = spaceBelow < 200 && spaceAbove > spaceBelow;\r\n const maxHeight = Math.max(150, Math.min(360, openUp ? spaceAbove : spaceBelow));\r\n setPos({\r\n left: r.left,\r\n width: r.width,\r\n maxHeight,\r\n ...(openUp\r\n ? { bottom: window.innerHeight - r.top + gap }\r\n : { top: r.bottom + gap }),\r\n });\r\n };\r\n\r\n useLayoutEffect(() => {\r\n if (!open) return;\r\n reposition();\r\n const handler = () => reposition();\r\n window.addEventListener('scroll', handler, true);\r\n window.addEventListener('resize', handler);\r\n return () => {\r\n window.removeEventListener('scroll', handler, true);\r\n window.removeEventListener('resize', handler);\r\n };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [open]);\r\n\r\n // Fecha ao clicar fora — checa o campo e a lista (que vive no portal)\r\n useEffect(() => {\r\n if (!open) return;\r\n const onPointerDown = (e: MouseEvent) => {\r\n const target = e.target as Node;\r\n if (inputRef.current?.contains(target) || panelRef.current?.contains(target)) return;\r\n setOpen(false);\r\n };\r\n document.addEventListener('mousedown', onPointerDown);\r\n return () => document.removeEventListener('mousedown', onPointerDown);\r\n }, [open]);\r\n\r\n const closePanel = () => {\r\n setOpen(false);\r\n setQuery('');\r\n };\r\n\r\n const commitSingle = (opt: string) => {\r\n onChange(opt);\r\n setQuery('');\r\n setOpen(false);\r\n inputRef.current?.blur();\r\n };\r\n\r\n const toggleMulti = (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 const handleFocus = () => {\r\n setOpen(true);\r\n // Selecao unica: limpa para digitar; o valor atual volta a aparecer ao fechar\r\n if (!multi) setQuery('');\r\n };\r\n\r\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\r\n if (e.key === 'Escape') {\r\n closePanel();\r\n inputRef.current?.blur();\r\n } else if (e.key === 'Enter' && filtered.length > 0) {\r\n e.preventDefault();\r\n if (multi) {\r\n toggleMulti(filtered[0]);\r\n setQuery('');\r\n } else {\r\n commitSingle(filtered[0]);\r\n }\r\n }\r\n };\r\n\r\n // Texto do campo: multi sempre mostra a busca; unica mostra o valor quando fechado.\r\n const inputValue = multi ? query : (open ? query : (value || ''));\r\n // Multi vazio = todos (sem filtro). Fechado mostra o estado; aberto convida a buscar.\r\n const placeholder = multi\r\n ? (selected.length > 0 ? `${selected.length} selecionado(s)` : (open ? 'Buscar...' : 'Todos'))\r\n : (open ? 'Buscar...' : 'Todos');\r\n\r\n const panel = open && pos ? createPortal(\r\n <div\r\n ref={panelRef}\r\n className=\"widget-filter__search-panel\"\r\n style={{\r\n position: 'fixed',\r\n left: pos.left,\r\n width: pos.width,\r\n top: pos.top,\r\n bottom: pos.bottom,\r\n maxHeight: pos.maxHeight,\r\n }}\r\n >\r\n <div className=\"widget-filter__search-list\">\r\n {/* Selecao multipla: limpar toda a selecao (vazio = todos) */}\r\n {multi && selected.length > 0 && (\r\n <button\r\n type=\"button\"\r\n className=\"widget-filter__search-clear\"\r\n onClick={() => onChange('')}\r\n >\r\n Limpar seleção\r\n </button>\r\n )}\r\n\r\n {/* Selecao unica: opcao explicita para limpar o filtro */}\r\n {!multi && (\r\n <button\r\n type=\"button\"\r\n className={`widget-filter__search-option${value ? '' : ' is-selected'}`}\r\n onClick={() => commitSingle('')}\r\n >\r\n <span className=\"widget-filter__search-check\" aria-hidden>{value ? '' : '✓'}</span>\r\n Todos\r\n </button>\r\n )}\r\n\r\n {filtered.length === 0 ? (\r\n <span className=\"widget-filter__search-empty\">Nenhuma opção</span>\r\n ) : (\r\n filtered.map((opt) =>\r\n multi ? (\r\n <label\r\n key={opt}\r\n className={`widget-filter__search-option${selected.includes(opt) ? ' is-selected' : ''}`}\r\n >\r\n <input\r\n type=\"checkbox\"\r\n checked={selected.includes(opt)}\r\n onChange={() => toggleMulti(opt)}\r\n />\r\n {opt}\r\n </label>\r\n ) : (\r\n <button\r\n key={opt}\r\n type=\"button\"\r\n className={`widget-filter__search-option${value === opt ? ' is-selected' : ''}`}\r\n onClick={() => commitSingle(opt)}\r\n >\r\n <span className=\"widget-filter__search-check\" aria-hidden>{value === opt ? '✓' : ''}</span>\r\n {opt}\r\n </button>\r\n ),\r\n )\r\n )}\r\n </div>\r\n </div>,\r\n document.body,\r\n ) : null;\r\n\r\n return (\r\n <div className=\"widget-filter__search\">\r\n <input\r\n ref={inputRef}\r\n type=\"text\"\r\n className=\"widget-filter__search-field\"\r\n value={inputValue}\r\n placeholder={placeholder}\r\n onFocus={handleFocus}\r\n onClick={() => setOpen(true)}\r\n onChange={(e) => { setQuery(e.target.value); setOpen(true); }}\r\n onKeyDown={handleKeyDown}\r\n />\r\n {panel}\r\n </div>\r\n );\r\n}\r\n","// Purpose: Seletor de paleta de cores (13 slots semanticos).\n// Scope: Presets pre-definidos + modo customizado com color pickers nomeados por slot.\n// Public API: ColorPaletteSelector\n\nimport {\n PALETTES, ensurePaletteShape, getSeries, SLOT_INDEX, SLOT_LABELS, TOTAL_SLOTS,\n type PaletteKey,\n} from '../palettes';\n\n// Slots de tema usados para a segunda barra de preview do preset\nconst THEME_PREVIEW_SLOTS = [\n SLOT_INDEX.bgDark,\n SLOT_INDEX.bgPaper,\n SLOT_INDEX.bgElevated,\n SLOT_INDEX.accent,\n SLOT_INDEX.success,\n];\n\ninterface Props {\n selected?: string[];\n onSelect: (colors: string[]) => void;\n customMode?: boolean;\n onCustomModeChange?: (custom: boolean) => void;\n disabled?: boolean;\n}\n\nfunction isPreset(colors?: string[]): boolean {\n if (!colors) return true;\n const normalized = ensurePaletteShape(colors);\n return Object.values(PALETTES).some(\n (p) => JSON.stringify(p.colors) === JSON.stringify(normalized)\n );\n}\n\n// Slots agrupados por categoria para a UI customizada\nconst SLOT_ROWS: { label: string; slots: (keyof typeof SLOT_INDEX)[] }[] = [\n { label: 'Series', slots: ['series0', 'series1', 'series2', 'series3', 'series4'] },\n { label: 'Tema', slots: ['bgDark', 'bgPaper', 'bgElevated', 'textPrimary', 'textMuted'] },\n { label: 'Estados', slots: ['accent', 'success', 'error'] },\n];\n\nexport function ColorPaletteSelector({\n selected, onSelect, customMode, onCustomModeChange, disabled,\n}: Props) {\n const isCustom = customMode ?? !isPreset(selected);\n const colors = ensurePaletteShape(selected);\n\n const selectedKey = !isCustom\n ? (Object.entries(PALETTES).find(\n ([, p]) => JSON.stringify(p.colors) === JSON.stringify(colors)\n )?.[0] as PaletteKey | undefined)\n : undefined;\n\n const handleSlotChange = (slotIdx: number, color: string) => {\n const updated = [...colors];\n while (updated.length < TOTAL_SLOTS) updated.push('#000000');\n updated[slotIdx] = color;\n onSelect(updated);\n };\n\n return (\n <div className={`palette-selector ${disabled ? 'palette-selector--disabled' : ''}`}>\n {onCustomModeChange && (\n <label className=\"config-panel__checkbox\">\n <input\n type=\"checkbox\"\n checked={isCustom}\n onChange={(e) => onCustomModeChange(e.target.checked)}\n disabled={disabled}\n />\n Customizar\n </label>\n )}\n\n {isCustom ? (\n <div className=\"palette-selector__custom\">\n {SLOT_ROWS.map((row) => (\n <div key={row.label} className=\"palette-selector__row\">\n <span className=\"palette-selector__row-label\">{row.label}</span>\n <div className=\"palette-selector__row-slots\">\n {row.slots.map((slotName) => {\n const slotIdx = SLOT_INDEX[slotName];\n return (\n <input\n key={slotName}\n type=\"color\"\n className=\"palette-selector__color-input\"\n value={colors[slotIdx] || '#000000'}\n onChange={(e) => handleSlotChange(slotIdx, e.target.value)}\n disabled={disabled}\n title={SLOT_LABELS[slotName]}\n />\n );\n })}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className=\"palette-selector__options\">\n {(Object.entries(PALETTES) as [PaletteKey, typeof PALETTES[PaletteKey]][]).map(([key, palette]) => {\n const fullColors = ensurePaletteShape(palette.colors);\n return (\n <button\n key={key}\n className={`palette-selector__option ${selectedKey === key ? 'palette-selector__option--active' : ''}`}\n onClick={() => onSelect(palette.colors)}\n disabled={disabled}\n >\n <div className=\"palette-selector__bar\">\n {getSeries(palette.colors).map((color, i) => (\n <span\n key={i}\n className=\"palette-selector__swatch\"\n style={{ backgroundColor: color }}\n />\n ))}\n </div>\n <div className=\"palette-selector__bar palette-selector__bar--theme\">\n {THEME_PREVIEW_SLOTS.map((slotIdx, i) => (\n <span\n key={i}\n className=\"palette-selector__swatch\"\n style={{ backgroundColor: fullColors[slotIdx] }}\n />\n ))}\n </div>\n <span className=\"palette-selector__label\">{palette.label}</span>\n </button>\n );\n })}\n </div>\n )}\n </div>\n );\n}\n"],"names":["DEFAULT_API_URL","DASHBOARDS_PREFIX","STATEMENTS_PREFIX","apiUrl","setApiUrl","url","ApiError","message","status","payload","request","prefix","path","token","params","k","v","res","get","fetchLayout","fetchRender","fetchStatementLayout","fetchStatementRender","fetchStatementPdf","SLOT_INDEX","SERIES_COUNT","TOTAL_SLOTS","SLOT_LABELS","PALETTES","DEFAULT_PALETTE_COLORS","ensurePaletteShape","colors","fallback","result","i","getSeries","getPaletteCssVars","c","DEFAULT_PALETTE","DEFAULT_GRID_COLUMNS","DEFAULT_GRID_ROWS","EMPTY_LAYOUT","WIDGET_TYPE_LABELS","DATA_WIDGET_TYPES","CONTROL_WIDGET_TYPES","CONTROL_WIDGET_SET","TIME_OFFSET_UNIT_LABELS","TIME_OFFSET_WINDOW_LABEL","AGGREGATION_LABELS","FORMAT_LABELS","NUMERIC_FORMAT_OPTIONS","COMPARISON_DISPLAY_LABELS","TABLE_OVERFLOW_LABELS","GOOD_WHEN_LABELS","FILTER_OPERATOR_LABELS","VALUELESS_FILTER_OPERATORS","LIST_FILTER_OPERATORS","CHART_TYPE_LABELS","COMPOSITION_DISPLAY_LABELS","BRIDGE_DIRECTION_LABELS","FILTER_TYPE_LABELS","MULTI_VALUE_SEPARATOR","DEFAULT_GRID","DEFAULT_CONFIG","GRID_GAP_PX","GRID_PADDING_PX","CELL_ASPECT","MIN_CELL_HEIGHT_PX","MAX_CELL_HEIGHT_PX","clamp","value","min","max","isUsable","computeCellWidth","outerWidth","columns","gap","padding","available","computeCellHeight","cellWidth","aspect","computeGridHeight","rows","cellHeight","computeWidgetAspect","w","h","computeStackThreshold","LOCALE","PERCENTAGE_SCALE","NUMERIC_FORMATS","isNumericFormat","format","toNumber","n","formatValue","formatCompact","abs","MONTH_NAMES_SHORT","MONTH_NAMES_FULL","getFullYearRange","year","parseYearFromRange","start","m","getMonthRange","month","lastDay","pad","getISOWeek","dt","d","yearStart","getWeekRange","week","jan4","dayOfWeek","firstMonday","end","fmt","getWeeksInMonth","weeks","daysInMonth","a","b","getMonthWeeks","day","index","startDay","endDay","label","parseMonthWeekFromRange","dayMatch","parseMonthFromRange","parseWeekFromRange","getYearRange","dateBounds","now","minYear","maxYear","years","y","pad2","isoOf","fromIso","iso","periodOf","unit","range","monday","sunday","MAX_PERIOD_OPTIONS","rangePeriods","periods","cursor","previous","isoToDate","dateToIso","date","DashboardDatePicker","onChange","minIso","maxIso","placeholder","selectsStart","selectsEnd","startIso","endIso","className","disabled","jsx","DatePicker","state","SearchableSelect","options","multi","open","setOpen","useState","query","setQuery","pos","setPos","inputRef","useRef","panelRef","selected","useMemo","filtered","q","opt","reposition","el","r","spaceBelow","spaceAbove","openUp","maxHeight","useLayoutEffect","handler","useEffect","onPointerDown","e","target","_a","_b","closePanel","commitSingle","toggleMulti","next","s","handleFocus","handleKeyDown","inputValue","panel","createPortal","jsxs","THEME_PREVIEW_SLOTS","isPreset","normalized","p","SLOT_ROWS","ColorPaletteSelector","onSelect","customMode","onCustomModeChange","isCustom","selectedKey","handleSlotChange","slotIdx","color","updated","row","slotName","key","palette","fullColors"],"mappings":"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"}