@bluemarble/bi 0.0.0-stage → 0.1.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.
@@ -0,0 +1,410 @@
1
+ import { F as ModelMeta, N as MeasureMeta, P as ModelDef, _ as ChartDef, a as DashboardResult, i as DashboardQueryDebug, l as FilterValue, n as DashboardFilters$1, o as DashboardRow, r as DashboardQuery, y as ChartsLayout } from "../types-CB4sK4jP.js";
2
+ import { ComponentType, ReactNode } from "react";
3
+ //#region src/client/BarChart.d.ts
4
+ type BarChartProps = {
5
+ /** Dimensão das categorias. */
6
+ dimension: string;
7
+ /** Uma série por medida (cores fixas pela posição). */
8
+ measures: string[];
9
+ /** `horizontal` cabe nomes longos; com muitas categorias, rola dentro da altura. */
10
+ orientation?: 'vertical' | 'horizontal';
11
+ /** Empilha as séries (só faz sentido com partes de um total). */
12
+ stacked?: boolean;
13
+ /** `dimension` = ordem da consulta; `desc`/`asc` = pela primeira medida. */
14
+ sort?: 'dimension' | 'desc' | 'asc';
15
+ /** Só os N primeiros depois de ordenar. */
16
+ limit?: number;
17
+ formatDimension?: (value: FilterValue) => string;
18
+ /** Esconde categorias sem valor em nenhuma medida. */
19
+ hideEmpty?: boolean;
20
+ /** Valores nas pontas das barras (até 30 categorias; acima disso, só tooltip). */
21
+ showValues?: boolean;
22
+ clickToFilter?: boolean;
23
+ height?: number;
24
+ /** Nome da consulta no devtools. */
25
+ queryLabel?: string;
26
+ };
27
+ /**
28
+ * Barras de uma ou mais medidas por uma dimensão. Ex.:
29
+ * `<BarChart dimension="navio" measures={['custoTotal']} orientation="horizontal" sort="desc" limit={10} />`.
30
+ */
31
+ declare function BarChart({ dimension, measures, orientation, stacked, sort, limit, formatDimension, hideEmpty, showValues, clickToFilter, height, queryLabel }: BarChartProps): import("react").JSX.Element;
32
+ //#endregion
33
+ //#region src/client/ComboChart.d.ts
34
+ type ComboChartProps = {
35
+ /** Dimensão do eixo X. */
36
+ dimension: string;
37
+ /** Medida das barras. */
38
+ bar: string;
39
+ /** Medida da linha (eixo próprio, oculto; os valores aparecem nos pontos). */
40
+ line: string;
41
+ /** Medida extra mostrada como segunda linha do rótulo da barra (ex.: volume). */
42
+ detail?: string;
43
+ /** Rótulos e formatos: sem a prop, vale o dicionário do modelo (`label`, `format`). */
44
+ barLabel?: string;
45
+ lineLabel?: string;
46
+ detailLabel?: string;
47
+ formatDimension?: (value: FilterValue) => string;
48
+ formatBar?: (value: number) => string;
49
+ formatLine?: (value: number) => string;
50
+ formatDetail?: (value: number) => string;
51
+ /** Esconde grupos cuja medida da barra é vazia/zero (como o Power BI faz). */
52
+ hideEmpty?: boolean;
53
+ height?: number;
54
+ /** Rótulos de dados só até essa quantidade de barras (acima disso, só tooltip). */
55
+ maxLabels?: number;
56
+ barColor?: string;
57
+ lineColor?: string;
58
+ /**
59
+ * Clicar numa barra filtra o dashboard pelo valor dela (Ctrl/Cmd+clique acumula; clicar de novo
60
+ * no único selecionado ou fora das barras limpa). O próprio gráfico ignora esse filtro e só
61
+ * destaca a seleção, como o filtro cruzado do Power BI.
62
+ */
63
+ clickToFilter?: boolean;
64
+ /** Nome da consulta no devtools (padrão: `ComboChart · <dimensão>`). */
65
+ queryLabel?: string;
66
+ };
67
+ /**
68
+ * Barras + linha de uma dimensão, consultando o modelo do `DashboardProvider` (com os filtros dele).
69
+ * Ex.: `<ComboChart dimension="mes" bar="custoTotal" line="custoTon" detail="volTotal" />`.
70
+ */
71
+ declare function ComboChart({ dimension, bar, line, detail, barLabel, lineLabel, detailLabel, formatDimension, formatBar, formatLine, formatDetail, hideEmpty, height, maxLabels, barColor, lineColor, clickToFilter, queryLabel }: ComboChartProps): import("react").JSX.Element;
72
+ //#endregion
73
+ //#region src/client/chartKit.d.ts
74
+ /**
75
+ * Peças comuns dos gráficos ligados ao modelo: paleta, filtro por clique, legenda e os estados de
76
+ * carregando/erro/vazio.
77
+ */
78
+ /**
79
+ * Paleta categórica, sempre nesta ordem (a série N tem sempre a mesma cor). Laranja Rocha primeiro;
80
+ * a ordem passa no validador de daltonismo (CVD ΔE ≥ 9 entre vizinhas) e de visão normal (≥ 19).
81
+ */
82
+ declare const SERIES_COLORS: readonly ['#F58220', '#2a78d6', '#1baf7a', '#eda100', '#e87ba4', '#008300', '#6250d6', '#e34948'];
83
+ /** "Outros" (fatias agrupadas) fica neutro, fora da paleta. */
84
+ declare const OTHER_COLOR = "#9e9e9e";
85
+ //#endregion
86
+ //#region src/client/DashboardCanvas.d.ts
87
+ type DashboardCanvasProps = {
88
+ /** O mesmo layout do `<DashboardCharts>` (`canvas` do JSON). */
89
+ layout: ChartsLayout;
90
+ children: ReactNode;
91
+ };
92
+ /**
93
+ * Tela de tamanho fixo (`layout.canvas`, ex.: 1920×1080): desenha os filhos nessa largura e escala
94
+ * tudo para caber na largura disponível, mantendo a proporção — numa tela menor o dashboard encolhe
95
+ * em vez de reorganizar os gráficos. Sem `canvas` no layout, só renderiza os filhos (responsivo).
96
+ *
97
+ * ```tsx
98
+ * <DashboardCanvas layout={layout}>
99
+ * <DashboardFilters layout={layout} />
100
+ * <DashboardCharts layout={layout} />
101
+ * </DashboardCanvas>
102
+ * ```
103
+ *
104
+ * A escala é um `transform`: os gráficos continuam medindo o tamanho de projeto (o Recharts compensa
105
+ * a escala no mouse) e os breakpoints do MUI, que olham a janela, ficam desligados no grid.
106
+ */
107
+ declare function DashboardCanvas({ layout, children }: DashboardCanvasProps): import("react").JSX.Element;
108
+ //#endregion
109
+ //#region src/client/DashboardCharts.d.ts
110
+ type ChartPanelProps = {
111
+ title: string;
112
+ chart: ChartDef;
113
+ children: ReactNode;
114
+ };
115
+ type DashboardChartsProps = {
116
+ /** Layout importado do JSON (`src/dashboard/layouts/<id>.json`). */
117
+ layout: ChartsLayout;
118
+ /** Formatters por nome, referenciados no JSON por `formatDimension`. */
119
+ formatters?: Record<string, (value: FilterValue) => string>;
120
+ /** Moldura de cada gráfico (título + conteúdo). */
121
+ panel?: ComponentType<ChartPanelProps>;
122
+ gap?: number;
123
+ };
124
+ /**
125
+ * Renderiza os gráficos de um layout declarativo num grid de 12 colunas (no celular, um por linha;
126
+ * dentro de um `<DashboardCanvas>` de tamanho fixo, sempre as 12). Em desenvolvimento, a aba
127
+ * Layout do devtools edita esse layout ao vivo (rascunho) e grava o JSON de volta.
128
+ *
129
+ * ```tsx
130
+ * import layout from '@/dashboard/layouts/analiseCusto.json'
131
+ * <DashboardCharts layout={layout as ChartsLayout} formatters={{ nomeMes }} panel={Panel} />
132
+ * ```
133
+ */
134
+ declare function DashboardCharts({ layout, formatters, panel: Panel, gap }: DashboardChartsProps): import("react").JSX.Element;
135
+ //#endregion
136
+ //#region src/client/DashboardFilters.d.ts
137
+ type DashboardFiltersProps = {
138
+ /** O mesmo layout do `<DashboardCharts>` (`filters` do JSON). */
139
+ layout: ChartsLayout;
140
+ /** Formatters por nome, referenciados no JSON por `formatLabel`. */
141
+ formatters?: Record<string, (value: FilterValue) => string>;
142
+ gap?: number;
143
+ };
144
+ /**
145
+ * Filtros (slicers) declarados em `layout.filters`, na ordem. Em desenvolvimento, a aba Layout do
146
+ * devtools adiciona, remove, reordena e edita os filtros ao vivo.
147
+ */
148
+ declare function DashboardFilters({ layout, formatters, gap }: DashboardFiltersProps): import("react").JSX.Element;
149
+ //#endregion
150
+ //#region src/devtools/layoutStore.d.ts
151
+ /**
152
+ * Layouts montados na página (`<DashboardCharts>` / `<DashboardFilters>`) e o rascunho de cada um,
153
+ * editado na aba Layout do devtools. Store externo como o de consultas: editar um gráfico
154
+ * re-renderiza só os componentes daquele layout e o painel.
155
+ */
156
+ /** Parte do layout que um componente renderiza. */
157
+ type LayoutPart = 'charts' | 'filters' | 'canvas';
158
+ type LayoutEntry = {
159
+ /** O layout que veio do arquivo (o que a página passou ao `<DashboardCharts>`). */
160
+ registered: ChartsLayout;
161
+ /** Rascunho editado no devtools; `null` = página usando o registrado. */
162
+ draft: ChartsLayout | null;
163
+ /**
164
+ * Partes montadas na página e os formatters que cada uma recebeu (`formatDimension`,
165
+ * `formatLabel`). Parte ausente = a página não renderiza (ex.: sem `<DashboardFilters>`).
166
+ */
167
+ parts: Partial<Record<LayoutPart, string[]>>;
168
+ };
169
+ declare function createLayoutStore(): {
170
+ subscribe(listener: () => void): () => boolean;
171
+ getSnapshot: () => LayoutEntry[];
172
+ get: (id: string) => LayoutEntry | null;
173
+ /** Rascunho do layout, mesmo antes de registrar (evita renderizar o registrado e trocar). */
174
+ draftOf(layout: ChartsLayout): ChartsLayout | null;
175
+ /** Chamado pelo `<DashboardCharts>`/`<DashboardFilters>` ao montar e quando o arquivo muda (HMR). */
176
+ register(layout: ChartsLayout, part: LayoutPart, formatters: string[]): () => void;
177
+ setDraft: (id: string, next: ChartsLayout | null) => void;
178
+ };
179
+ type LayoutStore = ReturnType<typeof createLayoutStore>;
180
+ //#endregion
181
+ //#region src/devtools/store.d.ts
182
+ /**
183
+ * Registro das consultas feitas pelos componentes (`useModelQuery`), lido pelo painel do devtools.
184
+ * É um store externo (`useSyncExternalStore`) para que registrar uma consulta não re-renderize a
185
+ * página inteira — só o painel.
186
+ */
187
+ type RunStatus = 'loading' | 'success' | 'error' | 'cancelled';
188
+ type QueryRun = {
189
+ runId: number;
190
+ instanceId: string;
191
+ label: string;
192
+ query: DashboardQuery;
193
+ status: RunStatus;
194
+ startedAt: number;
195
+ /** Ida e volta medida no browser. */
196
+ durationMs?: number;
197
+ rows?: DashboardRow[];
198
+ error?: string;
199
+ debug?: DashboardQueryDebug;
200
+ };
201
+ type TrackedInstance = {
202
+ instanceId: string;
203
+ label: string;
204
+ runs: number;
205
+ last: QueryRun;
206
+ /** Refeita muitas vezes em pouco tempo: sinal de re-render em loop (ex.: array novo a cada render). */
207
+ storm: boolean;
208
+ };
209
+ type DevtoolsSnapshot = {
210
+ instances: TrackedInstance[];
211
+ /** Execuções mais recentes primeiro. */
212
+ history: QueryRun[];
213
+ };
214
+ declare function createDevtoolsStore(): {
215
+ subscribe(listener: () => void): () => boolean;
216
+ getSnapshot: () => DevtoolsSnapshot;
217
+ start(instanceId: string, label: string, query: DashboardQuery): number;
218
+ succeed: (runId: number, rows: DashboardRow[], debug?: DashboardQueryDebug) => void;
219
+ fail: (runId: number, error: unknown) => void;
220
+ /** Consulta descartada antes de responder (filtro mudou, componente desmontou). */
221
+ cancel: (runId: number) => void;
222
+ remove(instanceId: string): void;
223
+ /** Avisa que todas as consultas vão refazer agora, de propósito. */
224
+ expectRefetch(): void;
225
+ /** Zera os alertas de loop (depois de corrigir o componente, sem recarregar a página). */
226
+ resetStorms(): void;
227
+ clearHistory(): void;
228
+ };
229
+ type DevtoolsStore = ReturnType<typeof createDevtoolsStore>;
230
+ //#endregion
231
+ //#region src/client/DashboardProvider.d.ts
232
+ type DashboardFetcher = (query: DashboardQuery) => Promise<DashboardResult>;
233
+ /** Só existe com o devtools ligado. */
234
+ type DashboardDevtoolsContext = {
235
+ store: DevtoolsStore;
236
+ /** Layouts da página (`<DashboardCharts>`/`<DashboardFilters>`) e os rascunhos da aba Layout. */
237
+ layouts: LayoutStore;
238
+ /** Consulta o modelo registrado, ignorando o rascunho (comparações, snapshots). */
239
+ rawFetcher: DashboardFetcher;
240
+ /** Rascunho do modelo aplicado: todas as consultas da página passam a usá-lo. */
241
+ draft: ModelDef | null;
242
+ setDraft: (draft: ModelDef | null) => void;
243
+ /** Refaz todas as consultas da página. */
244
+ refresh: () => void;
245
+ defaultFilters: DashboardFilters$1;
246
+ setFilters: (filters: DashboardFilters$1) => void;
247
+ };
248
+ type DashboardContextValue = {
249
+ model: string;
250
+ filters: DashboardFilters$1;
251
+ setFilter: (dimension: string, values: FilterValue[]) => void;
252
+ fetcher: DashboardFetcher;
253
+ /** Dicionário do modelo (rótulos, descrições, formatos); `null` até carregar. */
254
+ meta: ModelMeta | null;
255
+ /** Muda quando o devtools pede para refazer as consultas. */
256
+ refreshKey: number;
257
+ devtools: DashboardDevtoolsContext | null;
258
+ };
259
+ type DashboardProviderProps = {
260
+ /** Nome do modelo no servidor (chave do registro de modelos do app). */
261
+ model: string;
262
+ /** Como chamar o endpoint do app (ex.: `(q) => api.post('/dashboard/query', q).then((r) => r.data)`). */
263
+ fetcher: DashboardFetcher;
264
+ defaultFilters?: DashboardFilters$1;
265
+ /**
266
+ * Painel de desenvolvimento (debug das consultas, edição do modelo). Padrão: ligado só com
267
+ * `NODE_ENV=development`. O endpoint também precisa de `runQuery(..., { devtools: true })`.
268
+ */
269
+ devtools?: boolean;
270
+ children: ReactNode;
271
+ };
272
+ /**
273
+ * Guarda os filtros do dashboard. Todo componente dentro dele (filtros, gráficos, tabelas) consulta o
274
+ * mesmo modelo com os mesmos filtros — é o que faz um slicer filtrar a página inteira, como no BI.
275
+ */
276
+ declare function DashboardProvider({ model, fetcher, defaultFilters, devtools, children }: DashboardProviderProps): import("react").JSX.Element;
277
+ declare function useDashboard(): DashboardContextValue;
278
+ //#endregion
279
+ //#region src/client/DataTable.d.ts
280
+ type SortDirection = 'asc' | 'desc';
281
+ type DataTableProps = {
282
+ /** Uma linha por combinação de dimensões (sem dimensões, uma linha só). */
283
+ dimensions?: string[];
284
+ /** Uma coluna por medida, formatada pelo dicionário do modelo. */
285
+ measures: string[];
286
+ /** Formatter por dimensão. */
287
+ formatDimensions?: Record<string, (value: FilterValue) => string>;
288
+ /**
289
+ * Linha de total, consultada sem as dimensões: razões (custo/t) saem do total, não da soma das
290
+ * linhas.
291
+ */
292
+ showTotal?: boolean;
293
+ /** Coluna da ordem inicial (dimensão ou medida); quem usa reordena clicando no cabeçalho. */
294
+ sortBy?: string;
295
+ sortDirection?: SortDirection;
296
+ /** Clicar numa linha filtra o dashboard pela primeira dimensão. */
297
+ clickToFilter?: boolean;
298
+ /** Altura máxima; a tabela rola com o cabeçalho fixo. */
299
+ height?: number;
300
+ /** Nome da consulta no devtools. */
301
+ queryLabel?: string;
302
+ };
303
+ /**
304
+ * Tabela de medidas por dimensões, com total e ordenação pelo cabeçalho. Ex.:
305
+ * `<DataTable dimensions={['navio']} measures={['volTotal', 'custoTotal', 'custoTon']} />`.
306
+ */
307
+ declare function DataTable({ dimensions, measures, formatDimensions, showTotal, sortBy, sortDirection, clickToFilter, height, queryLabel }: DataTableProps): import("react").JSX.Element;
308
+ //#endregion
309
+ //#region src/client/DonutChart.d.ts
310
+ type DonutChartProps = {
311
+ /** Dimensão das fatias. */
312
+ dimension: string;
313
+ /** Medida somável (partes de um total). Valores negativos ou zerados ficam de fora. */
314
+ measure: string;
315
+ /** Fatias além dessa quantidade viram "Outros" (no máximo 8, o tamanho da paleta). */
316
+ maxSlices?: number;
317
+ formatDimension?: (value: FilterValue) => string;
318
+ clickToFilter?: boolean;
319
+ height?: number;
320
+ /** Nome da consulta no devtools. */
321
+ queryLabel?: string;
322
+ };
323
+ /**
324
+ * Rosca de uma medida por uma dimensão, com o total no centro e a legenda ao lado (nome, % e valor).
325
+ * Ex.: `<DonutChart dimension="operacao_status" measure="custoTotal" />`.
326
+ */
327
+ declare function DonutChart({ dimension, measure, maxSlices, formatDimension, clickToFilter, height, queryLabel }: DonutChartProps): import("react").JSX.Element;
328
+ //#endregion
329
+ //#region src/client/FilterSelect.d.ts
330
+ type FilterSelectProps = {
331
+ dimension: string;
332
+ /** Padrão: `label` da dimensão no dicionário do modelo. */
333
+ label?: string;
334
+ formatLabel?: (value: FilterValue) => string;
335
+ width?: number;
336
+ };
337
+ /**
338
+ * Filtro de múltipla escolha de uma dimensão. As opções vêm do próprio modelo e respeitam os
339
+ * DEMAIS filtros (filtro cruzado): com Mês = Janeiro, o filtro de navio só lista quem atracou em
340
+ * janeiro. Nada selecionado = "Todos".
341
+ */
342
+ declare function FilterSelect({ dimension, label, formatLabel, width }: FilterSelectProps): import("react").JSX.Element;
343
+ //#endregion
344
+ //#region src/client/format.d.ts
345
+ declare function formatNumber(value: number | string | null | undefined, decimals?: number): string;
346
+ declare const formatCurrency: (value: number | string | null | undefined, decimals?: number) => string;
347
+ /**
348
+ * Formata pelo dicionário do modelo (`format`/`decimals` da medida). `fallbackDecimals` é o padrão
349
+ * do componente quando a medida não define `decimals`.
350
+ */
351
+ declare function formatMeasure(value: number | string | null | undefined, meta: MeasureMeta | undefined, fallbackDecimals?: number): string;
352
+ /** Formatter de uma medida pelo dicionário do modelo; sem `format`, número com `fallbackDecimals`. */
353
+ declare function measureFormatter(meta: ModelMeta | null, measure: string, fallbackDecimals?: number): (value: number | string | null | undefined) => string;
354
+ //#endregion
355
+ //#region src/client/KpiCard.d.ts
356
+ type KpiCardProps = {
357
+ /** Medida do número grande: o total com os filtros da página. */
358
+ measure: string;
359
+ /** Rótulo acima do número (no `<DashboardCharts>`, o título do painel faz esse papel). */
360
+ label?: string;
361
+ /** Medida extra numa linha menor embaixo (ex.: volume, custo/t). */
362
+ secondary?: string;
363
+ /** Padrão: `label` da medida secundária no dicionário. */
364
+ secondaryLabel?: string;
365
+ /** Nome da consulta no devtools. */
366
+ queryLabel?: string;
367
+ };
368
+ /**
369
+ * Card com o total de uma medida (e, opcionalmente, uma segunda medida embaixo). Uma consulta sem
370
+ * dimensões: razões (custo/t) saem do total, não de uma média. Ex.:
371
+ * `<KpiCard label="Custo total" measure="custoTotal" secondary="custoTon" />`.
372
+ */
373
+ declare function KpiCard({ measure, label, secondary, secondaryLabel, queryLabel }: KpiCardProps): import("react").JSX.Element;
374
+ //#endregion
375
+ //#region src/client/ModelDictionary.d.ts
376
+ /**
377
+ * Dicionário do modelo do `DashboardProvider`: o que cada filtro/eixo e cada número significa. É
378
+ * montado a partir de `label`/`description` das dimensões e medidas — documentação que não
379
+ * desatualiza, porque é a mesma definição que calcula os números.
380
+ */
381
+ declare function ModelDictionary(): import("react").JSX.Element | null;
382
+ //#endregion
383
+ //#region src/client/useModelQuery.d.ts
384
+ declare const INSPECT_ATTRIBUTE = "data-bm-dashboard-query";
385
+ type UseModelQueryParams = {
386
+ dimensions?: string[];
387
+ measures?: string[];
388
+ /**
389
+ * Filtros do dashboard que esta consulta NÃO deve respeitar. Um filtro ignora a si mesmo para
390
+ * listar as opções (senão, ao escolher um navio, a lista mostraria só ele).
391
+ */
392
+ ignoreFilters?: string[];
393
+ /** Nome da consulta no devtools (padrão: dimensões × medidas). */
394
+ label?: string;
395
+ /** Não consulta (devolve `rows: []`); ex.: a linha de total de uma tabela que não mostra total. */
396
+ skip?: boolean;
397
+ };
398
+ declare function useModelQuery({ dimensions, measures, ignoreFilters, label, skip }: UseModelQueryParams): {
399
+ rows: DashboardRow[];
400
+ isLoading: boolean;
401
+ error: unknown;
402
+ inspectProps: {
403
+ "data-bm-dashboard-query": string;
404
+ } | {
405
+ "data-bm-dashboard-query"?: undefined;
406
+ };
407
+ };
408
+ //#endregion
409
+ export { BarChart, type ChartPanelProps, ComboChart, DashboardCanvas, DashboardCharts, type DashboardFetcher, DashboardFilters, DashboardProvider, DataTable, DonutChart, FilterSelect, INSPECT_ATTRIBUTE, KpiCard, ModelDictionary, OTHER_COLOR, SERIES_COLORS, formatCurrency, formatMeasure, formatNumber, measureFormatter, useDashboard, useModelQuery };
410
+ //# sourceMappingURL=index.d.ts.map