@bluemarble/bi 0.7.0 → 0.8.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/README.md +77 -77
- package/dist/{DashboardDevtools-D0pzwSgn.js → DashboardDevtools-TFwjFdqn.js} +1437 -565
- package/dist/DashboardDevtools-TFwjFdqn.js.map +1 -0
- package/dist/{ModelDictionary-Cw4sa8tW.js → ModelDictionary-g5d84D0n.js} +67 -5
- package/dist/ModelDictionary-g5d84D0n.js.map +1 -0
- package/dist/cli.js +0 -0
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +48 -9
- package/dist/client/index.js +186 -45
- package/dist/client/index.js.map +1 -1
- package/dist/codegen-LoQzFAle.js.map +1 -1
- package/dist/compare-DloZhg1T.js.map +1 -1
- package/dist/{formatRules-DxA9vMvz.d.ts → formatRules-C1PW2EiL.d.ts} +74 -2
- package/dist/{layout-BS3nO6OT.js → layout-BuZhfoRI.js} +167 -15
- package/dist/layout-BuZhfoRI.js.map +1 -0
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +17 -1
- package/dist/server/index.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/package.json +81 -81
- package/dist/DashboardDevtools-D0pzwSgn.js.map +0 -1
- package/dist/ModelDictionary-Cw4sa8tW.js.map +0 -1
- package/dist/layout-BS3nO6OT.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DashboardDevtools-TFwjFdqn.js","names":["KEYWORDS","inputSx","MIN_HEIGHT","ToggleButton"],"sources":["../src/devtools/autoApply.ts","../src/devtools/sqlHighlight.tsx","../src/devtools/ui.tsx","../src/devtools/FiltersPanel.tsx","../src/devtools/DevtoolsWindow.tsx","../src/devtools/Inspector.tsx","../src/devtools/lineDiff.ts","../src/devtools/LayoutPanel.tsx","../src/devtools/modelCode.ts","../src/devtools/QueryBuilder.tsx","../src/devtools/queryTemplateDefs.ts","../src/devtools/QueryTemplates.tsx","../src/devtools/SqlEditor.tsx","../src/devtools/modelFields.tsx","../src/devtools/DimensionPicker.tsx","../src/devtools/ModelDiagram.tsx","../src/devtools/ModelPanel.tsx","../src/devtools/PlaygroundPanel.tsx","../src/devtools/QueriesPanel.tsx","../src/devtools/RegressionPanel.tsx","../src/devtools/DashboardDevtools.tsx"],"sourcesContent":["import { useSyncExternalStore } from 'react'\r\n\r\n/**\r\n * Preferência \"Aplicar automaticamente\" dos editores (Layout e Modelo): ligada, cada edição válida\r\n * vai para a página sozinha, como se clicasse em \"Aplicar na página\". Uma só para os dois editores,\r\n * guardada no navegador.\r\n */\r\n\r\nconst KEY = 'bm-dashboard-devtools:auto-apply'\r\nconst listeners = new Set<() => void>()\r\n\r\nfunction read() {\r\n try {\r\n return localStorage.getItem(KEY) === '1'\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nlet enabled = read()\r\n\r\nexport function setAutoApply(next: boolean) {\r\n enabled = next\r\n try {\r\n localStorage.setItem(KEY, next ? '1' : '0')\r\n } catch {\r\n // Sem storage (aba privada): vale só até recarregar\r\n }\r\n for (const listener of listeners) listener()\r\n}\r\n\r\nconst subscribe = (listener: () => void) => {\r\n listeners.add(listener)\r\n return () => listeners.delete(listener)\r\n}\r\nconst getSnapshot = () => enabled\r\n\r\nexport const useAutoApply = () => useSyncExternalStore(subscribe, getSnapshot, getSnapshot)\r\n\r\n/** Espera entre a última edição e o aplicar automático (digitação não aplica a cada tecla). */\r\nexport const AUTO_APPLY_DELAY = { layout: 500, model: 1200 }\r\n","import { type CSSProperties, type ReactNode, useMemo } from 'react'\r\n\r\n/**\r\n * Destaque de sintaxe do SQL do modelo (sem dependência de editor): um tokenizador pequeno que\r\n * reconhece o que aparece nos modelos — palavras-chave, funções, textos, números, comentários,\r\n * `tabela.coluna` e os marcadores `{keys}` / `{medida}`.\r\n */\r\n\r\nexport type TokenKind =\r\n | 'keyword'\r\n | 'function'\r\n | 'string'\r\n | 'number'\r\n | 'comment'\r\n | 'placeholder'\r\n | 'qualifier'\r\n | 'quoted'\r\n | 'plain'\r\n\r\nexport type Token = { kind: TokenKind; text: string }\r\n\r\nconst KEYWORDS = new Set(\r\n `SELECT FROM WHERE AND OR NOT IN IS NULL JOIN LEFT RIGHT INNER OUTER CROSS ON AS GROUP BY ORDER\r\n HAVING LIMIT OFFSET UNION ALL DISTINCT CASE WHEN THEN ELSE END WITH ASC DESC BETWEEN LIKE EXISTS\r\n INTERVAL TRUE FALSE USING OVER PARTITION ROLLUP`.split(/\\s+/)\r\n)\r\n\r\nconst PATTERN =\r\n /(--[^\\n]*|\\/\\*[\\s\\S]*?(?:\\*\\/|$))|('(?:[^'\\\\]|\\\\.)*'?|\"(?:[^\"\\\\]|\\\\.)*\"?)|(`[^`]*`?)|(\\{[A-Za-z_]\\w*\\})|(\\b\\d+(?:\\.\\d+)?\\b)|([A-Za-z_]\\w*)/g\r\n\r\nexport function tokenizeSql(sql: string): Token[] {\r\n const tokens: Token[] = []\r\n let last = 0\r\n for (const match of sql.matchAll(PATTERN)) {\r\n const index = match.index ?? 0\r\n if (index > last) tokens.push({ kind: 'plain', text: sql.slice(last, index) })\r\n const [text, comment, string, quoted, placeholder, number, word] = match\r\n let kind: TokenKind = 'plain'\r\n if (comment) kind = 'comment'\r\n else if (string) kind = 'string'\r\n else if (quoted) kind = 'quoted'\r\n else if (placeholder) kind = 'placeholder'\r\n else if (number) kind = 'number'\r\n else if (word) {\r\n const after = sql.slice(index + text.length)\r\n // Palavra-chave antes de função: `IN (`, `EXISTS (`, `OVER (`\r\n if (after.startsWith('.')) kind = 'qualifier'\r\n else if (KEYWORDS.has(word.toUpperCase())) kind = 'keyword'\r\n else if (/^\\s*\\(/.test(after)) kind = 'function'\r\n }\r\n tokens.push({ kind, text })\r\n last = index + text.length\r\n }\r\n if (last < sql.length) tokens.push({ kind: 'plain', text: sql.slice(last) })\r\n return tokens\r\n}\r\n\r\n// `style` em vez de `sx` (um span por token). Sem negrito nem itálico: no editor o texto colorido fica por\r\n// baixo do campo e precisa ter exatamente a mesma largura\r\nconst COLORS: Record<TokenKind, CSSProperties> = {\r\n keyword: { color: '#c792ea' },\r\n function: { color: '#82aaff' },\r\n string: { color: '#c3e88d' },\r\n number: { color: '#f78c6c' },\r\n comment: { color: '#697098' },\r\n placeholder: { color: '#ffcb6b' },\r\n qualifier: { color: '#89ddff' },\r\n quoted: { color: '#eeffff' },\r\n plain: {}\r\n}\r\n\r\n/** Os tokens como `<span>` coloridos (para dentro de um `<pre>`). */\r\nexport function HighlightedSql({ code }: { code: string }) {\r\n const parts = useMemo(() => tokenizeSql(code), [code])\r\n return (\r\n <>\r\n {parts.map((token, index): ReactNode =>\r\n token.kind === 'plain' ? (\r\n token.text\r\n ) : (\r\n // biome-ignore lint/suspicious/noArrayIndexKey: tokens recalculados a cada texto\r\n <span key={index} style={COLORS[token.kind]}>\r\n {token.text}\r\n </span>\r\n )\r\n )}\r\n </>\r\n )\r\n}\r\n","import {\r\n Box,\r\n Button,\r\n type ButtonProps,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n FormControlLabel,\r\n Switch,\r\n Table,\r\n TableBody,\r\n TableCell,\r\n TableContainer,\r\n TableHead,\r\n TableRow,\r\n TableSortLabel,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport { type ReactNode, useState } from 'react'\r\nimport type { RowDiff } from '../compare'\r\nimport { setAutoApply, useAutoApply } from './autoApply'\r\nimport type { DashboardRow } from '../types'\r\nimport type { DiffLine } from './lineDiff'\r\nimport { HighlightedSql } from './sqlHighlight'\r\nimport type { RunStatus } from './store'\r\n\r\nexport const MONO = 'ui-monospace, SFMono-Regular, Menlo, Consolas, monospace'\r\n\r\nexport const STATUS_COLOR: Record<RunStatus, string> = {\r\n loading: '#4dabf7',\r\n success: '#51cf66',\r\n error: '#ff6b6b',\r\n cancelled: '#868e96'\r\n}\r\n\r\nexport const STATUS_LABEL: Record<RunStatus, string> = {\r\n loading: 'carregando',\r\n success: 'ok',\r\n error: 'erro',\r\n cancelled: 'cancelada'\r\n}\r\n\r\nexport function StatusDot({ status }: { status: RunStatus }) {\r\n return (\r\n <Box\r\n component=\"span\"\r\n title={STATUS_LABEL[status]}\r\n sx={{\r\n width: 8,\r\n height: 8,\r\n flexShrink: 0,\r\n borderRadius: '50%',\r\n display: 'inline-block',\r\n bgcolor: STATUS_COLOR[status]\r\n }}\r\n />\r\n )\r\n}\r\n\r\n/**\r\n * Copia para a área de transferência. Com o devtools em janela separada, o clipboard tem que ser o\r\n * dela (o da página não está em foco e recusa): passe o elemento clicado.\r\n */\r\nexport async function copyText(text: string, from?: Element | null) {\r\n try {\r\n const view = from?.ownerDocument.defaultView ?? window\r\n await view.navigator.clipboard.writeText(text)\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\n\r\nexport function CopyButton({ text, label = 'Copiar' }: { text: string; label?: string }) {\r\n const [copied, setCopied] = useState(false)\r\n return (\r\n <Button\r\n size=\"small\"\r\n onClick={async (event) => {\r\n if (await copyText(text, event.currentTarget)) {\r\n setCopied(true)\r\n setTimeout(() => setCopied(false), 1200)\r\n }\r\n }}\r\n >\r\n {copied ? 'Copiado!' : label}\r\n </Button>\r\n )\r\n}\r\n\r\nconst COLLAPSED_KEY = 'bm-dashboard-devtools:collapsed'\r\n\r\nfunction loadCollapsed(): string[] {\r\n try {\r\n const saved = JSON.parse(localStorage.getItem(COLLAPSED_KEY) ?? '[]')\r\n return Array.isArray(saved) ? saved : []\r\n } catch {\r\n return []\r\n }\r\n}\r\n\r\n/** Seção recolhida (lembrada entre recargas, pela chave). */\r\nfunction useCollapsed(key: string | undefined) {\r\n const [collapsed, setCollapsed] = useState(() => !!key && loadCollapsed().includes(key))\r\n const toggle = () => {\r\n if (!key) return\r\n const next = !collapsed\r\n setCollapsed(next)\r\n try {\r\n const others = loadCollapsed().filter((item) => item !== key)\r\n localStorage.setItem(COLLAPSED_KEY, JSON.stringify(next ? [...others, key] : others))\r\n } catch {}\r\n }\r\n return [collapsed, toggle] as const\r\n}\r\n\r\nexport function Section({\r\n title,\r\n actions,\r\n collapseKey,\r\n children\r\n}: {\r\n title: ReactNode\r\n actions?: ReactNode\r\n /** Com chave, o título recolhe/expande a seção (a escolha fica salva no navegador). */\r\n collapseKey?: string\r\n children: ReactNode\r\n}) {\r\n const [collapsed, toggle] = useCollapsed(collapseKey)\r\n return (\r\n <Box sx={{ mb: collapsed ? 0.5 : 2 }}>\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 0.5, minHeight: 30 }}>\r\n <Typography\r\n variant=\"overline\"\r\n component={collapseKey ? 'button' : 'span'}\r\n {...(collapseKey && {\r\n type: 'button',\r\n onClick: toggle,\r\n 'aria-expanded': !collapsed,\r\n title: collapsed ? 'Expandir' : 'Recolher'\r\n })}\r\n sx={{\r\n color: 'text.secondary',\r\n lineHeight: 1.5,\r\n fontWeight: 700,\r\n ...(collapseKey && {\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.5,\r\n p: 0,\r\n border: 0,\r\n bgcolor: 'transparent',\r\n cursor: 'pointer',\r\n textAlign: 'left',\r\n '&:hover': { color: 'text.primary' }\r\n })\r\n }}\r\n >\r\n {collapseKey && (\r\n <Box\r\n component=\"span\"\r\n aria-hidden\r\n sx={{\r\n display: 'inline-block',\r\n fontSize: 9,\r\n transition: 'transform .15s',\r\n transform: collapsed ? 'rotate(-90deg)' : 'none'\r\n }}\r\n >\r\n ▼\r\n </Box>\r\n )}\r\n {title}\r\n </Typography>\r\n {!collapsed && <Box sx={{ ml: 'auto', display: 'flex', gap: 0.5 }}>{actions}</Box>}\r\n </Box>\r\n {!collapsed && children}\r\n </Box>\r\n )\r\n}\r\n\r\nexport function CodeBlock({\r\n code,\r\n maxHeight = 260,\r\n sql = false\r\n}: {\r\n code: string\r\n maxHeight?: number\r\n /** Colore como SQL. */\r\n sql?: boolean\r\n}) {\r\n return (\r\n <Box sx={{ position: 'relative' }}>\r\n <Box\r\n component=\"pre\"\r\n sx={{\r\n m: 0,\r\n p: 1.25,\r\n pr: 9,\r\n maxHeight,\r\n overflow: 'auto',\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n lineHeight: 1.5,\r\n bgcolor: 'rgba(0,0,0,.35)',\r\n borderRadius: 1,\r\n whiteSpace: 'pre'\r\n }}\r\n >\r\n {sql ? <HighlightedSql code={code} /> : code}\r\n </Box>\r\n <Box sx={{ position: 'absolute', top: 4, right: 4 }}>\r\n <CopyButton text={code} />\r\n </Box>\r\n </Box>\r\n )\r\n}\r\n\r\n/** Substitui os `?` pelos parâmetros, para colar o SQL direto num cliente de banco. */\r\nexport function inlineParams(sql: string, params: (string | number)[]) {\r\n let index = 0\r\n return sql.replace(/\\?/g, () => {\r\n const value = params[index++]\r\n if (value === undefined) return '?'\r\n return typeof value === 'number' ? String(value) : `'${value.replaceAll(\"'\", \"''\")}'`\r\n })\r\n}\r\n\r\nconst MAX_ROWS = 500\r\n\r\n/** Ordena linhas de resultado por uma coluna; `null` sempre no fim. */\r\nfunction compareCells(\r\n a: DashboardRow,\r\n b: DashboardRow,\r\n { column, direction }: { column: string; direction: 'asc' | 'desc' }\r\n) {\r\n const [x, y] = [a[column], b[column]]\r\n if (x === null || x === undefined) return y === null || y === undefined ? 0 : 1\r\n if (y === null || y === undefined) return -1\r\n const order =\r\n typeof x === 'number' && typeof y === 'number'\r\n ? x - y\r\n : String(x).localeCompare(String(y), 'pt-BR', { numeric: true })\r\n return direction === 'asc' ? order : -order\r\n}\r\n\r\nexport function ResultTable({\r\n rows,\r\n maxHeight = 320\r\n}: {\r\n rows: DashboardRow[]\r\n maxHeight?: number\r\n}) {\r\n const [sort, setSort] = useState<{ column: string; direction: 'asc' | 'desc' } | null>(null)\r\n if (!rows.length)\r\n return <Typography sx={{ color: 'text.secondary', fontSize: 12 }}>Nenhuma linha.</Typography>\r\n const columns = Object.keys(rows[0])\r\n const sorted = sort ? [...rows].sort((a, b) => compareCells(a, b, sort)) : rows\r\n // Clique alterna crescente → decrescente → ordem original\r\n const toggleSort = (column: string) =>\r\n setSort((current) =>\r\n current?.column !== column\r\n ? { column, direction: 'asc' }\r\n : current.direction === 'asc'\r\n ? { column, direction: 'desc' }\r\n : null\r\n )\r\n return (\r\n <>\r\n <TableContainer sx={{ maxHeight, border: 1, borderColor: 'divider', borderRadius: 1 }}>\r\n <Table size=\"small\" stickyHeader>\r\n <TableHead>\r\n <TableRow>\r\n {columns.map((column) => (\r\n <TableCell\r\n key={column}\r\n sortDirection={sort?.column === column ? sort.direction : false}\r\n sx={{ fontFamily: MONO, fontWeight: 700, whiteSpace: 'nowrap' }}\r\n >\r\n <TableSortLabel\r\n active={sort?.column === column}\r\n direction={sort?.column === column ? sort.direction : 'asc'}\r\n onClick={() => toggleSort(column)}\r\n >\r\n {column}\r\n </TableSortLabel>\r\n </TableCell>\r\n ))}\r\n </TableRow>\r\n </TableHead>\r\n <TableBody>\r\n {sorted.slice(0, MAX_ROWS).map((row, index) => (\r\n // biome-ignore lint/suspicious/noArrayIndexKey: linhas de resultado não têm id\r\n <TableRow key={index} hover>\r\n {columns.map((column) => (\r\n <TableCell\r\n key={column}\r\n align={typeof row[column] === 'number' ? 'right' : 'left'}\r\n sx={{ fontFamily: MONO, whiteSpace: 'nowrap' }}\r\n >\r\n {row[column] === null ? (\r\n <Box component=\"span\" sx={{ color: 'text.disabled' }}>\r\n null\r\n </Box>\r\n ) : (\r\n String(row[column])\r\n )}\r\n </TableCell>\r\n ))}\r\n </TableRow>\r\n ))}\r\n </TableBody>\r\n </Table>\r\n </TableContainer>\r\n {rows.length > MAX_ROWS && (\r\n <Typography sx={{ color: 'text.secondary', fontSize: 12, mt: 0.5 }}>\r\n Mostrando {MAX_ROWS} de {rows.length} linhas.\r\n </Typography>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nexport function Empty({ children }: { children: ReactNode }) {\r\n return (\r\n <Box\r\n sx={{\r\n height: '100%',\r\n minHeight: 120,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n color: 'text.secondary',\r\n fontSize: 13,\r\n textAlign: 'center',\r\n p: 2\r\n }}\r\n >\r\n {children}\r\n </Box>\r\n )\r\n}\r\n\r\nconst DIFF_LINE_COLOR = {\r\n same: 'transparent',\r\n added: 'rgba(81, 207, 102, .18)',\r\n removed: 'rgba(255, 107, 107, .18)'\r\n} as const\r\n\r\n/** Diff de arquivo; linhas iguais longe de mudanças ficam recolhidas. */\r\nexport function FileDiff({ lines, context = 3 }: { lines: DiffLine[]; context?: number }) {\r\n const near = lines.map((_, index) =>\r\n lines\r\n .slice(Math.max(0, index - context), index + context + 1)\r\n .some((line) => line.kind !== 'same')\r\n )\r\n const output: ReactNode[] = []\r\n let skipped = 0\r\n lines.forEach((line, index) => {\r\n if (!near[index]) {\r\n skipped++\r\n return\r\n }\r\n if (skipped) {\r\n output.push(\r\n // biome-ignore lint/suspicious/noArrayIndexKey: posição do trecho recolhido no diff\r\n <Box key={`skip-${index}`} sx={{ color: 'text.disabled', px: 1 }}>\r\n ⋯ {skipped} linhas iguais\r\n </Box>\r\n )\r\n skipped = 0\r\n }\r\n output.push(\r\n // biome-ignore lint/suspicious/noArrayIndexKey: linhas de um diff fixo, sem id próprio\r\n <Box key={index} sx={{ bgcolor: DIFF_LINE_COLOR[line.kind], px: 1, whiteSpace: 'pre' }}>\r\n {line.kind === 'added' ? '+ ' : line.kind === 'removed' ? '- ' : ' '}\r\n {line.text}\r\n </Box>\r\n )\r\n })\r\n if (skipped)\r\n output.push(\r\n <Box key=\"skip-end\" sx={{ color: 'text.disabled', px: 1 }}>\r\n ⋯ {skipped} linhas iguais\r\n </Box>\r\n )\r\n return (\r\n <Box\r\n sx={{\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n lineHeight: 1.5,\r\n bgcolor: 'rgba(0,0,0,.35)',\r\n borderRadius: 1,\r\n py: 1,\r\n overflow: 'auto',\r\n maxHeight: 420\r\n }}\r\n >\r\n {lines.some((line) => line.kind !== 'same') ? (\r\n output\r\n ) : (\r\n <Box sx={{ px: 1 }}>Sem mudanças.</Box>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\nconst DIFF_KIND_LABEL: Record<RowDiff['kind'], string> = {\r\n missing: 'sumiu',\r\n extra: 'nova',\r\n changed: 'mudou'\r\n}\r\n\r\n/** Linhas que diferem entre dois resultados (esperado x atual). */\r\nexport function RowDiffTable({\r\n diffs,\r\n expectedLabel = 'esperado',\r\n actualLabel = 'atual'\r\n}: {\r\n diffs: RowDiff[]\r\n expectedLabel?: string\r\n actualLabel?: string\r\n}) {\r\n if (!diffs.length)\r\n return <Typography sx={{ color: 'success.main', fontSize: 12 }}>Resultados iguais.</Typography>\r\n return (\r\n <TableContainer sx={{ maxHeight: 320, border: 1, borderColor: 'divider', borderRadius: 1 }}>\r\n <Table size=\"small\" stickyHeader>\r\n <TableHead>\r\n <TableRow>\r\n <TableCell>linha</TableCell>\r\n <TableCell>dimensões</TableCell>\r\n <TableCell>medida</TableCell>\r\n <TableCell align=\"right\">{expectedLabel}</TableCell>\r\n <TableCell align=\"right\">{actualLabel}</TableCell>\r\n <TableCell align=\"right\">diferença</TableCell>\r\n </TableRow>\r\n </TableHead>\r\n <TableBody>\r\n {diffs.flatMap((diff) => {\r\n const where = JSON.stringify(diff.dimensions)\r\n if (diff.kind !== 'changed')\r\n return (\r\n <TableRow key={where}>\r\n <TableCell sx={{ color: diff.kind === 'missing' ? 'error.main' : 'info.main' }}>\r\n {DIFF_KIND_LABEL[diff.kind]}\r\n </TableCell>\r\n <TableCell sx={{ fontFamily: MONO }} colSpan={5}>\r\n {where}\r\n </TableCell>\r\n </TableRow>\r\n )\r\n return diff.changes.map((change) => (\r\n <TableRow key={`${where}-${change.measure}`}>\r\n <TableCell sx={{ color: 'warning.main' }}>{DIFF_KIND_LABEL.changed}</TableCell>\r\n <TableCell sx={{ fontFamily: MONO }}>{where}</TableCell>\r\n <TableCell sx={{ fontFamily: MONO }}>{change.measure}</TableCell>\r\n <TableCell align=\"right\" sx={{ fontFamily: MONO }}>\r\n {String(change.expected)}\r\n </TableCell>\r\n <TableCell align=\"right\" sx={{ fontFamily: MONO }}>\r\n {String(change.actual)}\r\n </TableCell>\r\n <TableCell align=\"right\" sx={{ fontFamily: MONO }}>\r\n {typeof change.expected === 'number' && typeof change.actual === 'number'\r\n ? (change.actual - change.expected).toFixed(4)\r\n : ''}\r\n </TableCell>\r\n </TableRow>\r\n ))\r\n })}\r\n </TableBody>\r\n </Table>\r\n </TableContainer>\r\n )\r\n}\r\n\r\n/**\r\n * Botão que pede confirmação antes de agir (ações que perdem trabalho, como desfazer edições).\r\n * Diálogo do MUI, e não `confirm()`: no modo janela separada, ele abre no popup.\r\n */\r\nexport function ConfirmButton({\r\n confirmTitle,\r\n confirmText,\r\n confirmLabel = 'Confirmar',\r\n onConfirm,\r\n ...props\r\n}: Omit<ButtonProps, 'onClick'> & {\r\n confirmTitle: string\r\n confirmText: ReactNode\r\n confirmLabel?: string\r\n onConfirm: () => void\r\n}) {\r\n const [open, setOpen] = useState(false)\r\n return (\r\n <>\r\n <Button {...props} onClick={() => setOpen(true)} />\r\n <Dialog open={open} onClose={() => setOpen(false)} maxWidth=\"xs\" fullWidth>\r\n <DialogTitle sx={{ fontSize: 15 }}>{confirmTitle}</DialogTitle>\r\n <DialogContent>\r\n <Typography sx={{ fontSize: 13 }}>{confirmText}</Typography>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => setOpen(false)}>Cancelar</Button>\r\n <Button\r\n variant=\"contained\"\r\n color=\"warning\"\r\n autoFocus\r\n onClick={() => {\r\n setOpen(false)\r\n onConfirm()\r\n }}\r\n >\r\n {confirmLabel}\r\n </Button>\r\n </DialogActions>\r\n </Dialog>\r\n </>\r\n )\r\n}\r\n\r\n/** Liga/desliga o \"Aplicar automaticamente\" (compartilhado entre os editores). */\r\nexport function AutoApplySwitch({ applying }: { applying?: boolean }) {\r\n const enabled = useAutoApply()\r\n return (\r\n <Tooltip title=\"Cada edição válida vai para a página sozinha (como “Aplicar na página”). Desligado, aparece o botão Aplicar.\">\r\n <FormControlLabel\r\n sx={{ m: 0, mr: 0.5 }}\r\n control={\r\n <Switch size=\"small\" checked={enabled} onChange={(e) => setAutoApply(e.target.checked)} />\r\n }\r\n label={\r\n <Typography sx={{ fontSize: 12 }}>\r\n Aplicar automaticamente{enabled && applying ? ' · aplicando…' : ''}\r\n </Typography>\r\n }\r\n />\r\n </Tooltip>\r\n )\r\n}\r\n","import { Alert, Box, Button, Chip, TextField, Typography } from '@mui/material'\r\nimport { useEffect, useState } from 'react'\r\nimport type { DashboardDevtoolsContext } from '../client/DashboardProvider'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport type { DashboardFilters } from '../types'\r\nimport { MONO, Section } from './ui'\r\n\r\nfunction parseFilters(text: string): DashboardFilters {\r\n const parsed: unknown = JSON.parse(text)\r\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))\r\n throw new Error('Esperado um objeto { dimensão: [valores] }')\r\n for (const [name, values] of Object.entries(parsed)) {\r\n const valid =\r\n Array.isArray(values) &&\r\n values.every((value) => typeof value === 'string' || typeof value === 'number')\r\n if (!valid) throw new Error(`\"${name}\" precisa ser uma lista de textos/números`)\r\n }\r\n return parsed as DashboardFilters\r\n}\r\n\r\n/** Estado dos filtros do `DashboardProvider`, editável como JSON. */\r\nexport function FiltersPanel({ devtools }: { devtools: DashboardDevtoolsContext }) {\r\n const { filters, setFilter } = useDashboard()\r\n const current = JSON.stringify(filters, null, 2)\r\n const [text, setText] = useState(current)\r\n const [error, setError] = useState<string | null>(null)\r\n\r\n // Filtro alterado na página: o texto acompanha (descarta edição não aplicada)\r\n useEffect(() => {\r\n setText(current)\r\n setError(null)\r\n }, [current])\r\n\r\n const active = Object.entries(filters).filter(([, values]) => values.length)\r\n\r\n const apply = () => {\r\n try {\r\n devtools.setFilters(parseFilters(text))\r\n setError(null)\r\n } catch (err) {\r\n setError((err as Error).message)\r\n }\r\n }\r\n\r\n return (\r\n <Box sx={{ p: 1.5, overflow: 'auto', height: '100%' }}>\r\n <Section\r\n title=\"Filtros ativos\"\r\n actions={\r\n <>\r\n <Button size=\"small\" onClick={() => devtools.setFilters(devtools.defaultFilters)}>\r\n Restaurar padrão\r\n </Button>\r\n <Button size=\"small\" onClick={() => devtools.setFilters({})}>\r\n Limpar tudo\r\n </Button>\r\n </>\r\n }\r\n >\r\n <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>\r\n {active.map(([name, values]) => (\r\n <Chip\r\n key={name}\r\n size=\"small\"\r\n label={`${name}: ${values.join(', ')}`}\r\n onDelete={() => setFilter(name, [])}\r\n sx={{ fontFamily: MONO }}\r\n />\r\n ))}\r\n {!active.length && (\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n Nenhum filtro: tudo aparece como \"Todos\".\r\n </Typography>\r\n )}\r\n </Box>\r\n </Section>\r\n\r\n <Section\r\n title=\"Editar como JSON\"\r\n actions={\r\n <Button size=\"small\" variant=\"contained\" disabled={text === current} onClick={apply}>\r\n Aplicar\r\n </Button>\r\n }\r\n >\r\n <TextField\r\n fullWidth\r\n multiline\r\n minRows={6}\r\n maxRows={18}\r\n value={text}\r\n onChange={(e) => setText(e.target.value)}\r\n error={!!error}\r\n sx={{ '& .MuiInputBase-input': { fontFamily: MONO, fontSize: 12 } }}\r\n />\r\n {error && (\r\n <Alert severity=\"error\" sx={{ mt: 1 }}>\r\n {error}\r\n </Alert>\r\n )}\r\n </Section>\r\n\r\n <Section title=\"Padrão do provider (defaultFilters)\">\r\n <Typography sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {JSON.stringify(devtools.defaultFilters)}\r\n </Typography>\r\n </Section>\r\n </Box>\r\n )\r\n}\r\n","import { createTheme, type Theme, ThemeProvider } from '@mui/material'\r\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from 'react'\r\nimport { createPortal } from 'react-dom'\r\n\r\n/**\r\n * Devtools numa janela separada do navegador (popup), para usar com a página em tela cheia ou em\r\n * outro monitor. O painel continua sendo renderizado pela árvore React da página (mesmo contexto,\r\n * mesmo store), só que via portal no `document` do popup:\r\n *\r\n * - os estilos do emotion/MUI vão para o `<head>` da página; aqui eles são espelhados no popup;\r\n * - menus, tooltips e diálogos do MUI montam no `body` da página por padrão: o tema da janela\r\n * aponta o `container` deles para o popup.\r\n *\r\n * Recarregar a página derruba o vínculo (o popup é de outra árvore): o popup avisa e o botão do\r\n * devtools na página reconecta (abrir popup exige um clique, o navegador bloqueia sem gesto).\r\n */\r\n\r\nconst WINDOW_NAME = 'bm-bi-devtools'\r\n\r\n/** Abre (ou reaproveita, se ainda estiver aberta) a janela do devtools. `null` = bloqueada. */\r\nexport function openDevtoolsWindow(): Window | null {\r\n const width = Math.min(1100, window.screen.availWidth)\r\n const height = Math.min(720, window.screen.availHeight)\r\n return window.open('', WINDOW_NAME, `popup,width=${width},height=${height}`)\r\n}\r\n\r\nconst isStyleNode = (node: Node): node is HTMLStyleElement | HTMLLinkElement =>\r\n node instanceof HTMLStyleElement || (node instanceof HTMLLinkElement && node.rel === 'stylesheet')\r\n\r\n/** Cópia de um `<style>`/`<link>`; estilo inserido por `insertRule` (sem texto) vai pelas regras. */\r\nfunction cloneStyle(node: HTMLStyleElement | HTMLLinkElement, target: Document) {\r\n const clone = target.importNode(node, true)\r\n if (node instanceof HTMLStyleElement && !node.textContent && node.sheet?.cssRules.length)\r\n clone.textContent = [...node.sheet.cssRules].map((rule) => rule.cssText).join('\\n')\r\n return clone\r\n}\r\n\r\n/** Copia os estilos da página para o popup e acompanha os que entrarem/saírem depois. */\r\nfunction mirrorStyles(source: Document, target: Document) {\r\n const clones = new Map<Node, Node>()\r\n const add = (node: Node) => {\r\n if (!isStyleNode(node) || clones.has(node)) return\r\n const clone = cloneStyle(node, target)\r\n clones.set(node, clone)\r\n target.head.appendChild(clone)\r\n }\r\n for (const node of source.head.querySelectorAll('style, link[rel=\"stylesheet\"]')) add(node)\r\n\r\n const observer = new MutationObserver((mutations) => {\r\n for (const mutation of mutations) {\r\n if (mutation.type === 'characterData' || mutation.target !== source.head) {\r\n // Texto de um <style> mudou: recopia\r\n const style = (\r\n mutation.target instanceof Element ? mutation.target : mutation.target.parentElement\r\n )?.closest('style')\r\n const clone = style && clones.get(style)\r\n if (style && clone) {\r\n const next = cloneStyle(style, target)\r\n target.head.replaceChild(next, clone)\r\n clones.set(style, next)\r\n }\r\n continue\r\n }\r\n for (const node of mutation.addedNodes) add(node)\r\n for (const node of mutation.removedNodes) {\r\n clones.get(node)?.parentNode?.removeChild(clones.get(node) as Node)\r\n clones.delete(node)\r\n }\r\n }\r\n })\r\n observer.observe(source.head, { childList: true, subtree: true, characterData: true })\r\n return () => observer.disconnect()\r\n}\r\n\r\n/** Tema com os portais do MUI (menus, tooltips, diálogos) dentro do popup. */\r\nfunction windowTheme(base: Theme, container: HTMLElement) {\r\n return createTheme(base, {\r\n components: {\r\n MuiModal: { defaultProps: { container } },\r\n MuiPopover: { defaultProps: { container } },\r\n MuiPopper: { defaultProps: { container } },\r\n MuiDialog: { defaultProps: { container } },\r\n MuiMenu: { defaultProps: { container } }\r\n }\r\n })\r\n}\r\n\r\nexport function DevtoolsWindow({\r\n popup,\r\n title,\r\n theme,\r\n onClosed,\r\n children\r\n}: {\r\n popup: Window\r\n title: string\r\n theme: Theme\r\n /** O usuário fechou a janela. */\r\n onClosed: () => void\r\n children: ReactNode\r\n}) {\r\n const [root, setRoot] = useState<HTMLElement | null>(null)\r\n const onClosedRef = useRef(onClosed)\r\n onClosedRef.current = onClosed\r\n\r\n useEffect(() => {\r\n const doc = popup.document\r\n doc.title = title\r\n // Reaproveitada depois de recarregar a página: limpa o que a árvore anterior deixou\r\n doc.head.replaceChildren()\r\n doc.body.replaceChildren()\r\n const meta = doc.createElement('meta')\r\n meta.setAttribute('charset', 'utf-8')\r\n doc.head.appendChild(meta)\r\n const base = doc.createElement('style')\r\n base.textContent = `html, body { height: 100%; margin: 0; background: ${theme.palette.background.paper}; color-scheme: dark; } body { font-family: ${theme.typography.fontFamily}; } #${WINDOW_NAME} { height: 100%; display: flex; flex-direction: column; }`\r\n doc.head.appendChild(base)\r\n const container = doc.createElement('div')\r\n container.id = WINDOW_NAME\r\n doc.body.appendChild(container)\r\n const stopMirror = mirrorStyles(document, doc)\r\n setRoot(container)\r\n\r\n // Janela fechada pelo usuário (o `pagehide` do popup não é confiável em todos os navegadores)\r\n const poll = setInterval(() => {\r\n if (popup.closed) onClosedRef.current()\r\n }, 400)\r\n // A página saiu (recarregou/navegou): o popup fica órfão, avisa como reconectar\r\n const onPageHide = () => {\r\n stopMirror()\r\n doc.body.innerHTML = `<p style=\"font: 14px sans-serif; color: #ccc; padding: 24px\">A página do dashboard recarregou. Clique no botão <b style=\"color: #F58220\">◆ BI</b> da página para reconectar o devtools a esta janela.</p>`\r\n }\r\n window.addEventListener('pagehide', onPageHide)\r\n return () => {\r\n clearInterval(poll)\r\n window.removeEventListener('pagehide', onPageHide)\r\n stopMirror()\r\n setRoot(null)\r\n }\r\n }, [popup, title, theme])\r\n\r\n const localTheme = useMemo(() => root && windowTheme(theme, root), [theme, root])\r\n\r\n if (!root || !localTheme) return null\r\n return createPortal(<ThemeProvider theme={localTheme}>{children}</ThemeProvider>, root)\r\n}\r\n","import { Box } from '@mui/material'\r\nimport { useEffect, useState } from 'react'\r\nimport { INSPECT_ATTRIBUTE } from '../client/useModelQuery'\r\n\r\n/**\r\n * Liga componente da página <-> consulta do devtools. Os componentes marcam o elemento raiz com\r\n * `inspectProps` do `useModelQuery` (`data-bm-dashboard-query=\"<instanceId>\"`).\r\n */\r\n\r\n/** Marca os elementos do próprio painel, que o modo de inspeção ignora. */\r\nexport const DEVTOOLS_ATTRIBUTE = 'data-bm-devtools'\r\n\r\nexport const findQueryElement = (instanceId: string) =>\r\n document.querySelector<HTMLElement>(`[${INSPECT_ATTRIBUTE}=\"${CSS.escape(instanceId)}\"]`)\r\n\r\nexport function scrollToQuery(instanceId: string) {\r\n findQueryElement(instanceId)?.scrollIntoView({ behavior: 'smooth', block: 'center' })\r\n}\r\n\r\n/** Retângulo do elemento, acompanhando scroll/resize. */\r\nfunction useElementRect(instanceId: string | null) {\r\n const [rect, setRect] = useState<DOMRect | null>(null)\r\n useEffect(() => {\r\n if (!instanceId) {\r\n setRect(null)\r\n return\r\n }\r\n let frame = 0\r\n const update = () => {\r\n setRect(findQueryElement(instanceId)?.getBoundingClientRect() ?? null)\r\n frame = requestAnimationFrame(update)\r\n }\r\n update()\r\n return () => cancelAnimationFrame(frame)\r\n }, [instanceId])\r\n return rect\r\n}\r\n\r\nexport function HighlightOverlay({\r\n instanceId,\r\n label,\r\n zIndex\r\n}: {\r\n instanceId: string | null\r\n label?: string\r\n zIndex: number\r\n}) {\r\n const rect = useElementRect(instanceId)\r\n if (!rect) return null\r\n return (\r\n <Box\r\n sx={{\r\n position: 'fixed',\r\n top: rect.top,\r\n left: rect.left,\r\n width: rect.width,\r\n height: rect.height,\r\n zIndex,\r\n pointerEvents: 'none',\r\n outline: '2px solid #F58220',\r\n bgcolor: 'rgba(245, 130, 32, .12)',\r\n borderRadius: 0.5\r\n }}\r\n >\r\n {label && (\r\n <Box\r\n sx={{\r\n position: 'absolute',\r\n left: -2,\r\n bottom: '100%',\r\n px: 0.75,\r\n py: 0.25,\r\n bgcolor: '#F58220',\r\n color: '#111',\r\n fontSize: 11,\r\n fontWeight: 700,\r\n whiteSpace: 'nowrap',\r\n fontFamily: 'ui-monospace, monospace'\r\n }}\r\n >\r\n {label}\r\n </Box>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\n/**\r\n * Modo de inspeção: passar o mouse num componente do dashboard destaca a consulta dele; clicar\r\n * seleciona no painel. O clique é engolido para não acionar o componente.\r\n */\r\nexport function useInspectMode({\r\n active,\r\n onHover,\r\n onPick\r\n}: {\r\n active: boolean\r\n onHover: (instanceId: string | null) => void\r\n onPick: (instanceId: string) => void\r\n}) {\r\n useEffect(() => {\r\n if (!active) return\r\n const target = (event: Event) => {\r\n const element = event.target as Element | null\r\n if (!element?.closest || element.closest(`[${DEVTOOLS_ATTRIBUTE}]`)) return null\r\n return element.closest(`[${INSPECT_ATTRIBUTE}]`)?.getAttribute(INSPECT_ATTRIBUTE) ?? null\r\n }\r\n const move = (event: MouseEvent) => onHover(target(event))\r\n const click = (event: MouseEvent) => {\r\n const instanceId = target(event)\r\n if (!instanceId) return\r\n event.preventDefault()\r\n event.stopPropagation()\r\n onPick(instanceId)\r\n }\r\n // O Select do MUI abre no mousedown, antes do click\r\n const press = (event: MouseEvent) => {\r\n if (!target(event)) return\r\n event.preventDefault()\r\n event.stopPropagation()\r\n }\r\n const previousCursor = document.body.style.cursor\r\n document.body.style.cursor = 'crosshair'\r\n document.addEventListener('mousemove', move, true)\r\n document.addEventListener('mousedown', press, true)\r\n document.addEventListener('click', click, true)\r\n return () => {\r\n document.body.style.cursor = previousCursor\r\n document.removeEventListener('mousemove', move, true)\r\n document.removeEventListener('mousedown', press, true)\r\n document.removeEventListener('click', click, true)\r\n onHover(null)\r\n }\r\n }, [active, onHover, onPick])\r\n}\r\n","export type DiffLine = { kind: 'same' | 'added' | 'removed'; text: string }\r\n\r\n/** Diff de linhas por LCS. Suficiente para arquivos de modelo (centenas de linhas). */\r\nexport function lineDiff(before: string, after: string): DiffLine[] {\r\n const a = before.split('\\n')\r\n const b = after.split('\\n')\r\n const lcs: number[][] = Array.from({ length: a.length + 1 }, () =>\r\n new Array(b.length + 1).fill(0)\r\n )\r\n for (let i = a.length - 1; i >= 0; i--)\r\n for (let j = b.length - 1; j >= 0; j--)\r\n lcs[i][j] = a[i] === b[j] ? lcs[i + 1][j + 1] + 1 : Math.max(lcs[i + 1][j], lcs[i][j + 1])\r\n\r\n const lines: DiffLine[] = []\r\n let i = 0\r\n let j = 0\r\n while (i < a.length && j < b.length) {\r\n if (a[i] === b[j]) {\r\n lines.push({ kind: 'same', text: a[i++] })\r\n j++\r\n } else if (lcs[i + 1][j] >= lcs[i][j + 1]) lines.push({ kind: 'removed', text: a[i++] })\r\n else lines.push({ kind: 'added', text: b[j++] })\r\n }\r\n while (i < a.length) lines.push({ kind: 'removed', text: a[i++] })\r\n while (j < b.length) lines.push({ kind: 'added', text: b[j++] })\r\n return lines\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Button,\r\n Checkbox,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n FormControlLabel,\r\n IconButton,\r\n ListSubheader,\r\n Menu,\r\n MenuItem,\r\n Popover,\r\n TextField,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport {\r\n type ChangeEvent,\r\n type DragEvent,\r\n type ReactNode,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n useSyncExternalStore\r\n} from 'react'\r\nimport type { DashboardDevtoolsContext } from '../client/DashboardProvider'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport { SERIES_COLORS } from '../client/chartKit'\r\nimport { formatMeasure } from '../client/format'\r\nimport { INSPECT_ATTRIBUTE } from '../client/useModelQuery'\r\nimport { canonicalJson } from '../codegen'\r\nimport {\r\n COLOR_SCALE_TARGETS,\r\n type ColorScale,\r\n type ColorScaleTarget,\r\n DEFAULT_SCALE_MIN_COLOR,\r\n type FormatRule,\r\n NUMERIC_OPERATORS,\r\n RULE_OPERATOR_LABEL,\r\n RULE_OPERATORS,\r\n type RuleOperator,\r\n UNARY_OPERATORS,\r\n VALUE_RULE_OPERATORS,\r\n type ValueRule,\r\n type ValueRuleOperator\r\n} from '../formatRules'\r\nimport {\r\n BUILTIN_CHART_TYPES,\r\n CANVAS_PRESETS,\r\n type CanvasDef,\r\n CARD_FIELDS,\r\n CARDS_FIELDS,\r\n cardsGap,\r\n type CardsStyle,\r\n type CardStyle,\r\n type ChartDef,\r\n type ChartNumberFormat,\r\n type ChartsLayout,\r\n type ChartTypes,\r\n COLUMN_ALIGNS,\r\n COLUMN_VERTICAL_ALIGNS,\r\n type ColumnAlign,\r\n type ColumnVerticalAlign,\r\n chartColumns,\r\n chartOfType,\r\n chartReferences,\r\n FILTER_FIELDS,\r\n type FieldSpec,\r\n type FilterDef,\r\n filterReferences,\r\n LAYOUT_COLUMNS,\r\n layoutModelWarnings,\r\n PARAMETER_FIELDS,\r\n type ParameterDef,\r\n PERCENT_PREFIX,\r\n percentColumn,\r\n tableColumns,\r\n validateLayout\r\n} from '../layout'\r\nimport { type ModelDef, VALUE_FORMATS } from '../model'\r\nimport type { DevtoolsCapabilities, SaveModelResult } from '../types'\r\nimport {\r\n LAYOUT_ITEM_ATTRIBUTE,\r\n type LayoutItem,\r\n layoutItemKey,\r\n parseLayoutItemKey\r\n} from './layoutStore'\r\nimport { AUTO_APPLY_DELAY, useAutoApply } from './autoApply'\r\nimport { lineDiff } from './lineDiff'\r\nimport { errorMessage } from './store'\r\nimport { AutoApplySwitch, ConfirmButton, Empty, FileDiff, MONO, Section } from './ui'\r\n\r\ntype Props = {\r\n devtools: DashboardDevtoolsContext\r\n /** Modelo em vigor (rascunho, se houver), para listar dimensões e medidas. */\r\n model: ModelDef\r\n capabilities: DevtoolsCapabilities | null\r\n /** Item escolhido pelo inspetor (`layoutItemKey`); objeto novo a cada clique. */\r\n picked: { item: string } | null\r\n /** Destaca a consulta do gráfico na página. */\r\n onHover: (instanceId: string | null) => void\r\n}\r\n\r\nconst inputSx = { '& .MuiInputBase-input': { fontFamily: MONO, fontSize: 12 } }\r\n\r\nconst itemElement = (layoutId: string, item: LayoutItem) =>\r\n document.querySelector<HTMLElement>(\r\n `[${LAYOUT_ITEM_ATTRIBUTE}=\"${CSS.escape(layoutItemKey(layoutId, item))}\"]`\r\n )\r\n\r\nconst itemQueryId = (layoutId: string, item: LayoutItem) =>\r\n itemElement(layoutId, item)\r\n ?.querySelector(`[${INSPECT_ATTRIBUTE}]`)\r\n ?.getAttribute(INSPECT_ATTRIBUTE) ?? null\r\n\r\n/** Item escolhido na lista: a tela (`layout.canvas`), os cards (`layout.cards`), um filtro ou um gráfico. */\r\ntype Selection = LayoutItem | { kind: 'canvas' } | { kind: 'cards' }\r\n\r\ntype DragState = { kind: LayoutItem['kind']; from: number; to: number }\r\n\r\nconst SIDEBAR_KEY = 'bm-dashboard-devtools:layout-sidebar'\r\n\r\n/** Abaixo disso a lista vai para cima do formulário, em vez de ficar ao lado. */\r\nconst STACK_WIDTH = 640\r\n\r\nfunction loadSidebar() {\r\n try {\r\n return localStorage.getItem(SIDEBAR_KEY) !== 'closed'\r\n } catch {\r\n return true\r\n }\r\n}\r\n\r\n/** Largura do elemento, acompanhando o redimensionamento do devtools. */\r\nfunction useWidth() {\r\n const [element, setElement] = useState<HTMLElement | null>(null)\r\n const [width, setWidth] = useState(Number.POSITIVE_INFINITY)\r\n useEffect(() => {\r\n if (!element) return\r\n // O da janela do elemento: com o devtools em janela separada, o da página não vê o elemento\r\n const Observer = element.ownerDocument.defaultView?.ResizeObserver ?? ResizeObserver\r\n const observer = new Observer(([entry]) => entry && setWidth(entry.contentRect.width))\r\n observer.observe(element)\r\n return () => observer.disconnect()\r\n }, [element])\r\n return [setElement, width] as const\r\n}\r\n\r\n/** Move o item `from` para antes da posição `to` (`to === list.length` = fim). */\r\nfunction moveTo<T>(list: T[], from: number, to: number) {\r\n const next = [...list]\r\n const [item] = next.splice(from, 1)\r\n next.splice(to > from ? to - 1 : to, 0, item as T)\r\n return next\r\n}\r\n\r\nconst uniqueId = (charts: ChartDef[], base: string) => {\r\n const ids = new Set(charts.map((chart) => chart.id))\r\n if (!ids.has(base)) return base\r\n let n = 2\r\n while (ids.has(`${base}-${n}`)) n++\r\n return `${base}-${n}`\r\n}\r\n\r\n/** Objeto sem nenhum campo sai do JSON. */\r\nconst nonEmpty = <T extends object>(object: T) => (Object.keys(object).length ? object : undefined)\r\n\r\n/** Campos do card de um gráfico, com o padrão do layout (`cards`) no lugar do padrão da lib. */\r\nconst chartCardFields = (cards: CardsStyle | undefined) =>\r\n Object.fromEntries(\r\n Object.entries(CARD_FIELDS).map(([key, spec]) => [\r\n key,\r\n { ...spec, default: cards?.[key as keyof CardStyle] ?? spec.default } as FieldSpec\r\n ])\r\n )\r\n\r\n/** `cards` como o formulário edita: o `gap` antigo vira `rowGap` e `columnGap`. */\r\nconst cardsValues = (cards: CardsStyle | undefined): Record<string, unknown> => {\r\n const { gap: _gap, ...rest } = cards ?? {}\r\n const space = cardsGap(cards)\r\n return (\r\n nonEmpty({\r\n ...rest,\r\n ...(space.row === undefined ? {} : { rowGap: space.row }),\r\n ...(space.column === undefined ? {} : { columnGap: space.column })\r\n }) ?? {}\r\n )\r\n}\r\n\r\nconst cardsSummary = (cards: CardsStyle | undefined) => {\r\n const { gap: _gap, rowGap: _row, columnGap: _column, ...style } = cards ?? {}\r\n const space = cardsGap(cards)\r\n const custom = Object.keys(style).length\r\n return `espaço ${String(space.row ?? CARDS_FIELDS.rowGap?.default)}×${String(space.column ?? CARDS_FIELDS.columnGap?.default)}px · ${custom ? `${custom} ajuste(s) de estilo` : 'estilo padrão'}`\r\n}\r\n\r\n/** Campo opcional vazio sai do objeto, para o JSON ficar só com o que foi definido. */\r\nfunction withField<T extends object>(object: T, key: keyof T, value: unknown): T {\r\n const next = { ...object }\r\n if (value === undefined || value === '') delete next[key]\r\n else (next as Record<keyof T, unknown>)[key] = value\r\n return next\r\n}\r\n\r\nconst NEW_CHART: Record<string, { id: string; title: string; span: number }> = {\r\n kpi: { id: 'kpi', title: 'Novo KPI', span: 3 },\r\n combo: { id: 'grafico', title: 'Novo gráfico', span: 6 },\r\n bar: { id: 'grafico', title: 'Novo gráfico', span: 6 },\r\n donut: { id: 'grafico', title: 'Novo gráfico', span: 6 },\r\n table: { id: 'tabela', title: 'Nova tabela', span: 12 }\r\n}\r\n\r\nconst newChart = (type: string, model: ModelDef, charts: ChartDef[], types: ChartTypes) => {\r\n // Tipo do app: id pelo nome do tipo, meia largura\r\n const { id, ...rest } = NEW_CHART[type] ?? {\r\n id: type,\r\n title: `Novo ${types[type]?.label ?? type}`,\r\n span: 6\r\n }\r\n return chartOfType(type, model, { id: uniqueId(charts, id), ...rest }, types)\r\n}\r\n\r\nconst chartSummary = (chart: ChartDef, types: ChartTypes) => {\r\n const { dimensions, measures } = chartReferences(chart, types)\r\n return `${chart.type} · ${dimensions.join(', ') || '—'} · ${measures.join(', ')}`\r\n}\r\n\r\n/**\r\n * Editor dos layouts da página (filtros do `<DashboardFilters>` e gráficos do `<DashboardCharts>`).\r\n * Como no modelo: as edições ficam no editor até \"Aplicar na página\" (vira rascunho e a página\r\n * re-renderiza com ele); \"Salvar no arquivo\" grava o JSON do layout com o que está no editor.\r\n */\r\nexport function LayoutPanel({ devtools, model, capabilities, picked, onHover }: Props) {\r\n const { layouts } = devtools\r\n const { fetcher, model: modelName, chartTypes } = useDashboard()\r\n const entries = useSyncExternalStore(layouts.subscribe, layouts.getSnapshot, layouts.getSnapshot)\r\n const [layoutId, setLayoutId] = useState<string | null>(null)\r\n const entry = entries.find((item) => item.registered.id === layoutId) ?? entries[0] ?? null\r\n const reference = entry ? (entry.draft ?? entry.registered) : null\r\n\r\n // Edições não aplicadas (guardadas no store: trocar de aba desmonta o painel)\r\n const pendingOrReference = () => (entry && layouts.pendingOf(entry.registered.id)) ?? reference\r\n const [editing, setEditingState] = useState<ChartsLayout | null>(pendingOrReference)\r\n const [selection, setSelection] = useState<Selection | null>(null)\r\n const [sidebar, setSidebar] = useState(loadSidebar)\r\n const [drag, setDrag] = useState<DragState | null>(null)\r\n const [rootRef, rootWidth] = useWidth()\r\n const [editorRef, editorWidth] = useWidth()\r\n const [busy, setBusy] = useState(false)\r\n const [actionError, setActionError] = useState<string | null>(null)\r\n const [save, setSave] = useState<SaveModelResult | null>(null)\r\n const [addMenu, setAddMenu] = useState<HTMLElement | null>(null)\r\n\r\n const referenceKey = canonicalJson(reference)\r\n /** Muda o editor e guarda como pendente o que difere do que a página mostra. */\r\n const setEditing = (next: ChartsLayout | null) => {\r\n setEditingState(next)\r\n if (entry)\r\n layouts.setPending(\r\n entry.registered.id,\r\n next && canonicalJson(next) !== referenceKey ? next : null\r\n )\r\n }\r\n // Rascunho descartado, arquivo recarregado ou outro layout: o editor acompanha (mantendo as\r\n // edições pendentes daquele layout)\r\n const firstRun = useRef(true)\r\n useEffect(() => {\r\n if (firstRun.current) {\r\n firstRun.current = false\r\n return\r\n }\r\n setEditingState(pendingOrReference())\r\n }, [referenceKey])\r\n\r\n // Inspetor clicou num gráfico\r\n useEffect(() => {\r\n const parsed = picked && parseLayoutItemKey(picked.item)\r\n if (!parsed) return\r\n setLayoutId(parsed.layoutId)\r\n setSelection(parsed.item)\r\n }, [picked])\r\n\r\n const errors = useMemo(\r\n () => (editing ? validateLayout(editing, chartTypes) : []),\r\n [editing, chartTypes]\r\n )\r\n\r\n /** Manda o editor para a página (vira rascunho e a página re-renderiza com ele). */\r\n const applyEditing = () => {\r\n if (!entry || !editing || validateLayout(editing, chartTypes).length) return\r\n devtools.store.expectRefetch()\r\n layouts.setPending(entry.registered.id, null)\r\n layouts.setDraft(entry.registered.id, editing)\r\n }\r\n // Aplicar automaticamente: edição válida vai para a página depois de uma pausa curta\r\n const autoApply = useAutoApply()\r\n const editingKey = canonicalJson(editing)\r\n useEffect(() => {\r\n if (!autoApply || editingKey === referenceKey || errors.length) return\r\n const timer = setTimeout(applyEditing, AUTO_APPLY_DELAY.layout)\r\n return () => clearTimeout(timer)\r\n }, [autoApply, editingKey, referenceKey, errors.length])\r\n const warnings = useMemo(() => {\r\n if (!editing || errors.length) return []\r\n const list = layoutModelWarnings(editing, model, chartTypes)\r\n const { charts: chartFormatters = [], filters: filterFormatters } = entry?.parts ?? {}\r\n const serverTypes = new Set(capabilities?.chartTypes ?? [])\r\n for (const type of new Set(editing.charts.map((chart) => chart.type)))\r\n if (capabilities?.saveLayout && !BUILTIN_CHART_TYPES[type] && !serverTypes.has(type))\r\n list.push(\r\n `Tipo \"${type}\" não foi passado ao \\`devtools.chartTypes\\` do endpoint: \"Salvar no arquivo\" vai recusar.`\r\n )\r\n for (const chart of editing.charts)\r\n for (const name of chartReferences(chart, chartTypes).formatters)\r\n if (!chartFormatters.includes(name))\r\n list.push(\r\n `\"${chart.title || chart.id}\": formatter \"${name}\" não foi passado ao <DashboardCharts formatters>`\r\n )\r\n if (editing.canvas && !entry?.parts.canvas)\r\n list.push(\r\n 'A página não usa <DashboardCanvas layout={...}>: o tamanho fixo da tela não é aplicado.'\r\n )\r\n if (editing.filters?.length && !filterFormatters)\r\n list.push(\r\n 'A página não usa <DashboardFilters layout={...}>: os filtros do layout não aparecem.'\r\n )\r\n for (const filter of editing.filters ?? [])\r\n for (const name of filterReferences(filter).formatters)\r\n if (filterFormatters && !filterFormatters.includes(name))\r\n list.push(\r\n `filtro \"${filter.dimension}\": formatter \"${name}\" não foi passado ao <DashboardFilters formatters>`\r\n )\r\n return list\r\n }, [editing, errors, model, entry, chartTypes, capabilities])\r\n\r\n if (!entry || !editing)\r\n return (\r\n <Empty>\r\n Nenhum <code>{'<DashboardCharts layout={...} />'}</code> ou{' '}\r\n <code>{'<DashboardFilters layout={...} />'}</code> nesta página. Os gráficos e filtros\r\n editáveis pelo devtools vêm de um layout em JSON (ex.:{' '}\r\n <code>src/dashboard/layouts/<id>.json</code>\r\n ).\r\n </Empty>\r\n )\r\n\r\n const charts = editing.charts\r\n const filters = editing.filters ?? []\r\n const parameters = editing.parameters ?? []\r\n const selectedFilter =\r\n selection?.kind === 'filter'\r\n ? (filters.find((filter) => filter.dimension === selection.key) ?? null)\r\n : null\r\n const selectedParameter =\r\n selection?.kind === 'parameter'\r\n ? (parameters.find((parameter) => parameter.name === selection.key) ?? null)\r\n : null\r\n const selected =\r\n selection?.kind === 'filter' ||\r\n selection?.kind === 'parameter' ||\r\n selection?.kind === 'canvas' ||\r\n selection?.kind === 'cards'\r\n ? null\r\n : (charts.find((chart) => chart.id === selection?.key) ?? charts[0] ?? null)\r\n const layoutKey = entry.registered.id\r\n const differsFromFile = canonicalJson(editing) !== canonicalJson(entry.registered)\r\n // Edições ainda não aplicadas (a página mostra o rascunho aplicado ou o arquivo)\r\n const dirty = canonicalJson(editing) !== referenceKey\r\n\r\n // Como no modelo: as edições ficam no editor até \"Aplicar na página\"\r\n const update = (next: ChartsLayout) => {\r\n setEditing(next)\r\n setSave(null)\r\n }\r\n const apply = applyEditing\r\n const setCharts = (next: ChartDef[]) => update({ ...editing, charts: next })\r\n const patchChart = (id: string, change: (chart: ChartDef) => ChartDef) =>\r\n setCharts(charts.map((chart) => (chart.id === id ? change(chart) : chart)))\r\n\r\n const setCanvas = (next: CanvasDef | undefined) => update(withField(editing, 'canvas', next))\r\n const setCards = (key: string, value: unknown) =>\r\n update(withField(editing, 'cards', nonEmpty(withField(cardsValues(editing.cards), key, value))))\r\n\r\n const setFilters = (next: FilterDef[]) => update({ ...editing, filters: next })\r\n const patchFilter = (dimension: string, change: (filter: FilterDef) => FilterDef) =>\r\n setFilters(filters.map((filter) => (filter.dimension === dimension ? change(filter) : filter)))\r\n\r\n const setParameters = (next: ParameterDef[]) =>\r\n update(withField(editing, 'parameters', next.length ? next : undefined))\r\n const patchParameter = (name: string, change: (parameter: ParameterDef) => ParameterDef) =>\r\n setParameters(\r\n parameters.map((parameter) => (parameter.name === name ? change(parameter) : parameter))\r\n )\r\n\r\n const toggleSidebar = () => {\r\n const next = !sidebar\r\n setSidebar(next)\r\n try {\r\n localStorage.setItem(SIDEBAR_KEY, next ? 'open' : 'closed')\r\n } catch {}\r\n }\r\n\r\n // Arrastar para reordenar: só dentro da mesma lista (filtros ou gráficos)\r\n const dragProps = (kind: LayoutItem['kind'], index: number, length: number) => ({\r\n dropBefore: drag?.kind === kind && drag.from !== index && drag.to === index,\r\n dropAfter: drag?.kind === kind && index === length - 1 && drag.to === length,\r\n onDragStart: () => setDrag({ kind, from: index, to: index }),\r\n onDragOver: (e: DragEvent<HTMLElement>) => {\r\n if (drag?.kind !== kind) return\r\n e.preventDefault()\r\n const rect = e.currentTarget.getBoundingClientRect()\r\n const to = e.clientY < rect.top + rect.height / 2 ? index : index + 1\r\n if (to !== drag.to) setDrag({ ...drag, to })\r\n },\r\n onDrop: () => {\r\n if (drag?.kind !== kind) return\r\n if (drag.to !== drag.from && drag.to !== drag.from + 1) {\r\n if (kind === 'chart') setCharts(moveTo(charts, drag.from, drag.to))\r\n else if (kind === 'parameter') setParameters(moveTo(parameters, drag.from, drag.to))\r\n else setFilters(moveTo(filters, drag.from, drag.to))\r\n }\r\n setDrag(null)\r\n },\r\n onDragEnd: () => setDrag(null)\r\n })\r\n\r\n const addFilter = () => {\r\n // Primeira dimensão que ainda não tem filtro\r\n const used = new Set(filters.map((filter) => filter.dimension))\r\n const dimension = Object.keys(model.dimensions).find((name) => !used.has(name))\r\n if (!dimension) return\r\n setFilters([...filters, { dimension }])\r\n setSelection({ kind: 'filter', key: dimension })\r\n }\r\n\r\n const addParameter = () => {\r\n const measure = Object.keys(model.measures)[0]\r\n if (!measure) return\r\n const used = new Set(parameters.map((parameter) => parameter.name))\r\n let name = 'medida'\r\n for (let i = 2; used.has(name); i++) name = `medida-${i}`\r\n setParameters([...parameters, { name, measures: [measure] }])\r\n setSelection({ kind: 'parameter', key: name })\r\n }\r\n\r\n const focus = (item: LayoutItem) => {\r\n setSelection(item)\r\n // Lista empilhada sobre o formulário: fecha para o formulário ter espaço\r\n if (stacked) setSidebar(false)\r\n itemElement(layoutKey, item)?.scrollIntoView({ behavior: 'smooth', block: 'center' })\r\n }\r\n const stacked = rootWidth < STACK_WIDTH\r\n const formColumns = editorWidth < 420 ? 1 : editorWidth < 720 ? 2 : 4\r\n const selectedTitle =\r\n selection?.kind === 'canvas'\r\n ? 'Tela'\r\n : selection?.kind === 'cards'\r\n ? 'Cards'\r\n : selectedFilter\r\n ? selectedFilter.label ||\r\n model.dimensions[selectedFilter.dimension]?.label ||\r\n selectedFilter.dimension\r\n : selectedParameter\r\n ? selectedParameter.label || selectedParameter.name\r\n : selected\r\n ? selected.title || selected.id\r\n : ''\r\n const hover = (item: LayoutItem | null) => onHover(item && itemQueryId(layoutKey, item))\r\n\r\n const add = (type: string, base?: ChartDef) => {\r\n setAddMenu(null)\r\n const chart = base\r\n ? { ...base, id: uniqueId(charts, base.id), title: `${base.title} (cópia)` }\r\n : newChart(type, model, charts, chartTypes)\r\n const index = base ? charts.findIndex((item) => item.id === base.id) + 1 : charts.length\r\n setCharts([...charts.slice(0, index), chart, ...charts.slice(index)])\r\n setSelection({ kind: 'chart', key: chart.id })\r\n setTimeout(() =>\r\n itemElement(layoutKey, { kind: 'chart', key: chart.id })?.scrollIntoView({ block: 'center' })\r\n )\r\n }\r\n\r\n const saveFile = async (mode: 'preview' | 'write') => {\r\n setBusy(true)\r\n setActionError(null)\r\n try {\r\n const result = await fetcher({\r\n model: modelName,\r\n devtools: { saveLayout: { layout: editing, mode } }\r\n })\r\n setSave(mode === 'write' ? null : (result.devtools?.save ?? null))\r\n // Gravado: a página passa a mostrar o que foi salvo (mesmo sem ter aplicado); o Next recarrega\r\n // o JSON e o rascunho some sozinho quando bater com o arquivo\r\n if (mode === 'write' && editing && entry) {\r\n devtools.store.expectRefetch()\r\n layouts.setPending(entry.registered.id, null)\r\n layouts.setDraft(entry.registered.id, editing)\r\n }\r\n } catch (error) {\r\n setActionError(errorMessage(error))\r\n } finally {\r\n setBusy(false)\r\n }\r\n }\r\n\r\n return (\r\n <Box\r\n ref={rootRef}\r\n sx={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}\r\n >\r\n <Box\r\n sx={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 1,\r\n px: 1,\r\n py: 0.5,\r\n borderBottom: 1,\r\n borderColor: 'divider'\r\n }}\r\n >\r\n <SmallButton\r\n title={sidebar ? 'Recolher a lista' : 'Mostrar a lista'}\r\n onClick={toggleSidebar}\r\n >\r\n {sidebar ? '«' : '☰'}\r\n </SmallButton>\r\n <Typography noWrap sx={{ fontSize: 12, fontWeight: 700 }}>\r\n {stacked && sidebar ? `Layout ${layoutKey}` : selectedTitle}\r\n </Typography>\r\n </Box>\r\n <Box sx={{ flex: 1, minHeight: 0, display: 'flex' }}>\r\n {sidebar && (\r\n <Box\r\n sx={{\r\n overflow: 'auto',\r\n p: 1.5,\r\n ...(stacked\r\n ? { flex: 1 }\r\n : { width: 280, flexShrink: 0, borderRight: 1, borderColor: 'divider' })\r\n }}\r\n >\r\n {entries.length > 1 && (\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n label=\"Layout\"\r\n value={entry.registered.id}\r\n onChange={(e) => setLayoutId(e.target.value)}\r\n sx={{ ...inputSx, mb: 1.5 }}\r\n >\r\n {entries.map((item) => (\r\n <MenuItem key={item.registered.id} value={item.registered.id}>\r\n {item.registered.id}\r\n {item.draft ? ' · rascunho' : ''}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )}\r\n <Section title=\"Tela\" collapseKey=\"layout:lista:tela\">\r\n <ItemRow\r\n title={editing.canvas ? 'Tamanho fixo' : 'Responsiva'}\r\n subtitle={\r\n editing.canvas ? presetLabel(editing.canvas) : 'reorganiza conforme a largura'\r\n }\r\n selected={selection?.kind === 'canvas'}\r\n onSelect={() => {\r\n setSelection({ kind: 'canvas' })\r\n if (stacked) setSidebar(false)\r\n }}\r\n />\r\n <ItemRow\r\n title=\"Cards\"\r\n subtitle={cardsSummary(editing.cards)}\r\n selected={selection?.kind === 'cards'}\r\n onSelect={() => {\r\n setSelection({ kind: 'cards' })\r\n if (stacked) setSidebar(false)\r\n }}\r\n />\r\n </Section>\r\n <Section\r\n title={`Filtros (${filters.length})`}\r\n collapseKey=\"layout:lista:filtros\"\r\n actions={\r\n <Button\r\n size=\"small\"\r\n onClick={addFilter}\r\n disabled={filters.length >= Object.keys(model.dimensions).length}\r\n >\r\n + Novo\r\n </Button>\r\n }\r\n >\r\n {!filters.length && (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled', mb: 1 }}>\r\n Nenhum filtro no layout.\r\n </Typography>\r\n )}\r\n {filters.map((filter, index) => {\r\n const item: LayoutItem = { kind: 'filter', key: filter.dimension }\r\n return (\r\n <ItemRow\r\n key={filter.dimension}\r\n title={\r\n filter.label || model.dimensions[filter.dimension]?.label || filter.dimension\r\n }\r\n subtitle={`${filter.dimension}${filter.formatLabel ? ` · ${filter.formatLabel}` : ''}`}\r\n selected={selectedFilter?.dimension === filter.dimension}\r\n onSelect={() => focus(item)}\r\n onHover={(on) => hover(on ? item : null)}\r\n {...dragProps('filter', index, filters.length)}\r\n onRemove={() =>\r\n setFilters(filters.filter((other) => other.dimension !== filter.dimension))\r\n }\r\n />\r\n )\r\n })}\r\n </Section>\r\n <Section\r\n title={`Parâmetros (${parameters.length})`}\r\n collapseKey=\"layout:lista:parametros\"\r\n actions={\r\n <Button\r\n size=\"small\"\r\n onClick={addParameter}\r\n disabled={!Object.keys(model.measures).length}\r\n >\r\n + Novo\r\n </Button>\r\n }\r\n >\r\n {!parameters.length && (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled', mb: 1 }}>\r\n Nenhum parâmetro de medida.\r\n </Typography>\r\n )}\r\n {parameters.map((parameter, index) => {\r\n const item: LayoutItem = { kind: 'parameter', key: parameter.name }\r\n return (\r\n <ItemRow\r\n key={parameter.name}\r\n title={parameter.label || 'Medida'}\r\n subtitle={`${parameter.name} · ${parameter.measures.length} medida(s)`}\r\n selected={selectedParameter?.name === parameter.name}\r\n onSelect={() => focus(item)}\r\n onHover={(on) => hover(on ? item : null)}\r\n {...dragProps('parameter', index, parameters.length)}\r\n onRemove={() =>\r\n setParameters(parameters.filter((other) => other.name !== parameter.name))\r\n }\r\n />\r\n )\r\n })}\r\n </Section>\r\n <Section\r\n title={`Gráficos (${charts.length})`}\r\n collapseKey=\"layout:lista:graficos\"\r\n actions={\r\n <>\r\n <Button size=\"small\" onClick={(e) => setAddMenu(e.currentTarget)}>\r\n + Novo\r\n </Button>\r\n <Menu anchorEl={addMenu} open={!!addMenu} onClose={() => setAddMenu(null)}>\r\n {Object.entries(chartTypes).map(([type, { label }]) => (\r\n <MenuItem key={type} dense onClick={() => add(type)}>\r\n {label}\r\n </MenuItem>\r\n ))}\r\n </Menu>\r\n </>\r\n }\r\n >\r\n {charts.map((chart, index) => {\r\n const item: LayoutItem = { kind: 'chart', key: chart.id }\r\n return (\r\n <ItemRow\r\n key={chart.id}\r\n title={chart.title || '(sem título)'}\r\n subtitle={`${chartSummary(chart, chartTypes)} · ${chart.span ?? LAYOUT_COLUMNS}/${LAYOUT_COLUMNS}`}\r\n selected={chart.id === selected?.id}\r\n onSelect={() => focus(item)}\r\n onHover={(on) => hover(on ? item : null)}\r\n {...dragProps('chart', index, charts.length)}\r\n onDuplicate={() => add(chart.type, chart)}\r\n onRemove={() => setCharts(charts.filter((other) => other.id !== chart.id))}\r\n />\r\n )\r\n })}\r\n </Section>\r\n </Box>\r\n )}\r\n\r\n {!(stacked && sidebar) && (\r\n <Box ref={editorRef} sx={{ flex: 1, minWidth: 0, overflow: 'auto' }}>\r\n <Box sx={{ p: 1.5 }}>\r\n {entry.draft && (\r\n <Alert severity=\"warning\" sx={{ mb: 1.5 }}>\r\n Rascunho aplicado: a página mostra o layout editado, não o arquivo{' '}\r\n <code>{entry.registered.id}.json</code>.\r\n {capabilities?.saveLayout\r\n ? ' Use \"Salvar no arquivo\" quando terminar.'\r\n : ' Copie o JSON para o arquivo quando terminar.'}\r\n </Alert>\r\n )}\r\n {!!errors.length && (\r\n <Alert severity=\"error\" sx={{ mb: 1.5 }}>\r\n Layout inválido — as edições não foram aplicadas na página:\r\n {errors.map((error) => (\r\n <div key={error}>{error}</div>\r\n ))}\r\n </Alert>\r\n )}\r\n {!!warnings.length && (\r\n <Alert severity=\"warning\" sx={{ mb: 1.5 }}>\r\n {warnings.map((warning) => (\r\n <div key={warning}>{warning}</div>\r\n ))}\r\n </Alert>\r\n )}\r\n {actionError && (\r\n <Alert severity=\"error\" sx={{ mb: 1.5, fontFamily: MONO, fontSize: 12 }}>\r\n {actionError}\r\n </Alert>\r\n )}\r\n {selection?.kind === 'canvas' ? (\r\n <CanvasForm canvas={editing.canvas} columns={formColumns} onChange={setCanvas} />\r\n ) : selection?.kind === 'cards' ? (\r\n <>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary', mb: 1 }}>\r\n Estilo padrão dos cards de todos os gráficos; cada gráfico pode sobrepor na\r\n seção Card dele. Vazio = padrão do componente.\r\n </Typography>\r\n <FieldsForm\r\n fields={CARDS_FIELDS}\r\n values={cardsValues(editing.cards)}\r\n onSet={setCards}\r\n model={model}\r\n formatters={[]}\r\n columns={[]}\r\n formColumns={formColumns}\r\n chosenDimensions={[]}\r\n />\r\n </>\r\n ) : selectedFilter ? (\r\n <FilterForm\r\n key={`filter:${selectedFilter.dimension}`}\r\n filter={selectedFilter}\r\n model={model}\r\n formatters={entry.parts.filters ?? []}\r\n charts={editing.charts.map((chart) => ({\r\n name: chart.id,\r\n label: chart.title || chart.id\r\n }))}\r\n columns={formColumns}\r\n onChange={(change) => {\r\n patchFilter(selectedFilter.dimension, change)\r\n setSelection({ kind: 'filter', key: change(selectedFilter).dimension })\r\n }}\r\n />\r\n ) : selectedParameter ? (\r\n <ParameterForm\r\n key={`parameter:${selectedParameter.name}`}\r\n parameter={selectedParameter}\r\n model={model}\r\n columns={formColumns}\r\n onChange={(change) => {\r\n patchParameter(selectedParameter.name, change)\r\n setSelection({ kind: 'parameter', key: change(selectedParameter).name })\r\n }}\r\n />\r\n ) : selected ? (\r\n <ChartForm\r\n key={`chart:${selected.id}`}\r\n chart={selected}\r\n cards={editing.cards}\r\n types={chartTypes}\r\n model={model}\r\n formatters={entry.parts.charts ?? []}\r\n measureParameters={parameters.map((parameter) => ({\r\n name: parameter.name,\r\n label: parameter.label || 'Medida'\r\n }))}\r\n columns={formColumns}\r\n onChange={(change) => {\r\n patchChart(selected.id, change)\r\n setSelection({ kind: 'chart', key: change(selected).id })\r\n }}\r\n />\r\n ) : (\r\n <Empty>Escolha a tela, um filtro ou um gráfico, ou use \"+ Novo\".</Empty>\r\n )}\r\n </Box>\r\n </Box>\r\n )}\r\n </Box>\r\n\r\n <Box\r\n sx={{\r\n display: 'flex',\r\n flexWrap: 'wrap',\r\n gap: 1,\r\n justifyContent: 'flex-end',\r\n alignItems: 'center',\r\n px: 1.5,\r\n py: 1,\r\n borderTop: 1,\r\n borderColor: 'divider'\r\n }}\r\n >\r\n <Box sx={{ mr: 'auto', display: 'flex', alignItems: 'center', gap: 1 }}>\r\n <AutoApplySwitch applying={dirty && !errors.length} />\r\n {dirty && (!autoApply || !!errors.length) && (\r\n <Typography sx={{ fontSize: 12, color: 'warning.main' }}>\r\n {errors.length ? 'Edições com erro, não aplicadas' : 'Edições não aplicadas'}\r\n </Typography>\r\n )}\r\n </Box>\r\n {!autoApply && (\r\n <ConfirmButton\r\n size=\"small\"\r\n disabled={!dirty}\r\n onConfirm={() => setEditing(reference)}\r\n title=\"Desfaz as edições ainda não aplicadas\"\r\n confirmTitle=\"Desfazer as edições?\"\r\n confirmText=\"As edições ainda não aplicadas na página serão perdidas; o editor volta ao que a página mostra.\"\r\n confirmLabel=\"Desfazer\"\r\n >\r\n Desfazer\r\n </ConfirmButton>\r\n )}\r\n <ConfirmButton\r\n size=\"small\"\r\n color=\"warning\"\r\n disabled={!entry.draft}\r\n onConfirm={() => {\r\n devtools.store.expectRefetch()\r\n layouts.setPending(entry.registered.id, null)\r\n layouts.setDraft(entry.registered.id, null)\r\n setEditingState(entry.registered)\r\n }}\r\n title=\"Volta a página e o editor ao layout do arquivo\"\r\n confirmTitle=\"Descartar o rascunho?\"\r\n confirmText=\"O rascunho e as edições do editor serão perdidos; a página e o editor voltam ao layout do arquivo.\"\r\n confirmLabel=\"Descartar\"\r\n >\r\n Descartar rascunho\r\n </ConfirmButton>\r\n {capabilities?.saveLayout && (\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n disabled={!differsFromFile || !!errors.length || busy}\r\n onClick={() => saveFile('preview')}\r\n title={`Reescreve ${entry.registered.id}.json com o que está no editor`}\r\n >\r\n {busy ? 'Gerando…' : 'Salvar no arquivo'}\r\n </Button>\r\n )}\r\n {!autoApply && (\r\n <Button\r\n size=\"small\"\r\n variant=\"contained\"\r\n disabled={!dirty || !!errors.length}\r\n onClick={apply}\r\n title=\"Mostra as edições na página (sem gravar o arquivo)\"\r\n >\r\n Aplicar na página\r\n </Button>\r\n )}\r\n </Box>\r\n\r\n <Dialog open={!!save} onClose={() => setSave(null)} maxWidth=\"lg\" fullWidth>\r\n <DialogTitle>Salvar layout no arquivo</DialogTitle>\r\n <DialogContent>\r\n <Typography sx={{ fontFamily: MONO, fontSize: 12, mb: 1 }}>{save?.path}</Typography>\r\n {save?.warnings.map((warning) => (\r\n <Alert key={warning} severity=\"warning\" sx={{ mb: 1 }}>\r\n {warning}\r\n </Alert>\r\n ))}\r\n {save && <FileDiff lines={lineDiff(save.previous, save.content)} />}\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary', mt: 1 }}>\r\n O Next recarrega o JSON sozinho; o rascunho some quando a página receber o arquivo novo.\r\n </Typography>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => setSave(null)}>Cancelar</Button>\r\n <Button\r\n variant=\"contained\"\r\n disabled={!save || save.previous === save.content || busy}\r\n onClick={() => saveFile('write')}\r\n >\r\n Gravar\r\n </Button>\r\n </DialogActions>\r\n </Dialog>\r\n </Box>\r\n )\r\n}\r\n\r\nconst presetLabel = ({ width, height }: CanvasDef) => `${width}×${height ?? 'auto'}`\r\n\r\n/** Tamanho fixo da tela (`layout.canvas`): desligado = responsivo. */\r\nfunction CanvasForm({\r\n canvas,\r\n columns,\r\n onChange\r\n}: {\r\n canvas: CanvasDef | undefined\r\n columns: number\r\n onChange: (next: CanvasDef | undefined) => void\r\n}) {\r\n const preset = canvas && CANVAS_PRESETS.find((item) => presetLabel(item) === presetLabel(canvas))\r\n const number = (value: string) => (value === '' ? undefined : Number(value))\r\n return (\r\n <Section title=\"Tela\" collapseKey=\"layout:form:Tela\">\r\n <Box sx={formGrid(columns)}>\r\n <Box sx={{ gridColumn: '1 / -1' }}>\r\n {withHint(\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={!!canvas}\r\n onChange={(e) =>\r\n onChange(e.target.checked ? (CANVAS_PRESETS[0] as CanvasDef) : undefined)\r\n }\r\n />\r\n }\r\n label={<Typography sx={{ fontSize: 12 }}>Tamanho fixo</Typography>}\r\n />,\r\n 'Desenha o dashboard nesse tamanho e escala para caber na tela, mantendo a proporção, em vez de reorganizar os gráficos. A página precisa do <DashboardCanvas>.'\r\n )}\r\n </Box>\r\n {canvas && (\r\n <>\r\n {field(\r\n 'Predefinido',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={preset ? presetLabel(preset) : ''}\r\n onChange={(e) =>\r\n onChange(CANVAS_PRESETS.find((item) => presetLabel(item) === e.target.value))\r\n }\r\n sx={inputSx}\r\n >\r\n {CANVAS_PRESETS.map((item) => (\r\n <MenuItem key={presetLabel(item)} value={presetLabel(item)}>\r\n {presetLabel(item)}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )}\r\n {field(\r\n 'Largura',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n type=\"number\"\r\n value={canvas.width ?? ''}\r\n onChange={(e) => onChange(withField(canvas, 'width', number(e.target.value)))}\r\n sx={inputSx}\r\n />\r\n )}\r\n {field(\r\n 'Altura mín.',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n type=\"number\"\r\n value={canvas.height ?? ''}\r\n placeholder=\"auto\"\r\n onChange={(e) => onChange(withField(canvas, 'height', number(e.target.value)))}\r\n sx={inputSx}\r\n />\r\n )}\r\n </>\r\n )}\r\n </Box>\r\n </Section>\r\n )\r\n}\r\n\r\nfunction ItemRow({\r\n title,\r\n subtitle,\r\n selected,\r\n onSelect,\r\n onHover,\r\n onDuplicate,\r\n onRemove,\r\n dropBefore,\r\n dropAfter,\r\n onDragStart,\r\n onDragOver,\r\n onDrop,\r\n onDragEnd\r\n}: {\r\n title: string\r\n subtitle: string\r\n selected: boolean\r\n onSelect: () => void\r\n onHover?: (hovering: boolean) => void\r\n onDuplicate?: () => void\r\n /** Ausente = item fixo (a tela). */\r\n onRemove?: () => void\r\n /** Marca onde o item arrastado vai cair. */\r\n dropBefore?: boolean\r\n dropAfter?: boolean\r\n /** Presente = item arrastável. */\r\n onDragStart?: () => void\r\n onDragOver?: (e: DragEvent<HTMLElement>) => void\r\n onDrop?: () => void\r\n onDragEnd?: () => void\r\n}) {\r\n const marker = {\r\n content: '\"\"',\r\n position: 'absolute',\r\n left: 0,\r\n right: 0,\r\n height: 2,\r\n bgcolor: 'primary.main'\r\n }\r\n return (\r\n <Box\r\n onClick={onSelect}\r\n onMouseEnter={() => onHover?.(true)}\r\n onMouseLeave={() => onHover?.(false)}\r\n draggable={!!onDragStart}\r\n onDragStart={(e) => {\r\n if (!onDragStart) return\r\n e.dataTransfer.effectAllowed = 'move'\r\n // Firefox só arrasta com algum dado\r\n e.dataTransfer.setData('text/plain', title)\r\n onDragStart()\r\n }}\r\n onDragOver={onDragOver}\r\n onDrop={(e) => {\r\n e.preventDefault()\r\n onDrop?.()\r\n }}\r\n onDragEnd={onDragEnd}\r\n sx={{\r\n position: 'relative',\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.5,\r\n px: 1,\r\n py: 0.5,\r\n mb: 0.5,\r\n borderRadius: 1,\r\n cursor: onDragStart ? 'grab' : 'pointer',\r\n border: 1,\r\n borderColor: selected ? 'primary.main' : 'divider',\r\n '&:hover .item-actions': { visibility: 'visible' },\r\n '&::before': dropBefore ? { ...marker, top: -4 } : undefined,\r\n '&::after': dropAfter ? { ...marker, bottom: -4 } : undefined\r\n }}\r\n >\r\n {onDragStart && (\r\n <Box\r\n component=\"span\"\r\n aria-hidden\r\n sx={{ color: 'text.disabled', fontSize: 12, lineHeight: 1, userSelect: 'none' }}\r\n >\r\n ⋮⋮\r\n </Box>\r\n )}\r\n <Box sx={{ minWidth: 0, flex: 1 }}>\r\n <Typography noWrap sx={{ fontSize: 12, fontWeight: 700 }}>\r\n {title}\r\n </Typography>\r\n <Typography noWrap sx={{ fontSize: 11, color: 'text.secondary', fontFamily: MONO }}>\r\n {subtitle}\r\n </Typography>\r\n </Box>\r\n {(onDuplicate || onRemove) && (\r\n <Box\r\n className=\"item-actions\"\r\n onClick={(e) => e.stopPropagation()}\r\n sx={{ display: 'flex', visibility: selected ? 'visible' : 'hidden' }}\r\n >\r\n {onDuplicate && (\r\n <SmallButton title=\"Duplicar\" onClick={onDuplicate}>\r\n ⧉\r\n </SmallButton>\r\n )}\r\n {onRemove && (\r\n <SmallButton title=\"Remover\" onClick={onRemove}>\r\n ×\r\n </SmallButton>\r\n )}\r\n </Box>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\nfunction SmallButton({\r\n title,\r\n disabled,\r\n onClick,\r\n children\r\n}: {\r\n title: string\r\n disabled?: boolean\r\n onClick: () => void\r\n children: ReactNode\r\n}) {\r\n return (\r\n <Tooltip title={title}>\r\n <span>\r\n <IconButton\r\n size=\"small\"\r\n disabled={disabled}\r\n onClick={onClick}\r\n aria-label={title}\r\n sx={{ p: 0.25, fontSize: 13 }}\r\n >\r\n {children}\r\n </IconButton>\r\n </span>\r\n </Tooltip>\r\n )\r\n}\r\n\r\nfunction ChartForm({\r\n chart,\r\n cards,\r\n types,\r\n model,\r\n formatters,\r\n measureParameters,\r\n columns,\r\n onChange\r\n}: {\r\n chart: ChartDef\r\n /** Estilo padrão dos cards do layout (placeholder da seção Card). */\r\n cards: CardsStyle | undefined\r\n types: ChartTypes\r\n model: ModelDef\r\n formatters: string[]\r\n /** Parâmetros de medida do layout (campo `measureParameter`): `{ name, label }`. */\r\n measureParameters: Option[]\r\n /** Colunas do formulário (encolhe com a largura do devtools). */\r\n columns: number\r\n onChange: (change: (chart: ChartDef) => ChartDef) => void\r\n}) {\r\n const set = (key: string, value: unknown) =>\r\n onChange((current) => withField(current as Record<string, unknown>, key, value) as ChartDef)\r\n // Vários campos numa mudança só (ex.: dimensões, medidas e a ordem das colunas juntas)\r\n const setMany = (changes: Record<string, unknown>) =>\r\n onChange(\r\n (current) =>\r\n Object.entries(changes).reduce(\r\n (chart, [key, value]) => withField(chart, key, value),\r\n current as Record<string, unknown>\r\n ) as ChartDef\r\n )\r\n const setCard = (key: string, value: unknown) =>\r\n onChange((current) =>\r\n withField(\r\n current,\r\n 'card',\r\n nonEmpty(withField((current.card ?? {}) as Record<string, unknown>, key, value))\r\n )\r\n )\r\n return (\r\n <>\r\n <FieldsForm\r\n fields={types[chart.type]?.fields ?? {}}\r\n values={chart as unknown as Record<string, unknown>}\r\n onSet={set}\r\n onSetMany={setMany}\r\n model={model}\r\n formatters={formatters}\r\n measureParameters={measureParameters}\r\n columns={chartColumns(chart, types)}\r\n formColumns={columns}\r\n chosenDimensions={chartReferences(chart, types).dimensions}\r\n chosenMeasures={chartReferences(chart, types).measures}\r\n header={\r\n <>\r\n {field(\r\n 'Tipo',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={chart.type}\r\n // Troca de tipo: mantém id, título, largura e o que der de dimensões/medidas\r\n onChange={(e) =>\r\n onChange((current) => chartOfType(e.target.value, model, current, types))\r\n }\r\n sx={inputSx}\r\n >\r\n {Object.entries(types).map(([type, { label }]) => (\r\n <MenuItem key={type} value={type}>\r\n {label}\r\n </MenuItem>\r\n ))}\r\n {!types[chart.type] && (\r\n <MenuItem value={chart.type} disabled>\r\n {chart.type} (não registrado)\r\n </MenuItem>\r\n )}\r\n </TextField>\r\n )}\r\n {field(\r\n 'id',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={chart.id}\r\n error={!/^[A-Za-z0-9_-]{1,80}$/.test(chart.id)}\r\n onChange={(e) => set('id', e.target.value)}\r\n sx={inputSx}\r\n />,\r\n 'Identificador no JSON (letras, números, \"-\" e \"_\")'\r\n )}\r\n </>\r\n }\r\n />\r\n <FieldsForm\r\n fields={chartCardFields(cards)}\r\n values={(chart.card ?? {}) as Record<string, unknown>}\r\n onSet={setCard}\r\n model={model}\r\n formatters={[]}\r\n columns={[]}\r\n formColumns={columns}\r\n chosenDimensions={[]}\r\n sectionActions={{\r\n Card: (\r\n <Button\r\n size=\"small\"\r\n disabled={!chart.card || !Object.keys(chart.card).length}\r\n onClick={() => onChange((current) => withField(current, 'card', undefined) as ChartDef)}\r\n >\r\n Usar valor padrão\r\n </Button>\r\n )\r\n }}\r\n />\r\n </>\r\n )\r\n}\r\n\r\nfunction FilterForm({\r\n filter,\r\n model,\r\n formatters,\r\n charts,\r\n columns,\r\n onChange\r\n}: {\r\n filter: FilterDef\r\n model: ModelDef\r\n formatters: string[]\r\n /** Gráficos do layout para o campo `ignoredBy`: `{ name: id, label: título }`. */\r\n charts: Option[]\r\n columns: number\r\n onChange: (change: (filter: FilterDef) => FilterDef) => void\r\n}) {\r\n return (\r\n <FieldsForm\r\n fields={FILTER_FIELDS}\r\n values={filter as unknown as Record<string, unknown>}\r\n onSet={(key, value) =>\r\n onChange(\r\n (current) => withField(current as Record<string, unknown>, key, value) as FilterDef\r\n )\r\n }\r\n model={model}\r\n formatters={formatters}\r\n charts={charts}\r\n columns={[]}\r\n formColumns={columns}\r\n chosenDimensions={[filter.dimension]}\r\n />\r\n )\r\n}\r\n\r\nfunction ParameterForm({\r\n parameter,\r\n model,\r\n columns,\r\n onChange\r\n}: {\r\n parameter: ParameterDef\r\n model: ModelDef\r\n columns: number\r\n onChange: (change: (parameter: ParameterDef) => ParameterDef) => void\r\n}) {\r\n return (\r\n <FieldsForm\r\n fields={PARAMETER_FIELDS}\r\n values={parameter as unknown as Record<string, unknown>}\r\n onSet={(key, value) =>\r\n onChange(\r\n (current) => withField(current as Record<string, unknown>, key, value) as ParameterDef\r\n )\r\n }\r\n model={model}\r\n formatters={[]}\r\n // O campo `default` (kind `column`) lista as medidas escolhidas no próprio parâmetro\r\n columns={parameter.measures}\r\n formColumns={columns}\r\n chosenDimensions={[]}\r\n />\r\n )\r\n}\r\n\r\n/** Formulário gerado dos `FieldSpec` (campos do tipo de gráfico ou do filtro). */\r\nfunction FieldsForm({\r\n fields,\r\n values,\r\n onSet: set,\r\n onSetMany,\r\n model,\r\n formatters,\r\n columns,\r\n formColumns,\r\n chosenDimensions,\r\n chosenMeasures = [],\r\n charts = [],\r\n measureParameters = [],\r\n sectionActions,\r\n header\r\n}: {\r\n fields: Record<string, FieldSpec>\r\n values: Record<string, unknown>\r\n onSet: (key: string, value: unknown) => void\r\n /** Vários campos numa mudança só (sem ele, um `onSet` por campo). */\r\n onSetMany?: (changes: Record<string, unknown>) => void\r\n model: ModelDef\r\n formatters: string[]\r\n /** Opções dos campos `column` (ex.: `sortBy`). */\r\n columns: string[]\r\n formColumns: number\r\n /** Dimensões já escolhidas (campos `formatters`). */\r\n chosenDimensions: string[]\r\n /** Medidas já escolhidas (campos `formats`). */\r\n chosenMeasures?: string[]\r\n /** Gráficos do layout (campos `charts`, ex.: `ignoredBy` do filtro): `{ name: id, label: título }`. */\r\n charts?: Option[]\r\n /** Parâmetros de medida do layout (campos `parameter`): `{ name, label }`. */\r\n measureParameters?: Option[]\r\n /** Botões ao lado do título de uma seção (ex.: \"Usar valor padrão\" na seção Card). */\r\n sectionActions?: Partial<Record<string, ReactNode>>\r\n /** Campos fixos no começo da primeira seção (tipo, id). */\r\n header?: ReactNode\r\n}) {\r\n const dimensions = Object.entries(model.dimensions).map(([name, dim]) => ({\r\n name,\r\n label: dim.label\r\n }))\r\n const measures = Object.entries(model.measures).map(([name, measure]) => ({\r\n name,\r\n label: measure.label\r\n }))\r\n const entries = Object.entries(fields)\r\n const columnLabel = (name: string) =>\r\n name.startsWith(PERCENT_PREFIX)\r\n ? `% ${fieldLabelOf(model, name.slice(PERCENT_PREFIX.length))}`\r\n : fieldLabelOf(model, name)\r\n const columnOptionsOf = (names: string[]): Option[] =>\r\n names.map((name) => ({ name, label: columnLabel(name) }))\r\n // Colunas do gráfico e, agrupadas depois, o resto do modelo (campos `column` com `outside`, regras)\r\n const fieldOptions: Option[] = [\r\n ...columnOptionsOf(columns).map((option) => ({ ...option, group: 'Colunas do gráfico' })),\r\n ...dimensions\r\n .filter((option) => !columns.includes(option.name))\r\n .map((option) => ({ ...option, group: 'Dimensões fora do gráfico' })),\r\n ...measures\r\n .filter((option) => !columns.includes(option.name))\r\n .map((option) => ({ ...option, group: 'Medidas fora do gráfico' }))\r\n ]\r\n\r\n // Opções de cada dimensão/medida (rótulo, formato, formatter) num ícone à direita do campo, em vez\r\n // de campos soltos. Vale quando o tipo tem `labels` ou `formats`.\r\n const keyOf = (kind: FieldSpec['kind']) => entries.find(([, spec]) => spec.kind === kind)?.[0]\r\n const labelsKey = keyOf('labels')\r\n const formatsKey = keyOf('formats')\r\n const alignsKey = keyOf('aligns')\r\n const verticalKey = keyOf('verticalAligns')\r\n const columnOptions = !!(labelsKey || formatsKey || alignsKey || verticalKey)\r\n const formattersKey = columnOptions ? keyOf('formatters') : undefined\r\n // `formatter` avulso só é da dimensão quando há uma dimensão e um formatter no tipo\r\n const single = (kind: FieldSpec['kind']) => entries.filter(([, spec]) => spec.kind === kind)\r\n const formatterKey =\r\n columnOptions && single('dimension').length === 1 && single('formatter').length === 1\r\n ? single('formatter')[0]?.[0]\r\n : undefined\r\n // Ou o formatter diz de qual campo `dimension` é (`of`), como na série do gráfico de barras\r\n const formatterOf = (fieldKey: string | undefined) =>\r\n (columnOptions &&\r\n fieldKey &&\r\n entries.find(([, spec]) => spec.kind === 'formatter' && spec.of === fieldKey)?.[0]) ||\r\n formatterKey\r\n const pairedFormatters = columnOptions\r\n ? entries.filter(([, spec]) => spec.kind === 'formatter' && spec.of).map(([key]) => key)\r\n : []\r\n const labels = (labelsKey && (values[labelsKey] as Record<string, string>)) || {}\r\n const formats = (formatsKey && (values[formatsKey] as Record<string, ChartNumberFormat>)) || {}\r\n const aligns = (alignsKey && (values[alignsKey] as Record<string, ColumnAlign>)) || {}\r\n const verticals =\r\n (verticalKey && (values[verticalKey] as Record<string, ColumnVerticalAlign>)) || {}\r\n // Alinhamentos de uma coluna (chave `%:medida` no percentual)\r\n const alignProps = (column: string, defaultAlign: ColumnAlign) => ({\r\n align: alignsKey ? (aligns[column] ?? '') : undefined,\r\n defaultAlign,\r\n onAlign: (next: ColumnAlign | undefined) =>\r\n alignsKey && set(alignsKey, pruned(withField(aligns, column, next), columns)),\r\n verticalAlign: verticalKey ? (verticals[column] ?? '') : undefined,\r\n onVerticalAlign: (next: ColumnVerticalAlign | undefined) =>\r\n verticalKey && set(verticalKey, pruned(withField(verticals, column, next), columns))\r\n })\r\n const resetAligns = (column: string, changes: Record<string, unknown>) => {\r\n if (alignsKey) changes[alignsKey] = pruned(withField(aligns, column, undefined), columns)\r\n if (verticalKey) changes[verticalKey] = pruned(withField(verticals, column, undefined), columns)\r\n }\r\n const setChanges = (changes: Record<string, unknown>) => {\r\n if (onSetMany) onSetMany(changes)\r\n else for (const [key, value] of Object.entries(changes)) set(key, value)\r\n }\r\n const dimensionFormatters =\r\n (formattersKey && (values[formattersKey] as Record<string, string>)) || {}\r\n\r\n const optionsButton = (kind: ColumnKind, name: string | undefined, fieldKey?: string) => {\r\n if (!columnOptions || !name) return null\r\n const formatterKey = formatterOf(fieldKey)\r\n // Percentual: só o alinhamento (a chave da coluna é `%:medida`)\r\n if (kind === 'percent') {\r\n if (!alignsKey && !verticalKey) return null\r\n const column = percentColumn(name)\r\n return (\r\n <ColumnOptions\r\n kind={kind}\r\n name={name}\r\n model={model}\r\n label={undefined}\r\n onLabel={() => {}}\r\n format={undefined}\r\n onFormat={() => {}}\r\n formatter={undefined}\r\n formatters={formatters}\r\n onFormatter={() => {}}\r\n {...alignProps(column, 'right')}\r\n onReset={() => {\r\n const changes: Record<string, unknown> = {}\r\n resetAligns(column, changes)\r\n setChanges(changes)\r\n }}\r\n />\r\n )\r\n }\r\n const canFormatter = kind === 'dimension' && !!(formattersKey || formatterKey)\r\n return (\r\n <ColumnOptions\r\n kind={kind}\r\n name={name}\r\n model={model}\r\n {...alignProps(name, kind === 'dimension' ? 'left' : 'right')}\r\n label={labelsKey ? (labels[name] ?? '') : undefined}\r\n onLabel={(text) =>\r\n labelsKey && set(labelsKey, pruned(withField(labels, name, text), columns))\r\n }\r\n format={kind === 'measure' && formatsKey ? (formats[name] ?? {}) : undefined}\r\n onFormat={(format) => {\r\n if (!formatsKey) return\r\n const map = { ...formats }\r\n if (Object.keys(format).length) map[name] = format\r\n else delete map[name]\r\n set(formatsKey, pruned(map, chosenMeasures))\r\n }}\r\n formatter={\r\n !canFormatter\r\n ? undefined\r\n : formattersKey\r\n ? (dimensionFormatters[name] ?? '')\r\n : ((formatterKey && (values[formatterKey] as string)) ?? '')\r\n }\r\n formatters={formatters}\r\n onFormatter={(formatter) => {\r\n if (formattersKey)\r\n set(\r\n formattersKey,\r\n pruned(withField(dimensionFormatters, name, formatter), chosenDimensions)\r\n )\r\n else if (formatterKey) set(formatterKey, formatter || undefined)\r\n }}\r\n onReset={() => {\r\n // Uma mudança só: chamadas seguidas de `set` partiriam do mesmo estado\r\n const changes: Record<string, unknown> = {}\r\n if (labelsKey) changes[labelsKey] = pruned(withField(labels, name, undefined), columns)\r\n resetAligns(name, changes)\r\n if (formatsKey && kind === 'measure')\r\n changes[formatsKey] = pruned(withField(formats, name, undefined), chosenMeasures)\r\n if (canFormatter && formattersKey)\r\n changes[formattersKey] = pruned(\r\n withField(dimensionFormatters, name, undefined),\r\n chosenDimensions\r\n )\r\n else if (canFormatter && formatterKey) changes[formatterKey] = undefined\r\n if (onSetMany) onSetMany(changes)\r\n else for (const [key, value] of Object.entries(changes)) set(key, value)\r\n }}\r\n />\r\n )\r\n }\r\n\r\n // Dimensões e medidas da mesma seção viram uma lista só, com um adicionar para os dois; com um\r\n // campo `columnOrder` no tipo, a ordem pode misturar (medida antes de dimensão)\r\n const merged = (() => {\r\n for (const [dimensionsKey, spec] of entries) {\r\n if (spec.kind !== 'dimensions') continue\r\n const pair = entries.find(\r\n ([, other]) => other.kind === 'measures' && !other.percent && other.section === spec.section\r\n )\r\n if (!pair) continue\r\n const order = entries.find(([, other]) => other.kind === 'columnOrder')?.[0]\r\n // Com a ordem no tipo, o % do total também entra na lista (posicionável como as colunas)\r\n const percents = order\r\n ? entries.find(\r\n ([, other]) =>\r\n other.kind === 'measures' && other.percent && other.section === spec.section\r\n )\r\n : undefined\r\n return {\r\n dimensions: dimensionsKey,\r\n dimensionsSpec: spec,\r\n measures: pair[0],\r\n measuresSpec: pair[1],\r\n percents: percents?.[0],\r\n percentsSpec: percents?.[1],\r\n order\r\n }\r\n }\r\n return undefined\r\n })()\r\n\r\n const mergedInput = (pair: NonNullable<typeof merged>) => {\r\n const dimensionNames = (values[pair.dimensions] as string[] | undefined) ?? []\r\n const measureNames = (values[pair.measures] as string[] | undefined) ?? []\r\n const percentNames = pair.percents\r\n ? ((values[pair.percents] as string[] | undefined) ?? [])\r\n : []\r\n const all: ColumnItem[] = [\r\n ...dimensionNames.map((name) => ({ kind: 'dimension' as const, name })),\r\n ...measureNames.map((name) => ({ kind: 'measure' as const, name })),\r\n ...percentNames.map((name) => ({ kind: 'percent' as const, name }))\r\n ]\r\n const order = pair.order ? (values[pair.order] as string[] | undefined) : undefined\r\n const sortedColumns = tableColumns([...dimensionNames, ...measureNames], percentNames, order)\r\n // Nome repetido entre dimensão e medida: cada item é usado uma vez só\r\n const pool = [...all]\r\n const items = sortedColumns.map((column) => {\r\n const index = pool.findIndex((item) => itemColumn(item) === column)\r\n return pool.splice(index, 1)[0] as ColumnItem\r\n })\r\n const required = !!pair.dimensionsSpec.required || !!pair.measuresSpec.required\r\n return (\r\n <ColumnList\r\n items={items}\r\n options={{\r\n dimension: options(pair.dimensionsSpec),\r\n measure: options(pair.measuresSpec),\r\n ...(pair.percentsSpec && { percent: options(pair.percentsSpec) })\r\n }}\r\n extra={(item) => optionsButton(item.kind, item.name)}\r\n error={\r\n (!!pair.measuresSpec.required && !measureNames.length) ||\r\n (!!pair.dimensionsSpec.required && !dimensionNames.length) ||\r\n (required && !items.length)\r\n }\r\n onChange={(next) => {\r\n const dimensionList = next.filter((item) => item.kind === 'dimension')\r\n const measureList = next.filter((item) => item.kind === 'measure')\r\n const percentList = next.filter((item) => item.kind === 'percent').map((i) => i.name)\r\n const names = next.map(itemColumn)\r\n const standard = tableColumns(\r\n [...dimensionList, ...measureList].map((item) => item.name),\r\n percentList\r\n )\r\n const changes: Record<string, unknown> = {\r\n [pair.dimensions]:\r\n dimensionList.length || pair.dimensionsSpec.required\r\n ? dimensionList.map((item) => item.name)\r\n : undefined,\r\n [pair.measures]:\r\n measureList.length || pair.measuresSpec.required\r\n ? measureList.map((item) => item.name)\r\n : undefined\r\n }\r\n if (pair.percents) changes[pair.percents] = percentList.length ? percentList : undefined\r\n // Ordem padrão (dimensões, medidas, cada % depois da medida) não precisa ir para o JSON\r\n if (pair.order)\r\n changes[pair.order] =\r\n names.join('\\u0000') === standard.join('\\u0000') ? undefined : names\r\n if (onSetMany) onSetMany(changes)\r\n else for (const [key, value] of Object.entries(changes)) set(key, value)\r\n }}\r\n />\r\n )\r\n }\r\n\r\n const options = (spec: FieldSpec): Option[] => {\r\n switch (spec.kind) {\r\n case 'dimension':\r\n case 'dimensions':\r\n return dimensions\r\n case 'measure':\r\n case 'measures':\r\n return measures\r\n case 'filters':\r\n return dimensions\r\n case 'charts':\r\n return charts\r\n case 'parameter':\r\n return measureParameters\r\n case 'formatter':\r\n return formatters.map((name) => ({ name }))\r\n case 'column':\r\n return spec.outside ? fieldOptions : columnOptionsOf(columns)\r\n case 'enum':\r\n return spec.values.map((name) => ({ name, label: spec.labels?.[name] }))\r\n default:\r\n return []\r\n }\r\n }\r\n\r\n const input = (key: string, spec: FieldSpec): ReactNode => {\r\n const value = values[key]\r\n switch (spec.kind) {\r\n case 'text':\r\n return (\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={(value as string | undefined) ?? ''}\r\n placeholder={labelPlaceholder(key, values, model)}\r\n onChange={(e) => set(key, e.target.value)}\r\n sx={inputSx}\r\n />\r\n )\r\n case 'color':\r\n return (\r\n <ColorInput\r\n value={value as string | undefined}\r\n fallback={spec.default as string}\r\n onCommit={(color) => set(key, color)}\r\n />\r\n )\r\n case 'boolean': {\r\n const fallback = spec.default as boolean\r\n return (\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={(value as boolean | undefined) ?? fallback}\r\n // Igual ao padrão do componente: sai do JSON\r\n onChange={(e) =>\r\n set(key, e.target.checked === fallback ? undefined : e.target.checked)\r\n }\r\n />\r\n }\r\n label={<Typography sx={{ fontSize: 12 }}>{spec.label}</Typography>}\r\n />\r\n )\r\n }\r\n case 'integer':\r\n // Largura: lista fechada, mais rápida que digitar\r\n if (key === 'span')\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={(value as number | undefined) ?? spec.default}\r\n onChange={(e) => {\r\n const span = Number(e.target.value)\r\n set(key, span === spec.default ? undefined : span)\r\n }}\r\n sx={inputSx}\r\n >\r\n {Array.from({ length: spec.max }, (_, i) => i + 1).map((span) => (\r\n <MenuItem key={span} value={span}>\r\n {span}/{spec.max}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )\r\n return (\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n type=\"number\"\r\n value={(value as number | undefined) ?? ''}\r\n placeholder={spec.default === undefined ? '' : String(spec.default)}\r\n error={\r\n typeof value === 'number' &&\r\n (!Number.isInteger(value) || value < spec.min || value > spec.max)\r\n }\r\n onChange={(e) =>\r\n set(key, e.target.value.trim() === '' ? undefined : Number(e.target.value))\r\n }\r\n sx={inputSx}\r\n />\r\n )\r\n case 'dimensions':\r\n case 'measures': {\r\n const kind = spec.kind === 'dimensions' ? 'dimension' : 'measure'\r\n if (merged?.dimensions === key) return mergedInput(merged)\r\n const names = (value as string[] | undefined) ?? []\r\n return (\r\n <ColumnList\r\n items={names.map((name) => ({ kind, name }))}\r\n options={{ [kind]: options(spec) }}\r\n extra={(item) => optionsButton(item.kind, item.name)}\r\n error={!!spec.required && !names.length}\r\n onChange={(next) => {\r\n const list = next.map((item) => item.name)\r\n set(key, list.length || spec.required ? list : undefined)\r\n }}\r\n />\r\n )\r\n }\r\n case 'filters': {\r\n const names = (value as string[] | undefined) ?? []\r\n return (\r\n <ColumnList\r\n items={names.map((name) => ({ kind: 'dimension', name }))}\r\n options={{ dimension: options(spec) }}\r\n onChange={(next) => {\r\n const list = next.map((item) => item.name)\r\n set(key, list.length ? list : undefined)\r\n }}\r\n />\r\n )\r\n }\r\n case 'charts': {\r\n const names = (value as string[] | undefined) ?? []\r\n return (\r\n <ColumnList\r\n items={names.map((name) => ({ kind: 'chart', name }))}\r\n options={{ chart: options(spec) }}\r\n onChange={(next) => {\r\n const list = next.map((item) => item.name)\r\n set(key, list.length ? list : undefined)\r\n }}\r\n />\r\n )\r\n }\r\n case 'valueRule':\r\n return (\r\n <ValueRuleInput\r\n rule={value as ValueRule | undefined}\r\n label={spec.label}\r\n onChange={(rule) => set(key, rule)}\r\n />\r\n )\r\n case 'colors':\r\n return (\r\n <ColorsInput\r\n colors={(value as Record<string, string> | undefined) ?? {}}\r\n // Com a dimensão de valores preenchida (a série), as chaves são valores digitados\r\n measures={spec.values && values[spec.values] ? null : chosenMeasures}\r\n onChange={(next) => set(key, Object.keys(next).length ? next : undefined)}\r\n />\r\n )\r\n case 'formatRules':\r\n return (\r\n <FormatRulesInput\r\n rules={(value as FormatRule[] | undefined) ?? []}\r\n fieldOptions={fieldOptions}\r\n columnOptions={columnOptionsOf(columns)}\r\n model={model}\r\n onChange={(rules) => set(key, rules.length ? rules : undefined)}\r\n />\r\n )\r\n case 'colorScales':\r\n return (\r\n <ColorScalesInput\r\n scales={(value as ColorScale[] | undefined) ?? []}\r\n // Escala só faz sentido em número: fora as dimensões de texto\r\n columnOptions={columnOptionsOf(\r\n columns.filter((name) => model.dimensions[name]?.type !== 'string')\r\n )}\r\n onChange={(scales) => set(key, scales.length ? scales : undefined)}\r\n />\r\n )\r\n case 'formatters': {\r\n const map = (value as Record<string, string> | undefined) ?? {}\r\n if (!chosenDimensions.length)\r\n return (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled' }}>sem dimensões</Typography>\r\n )\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>\r\n {chosenDimensions.map((dimension) => (\r\n <Box key={dimension} sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>\r\n <Typography sx={{ fontFamily: MONO, fontSize: 12, minWidth: 90 }}>\r\n {dimension}\r\n </Typography>\r\n <NameSelect\r\n value={map[dimension] ?? ''}\r\n options={formatters.map((name) => ({ name }))}\r\n onChange={(name) => {\r\n const next = withField(map, dimension, name)\r\n set(key, Object.keys(next).length ? next : undefined)\r\n }}\r\n />\r\n </Box>\r\n ))}\r\n </Box>\r\n )\r\n }\r\n default: {\r\n const select = (\r\n <NameSelect\r\n value={(value as string | undefined) ?? ''}\r\n options={options(spec)}\r\n required={spec.required}\r\n emptyLabel={\r\n spec.kind === 'enum' && spec.default\r\n ? `padrão (${spec.labels?.[spec.default as string] ?? spec.default})`\r\n : undefined\r\n }\r\n onChange={(name) => set(key, name === spec.default ? undefined : name)}\r\n />\r\n )\r\n const button =\r\n spec.kind === 'dimension' || spec.kind === 'measure'\r\n ? optionsButton(spec.kind, value as string | undefined, key)\r\n : null\r\n return button ? (\r\n <Box sx={{ display: 'flex', gap: 0.25, alignItems: 'center' }}>\r\n {select}\r\n {button}\r\n </Box>\r\n ) : (\r\n select\r\n )\r\n }\r\n }\r\n }\r\n\r\n // Campos que não aparecem sozinhos: as medidas do par e a ordem (editadas na lista junta) e os\r\n // rótulos/formatos/formatters (no ícone de cada coluna)\r\n const hidden = new Set(\r\n [\r\n merged?.measures,\r\n merged?.percents,\r\n ...entries.filter(([, spec]) => spec.kind === 'columnOrder').map(([key]) => key),\r\n labelsKey,\r\n formatsKey,\r\n alignsKey,\r\n verticalKey,\r\n formattersKey,\r\n formatterKey,\r\n ...pairedFormatters\r\n ].filter(Boolean)\r\n )\r\n // Seções na ordem em que aparecem nos campos (só as que têm campo visível)\r\n const sections = [\r\n ...new Set(entries.filter(([key]) => !hidden.has(key)).map(([, spec]) => spec.section))\r\n ]\r\n // Listas (dimensões/medidas) ocupam a linha toda: uma embaixo da outra, nunca lado a lado\r\n const fullRow = (spec: FieldSpec) =>\r\n spec.kind === 'dimensions' ||\r\n spec.kind === 'measures' ||\r\n spec.kind === 'filters' ||\r\n spec.kind === 'charts' ||\r\n spec.kind === 'formatters' ||\r\n spec.kind === 'formatRules' ||\r\n spec.kind === 'colorScales' ||\r\n spec.kind === 'colors' ||\r\n spec.kind === 'valueRule'\r\n const gridColumn = (spec: FieldSpec, key: string) =>\r\n fullRow(spec) ? '1 / -1' : key === 'title' && formColumns > 1 ? 'span 2' : undefined\r\n\r\n return (\r\n <>\r\n {sections.map((section) => {\r\n const inSection = entries.filter(([, spec]) => spec.section === section)\r\n return (\r\n <Section\r\n key={section}\r\n title={section}\r\n collapseKey={`layout:form:${section}`}\r\n actions={sectionActions?.[section]}\r\n >\r\n <Box sx={formGrid(formColumns)}>\r\n {section === sections[0] && header}\r\n {inSection\r\n .filter(([key]) => !hidden.has(key))\r\n .map(([key, spec]) => (\r\n <Box\r\n key={key}\r\n sx={{\r\n gridColumn: gridColumn(spec, key),\r\n alignSelf: spec.kind === 'boolean' ? 'end' : undefined\r\n }}\r\n >\r\n {spec.kind === 'boolean' || spec.kind === 'valueRule'\r\n ? withHint(input(key, spec), spec.hint)\r\n : merged?.dimensions === key\r\n ? field(\r\n merged.percents ? 'Dimensões, medidas e %' : 'Dimensões e medidas',\r\n input(key, spec),\r\n `${merged.order ? 'Em qualquer ordem: é a ordem das colunas. ' : ''}${[spec.hint, merged.measuresSpec.hint, merged.percentsSpec?.hint && `% do total: ${merged.percentsSpec.hint}`].filter(Boolean).join(' · ')}`\r\n )\r\n : field(spec.label, input(key, spec), spec.hint)}\r\n </Box>\r\n ))}\r\n </Box>\r\n </Section>\r\n )\r\n })}\r\n </>\r\n )\r\n}\r\n\r\n/** `group`: subtítulo da lista (opções do mesmo grupo vêm juntas). */\r\ntype Option = { name: string; label?: string; group?: string }\r\n\r\nconst fieldLabelOf = (model: ModelDef, name: string) =>\r\n model.dimensions[name]?.label ?? model.measures[name]?.label ?? name\r\n\r\n/** Exemplo de célula com o estilo de uma regra. */\r\nconst RULE_SAMPLE = 'Exemplo'\r\n\r\nconst DEFAULT_RULE_BACKGROUND = '#ffe3e3'\r\n\r\n/**\r\n * Regras de formatação condicional, uma por cartão: \"se <campo> <operador> <valor>, pinta <a célula\r\n * de uma coluna | a linha toda> com <texto, fundo, negrito>\". A ordem importa (a de baixo ganha):\r\n * reordena com ↑/↓.\r\n */\r\nfunction FormatRulesInput({\r\n rules,\r\n fieldOptions,\r\n columnOptions,\r\n model,\r\n onChange\r\n}: {\r\n rules: FormatRule[]\r\n fieldOptions: Option[]\r\n columnOptions: Option[]\r\n model: ModelDef\r\n onChange: (rules: FormatRule[]) => void\r\n}) {\r\n const update = (index: number, change: (rule: FormatRule) => FormatRule) =>\r\n onChange(rules.map((rule, i) => (i === index ? change(rule) : rule)))\r\n const columns = columnOptions.map((option) => option.name)\r\n // Texto digitado -> valor da regra: número quando o operador ou o campo pedem\r\n const parseValue = (rule: FormatRule, text: string): number | string | undefined => {\r\n const trimmed = text.trim()\r\n if (!trimmed) return undefined\r\n const number = Number(trimmed.replace(',', '.'))\r\n if (NUMERIC_OPERATORS.includes(rule.operator))\r\n return Number.isFinite(number) ? number : undefined\r\n if (rule.operator === 'contains') return trimmed\r\n const textField = model.dimensions[rule.field]?.type === 'string'\r\n return !textField && Number.isFinite(number) ? number : trimmed\r\n }\r\n const withOperator = (rule: FormatRule, operator: RuleOperator): FormatRule => {\r\n const { value, to, ...rest } = rule\r\n if (UNARY_OPERATORS.includes(operator)) return { ...rest, operator }\r\n const numeric = NUMERIC_OPERATORS.includes(operator)\r\n const next: FormatRule = {\r\n ...rest,\r\n operator,\r\n value: numeric ? (Number.isFinite(Number(value)) ? Number(value) : 0) : (value ?? '')\r\n }\r\n if (operator === 'between') next.to = to ?? (next.value as number)\r\n return next\r\n }\r\n\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.75, maxWidth: 760 }}>\r\n {rules.map((rule, index) => {\r\n const painted = rule.target === 'row' ? undefined : (rule.column ?? rule.field)\r\n const lost = painted !== undefined && !columns.includes(painted)\r\n return (\r\n <Box\r\n // biome-ignore lint/suspicious/noArrayIndexKey: regras não têm id\r\n key={index}\r\n sx={{\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 1,\r\n p: 0.75,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: 0.5,\r\n '&:hover .row-actions': { visibility: 'visible' }\r\n }}\r\n >\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center', flexWrap: 'wrap' }}>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n {index + 1}. Se\r\n </Typography>\r\n <Box sx={{ flex: '2 1 140px' }}>\r\n <NameSelect\r\n value={rule.field}\r\n options={fieldOptions}\r\n required\r\n onChange={(field) => update(index, (current) => ({ ...current, field }))}\r\n />\r\n </Box>\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={rule.operator}\r\n onChange={(e) =>\r\n update(index, (current) => withOperator(current, e.target.value as RuleOperator))\r\n }\r\n sx={{ ...inputSx, flex: '1 1 110px' }}\r\n >\r\n {RULE_OPERATORS.map((operator) => (\r\n <MenuItem key={operator} value={operator}>\r\n {RULE_OPERATOR_LABEL[operator]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n {!UNARY_OPERATORS.includes(rule.operator) && (\r\n <Box sx={{ flex: '1 1 80px' }}>\r\n <CommitText\r\n value={rule.value === undefined ? '' : String(rule.value)}\r\n placeholder=\"valor\"\r\n error={rule.value === undefined}\r\n onCommit={(text) =>\r\n update(index, (current) => ({ ...current, value: parseValue(current, text) }))\r\n }\r\n />\r\n </Box>\r\n )}\r\n {rule.operator === 'between' && (\r\n <>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>e</Typography>\r\n <Box sx={{ flex: '1 1 80px' }}>\r\n <CommitText\r\n value={rule.to === undefined ? '' : String(rule.to)}\r\n placeholder=\"até\"\r\n error={rule.to === undefined}\r\n onCommit={(text) =>\r\n update(index, (current) => {\r\n const to = parseValue(current, text)\r\n return { ...current, to: typeof to === 'number' ? to : undefined }\r\n })\r\n }\r\n />\r\n </Box>\r\n </>\r\n )}\r\n <Box className=\"row-actions\" sx={{ display: 'flex', visibility: 'hidden' }}>\r\n <SmallButton\r\n title=\"Subir\"\r\n disabled={index === 0}\r\n onClick={() => onChange(moveTo(rules, index, index - 1))}\r\n >\r\n ↑\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Descer\"\r\n disabled={index === rules.length - 1}\r\n onClick={() => onChange(moveTo(rules, index, index + 2))}\r\n >\r\n ↓\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Remover\"\r\n onClick={() => onChange(rules.filter((_, i) => i !== index))}\r\n >\r\n ×\r\n </SmallButton>\r\n </Box>\r\n </Box>\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center', flexWrap: 'wrap' }}>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>pinta</Typography>\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={rule.target === 'row' ? 'row' : 'cell'}\r\n onChange={(e) =>\r\n update(index, ({ target: _target, column: _column, ...rest }) =>\r\n e.target.value === 'row' ? { ...rest, target: 'row' } : rest\r\n )\r\n }\r\n sx={{ ...inputSx, flex: '1 1 110px' }}\r\n >\r\n <MenuItem value=\"cell\">a célula de</MenuItem>\r\n <MenuItem value=\"row\">a linha toda</MenuItem>\r\n </TextField>\r\n {rule.target !== 'row' && (\r\n <Box sx={{ flex: '2 1 140px' }}>\r\n <NameSelect\r\n value={rule.column ?? ''}\r\n options={columnOptions}\r\n emptyLabel={`o próprio campo${columns.includes(rule.field) ? '' : ' (fora do gráfico)'}`}\r\n onChange={(column) =>\r\n update(index, (current) => withField(current, 'column', column || undefined))\r\n }\r\n />\r\n </Box>\r\n )}\r\n <Box\r\n sx={{\r\n px: 1,\r\n py: 0.25,\r\n fontSize: 12,\r\n border: 1,\r\n borderColor: 'divider',\r\n color: rule.color,\r\n bgcolor: rule.background,\r\n fontWeight: rule.bold ? 700 : undefined\r\n }}\r\n >\r\n {RULE_SAMPLE}\r\n </Box>\r\n </Box>\r\n {lost && (\r\n <Typography sx={{ fontSize: 11, color: 'warning.main' }}>\r\n \"{painted}\" não é coluna do gráfico: escolha a coluna a pintar ou a linha toda\r\n </Typography>\r\n )}\r\n <Box\r\n sx={{\r\n display: 'grid',\r\n gap: 0.5,\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(150px, 1fr))',\r\n alignItems: 'end'\r\n }}\r\n >\r\n {field(\r\n 'Cor do texto',\r\n <ColorInput\r\n value={rule.color}\r\n fallback=\"#000000\"\r\n onCommit={(color) =>\r\n update(index, (current) => withField(current, 'color', color))\r\n }\r\n />\r\n )}\r\n {field(\r\n 'Fundo',\r\n <ColorInput\r\n value={rule.background}\r\n fallback=\"#ffffff\"\r\n onCommit={(color) =>\r\n update(index, (current) => withField(current, 'background', color))\r\n }\r\n />\r\n )}\r\n {field(\r\n 'Alinhamento',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={rule.align ?? ''}\r\n onChange={(e) =>\r\n update(index, (current) =>\r\n withField(current, 'align', e.target.value || undefined)\r\n )\r\n }\r\n slotProps={{ select: { displayEmpty: true } }}\r\n sx={inputSx}\r\n >\r\n <MenuItem value=\"\">\r\n <em>não muda</em>\r\n </MenuItem>\r\n {COLUMN_ALIGNS.map((option) => (\r\n <MenuItem key={option} value={option}>\r\n {ALIGN_LABEL[option]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )}\r\n {field(\r\n 'Vertical',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={rule.verticalAlign ?? ''}\r\n onChange={(e) =>\r\n update(index, (current) =>\r\n withField(current, 'verticalAlign', e.target.value || undefined)\r\n )\r\n }\r\n slotProps={{ select: { displayEmpty: true } }}\r\n sx={inputSx}\r\n >\r\n <MenuItem value=\"\">\r\n <em>não muda</em>\r\n </MenuItem>\r\n {COLUMN_VERTICAL_ALIGNS.map((option) => (\r\n <MenuItem key={option} value={option}>\r\n {VERTICAL_ALIGN_LABEL[option]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )}\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={!!rule.bold}\r\n onChange={(e) =>\r\n update(index, (current) =>\r\n withField(current, 'bold', e.target.checked || undefined)\r\n )\r\n }\r\n />\r\n }\r\n label={<Typography sx={{ fontSize: 12 }}>Negrito</Typography>}\r\n />\r\n </Box>\r\n </Box>\r\n )\r\n })}\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n disabled={!fieldOptions.length}\r\n onClick={() =>\r\n onChange([\r\n ...rules,\r\n {\r\n field: columns.find((name) => !name.startsWith(PERCENT_PREFIX)) ?? '',\r\n operator: '>',\r\n value: 0,\r\n background: DEFAULT_RULE_BACKGROUND\r\n }\r\n ])\r\n }\r\n sx={{ alignSelf: 'flex-start', textTransform: 'none' }}\r\n >\r\n + regra\r\n </Button>\r\n </Box>\r\n )\r\n}\r\n\r\nconst COLOR_SCALE_TARGET_LABEL: Record<ColorScaleTarget, string> = {\r\n background: 'o fundo',\r\n text: 'o texto'\r\n}\r\n\r\nconst DEFAULT_SCALE_COLOR = '#2e7d32'\r\n\r\n/**\r\n * Escalas de cor (gradiente), uma por cartão: \"pinta <o fundo | o texto> de <coluna> de <cor\r\n * mínima> (em <mínimo>) a <cor máxima> (em <máximo>)\". Mínimo/máximo vazios = da própria coluna.\r\n */\r\nfunction ColorScalesInput({\r\n scales,\r\n columnOptions,\r\n onChange\r\n}: {\r\n scales: ColorScale[]\r\n columnOptions: Option[]\r\n onChange: (scales: ColorScale[]) => void\r\n}) {\r\n const update = (index: number, change: (scale: ColorScale) => ColorScale) =>\r\n onChange(scales.map((scale, i) => (i === index ? change(scale) : scale)))\r\n const columns = columnOptions.map((option) => option.name)\r\n const parseNumber = (text: string) => {\r\n const number = Number(text.trim().replace(',', '.'))\r\n return text.trim() && Number.isFinite(number) ? number : undefined\r\n }\r\n\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.75, maxWidth: 760 }}>\r\n {scales.map((scale, index) => {\r\n const minColor = scale.minColor ?? DEFAULT_SCALE_MIN_COLOR\r\n const inverted =\r\n scale.min !== undefined && scale.max !== undefined && scale.min >= scale.max\r\n return (\r\n <Box\r\n // biome-ignore lint/suspicious/noArrayIndexKey: escalas não têm id\r\n key={index}\r\n sx={{\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 1,\r\n p: 0.75,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n gap: 0.5,\r\n '&:hover .row-actions': { visibility: 'visible' }\r\n }}\r\n >\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center', flexWrap: 'wrap' }}>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n {index + 1}. Pinta\r\n </Typography>\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={scale.target ?? 'background'}\r\n onChange={(e) =>\r\n update(index, (current) =>\r\n withField(\r\n current,\r\n 'target',\r\n e.target.value === 'background' ? undefined : e.target.value\r\n )\r\n )\r\n }\r\n sx={{ ...inputSx, flex: '1 1 100px' }}\r\n >\r\n {COLOR_SCALE_TARGETS.map((target) => (\r\n <MenuItem key={target} value={target}>\r\n {COLOR_SCALE_TARGET_LABEL[target]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>de</Typography>\r\n <Box sx={{ flex: '2 1 140px' }}>\r\n <NameSelect\r\n value={scale.column}\r\n options={columnOptions}\r\n required\r\n onChange={(column) => update(index, (current) => ({ ...current, column }))}\r\n />\r\n </Box>\r\n <Box\r\n title=\"Prévia do gradiente\"\r\n sx={{\r\n flex: '1 1 80px',\r\n height: 20,\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 0.5,\r\n background: `linear-gradient(to right, ${minColor}, ${scale.color})`\r\n }}\r\n />\r\n <Box className=\"row-actions\" sx={{ display: 'flex', visibility: 'hidden' }}>\r\n <SmallButton\r\n title=\"Subir\"\r\n disabled={index === 0}\r\n onClick={() => onChange(moveTo(scales, index, index - 1))}\r\n >\r\n ↑\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Descer\"\r\n disabled={index === scales.length - 1}\r\n onClick={() => onChange(moveTo(scales, index, index + 2))}\r\n >\r\n ↓\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Remover\"\r\n onClick={() => onChange(scales.filter((_, i) => i !== index))}\r\n >\r\n ×\r\n </SmallButton>\r\n </Box>\r\n </Box>\r\n {scale.column && !columns.includes(scale.column) && (\r\n <Typography sx={{ fontSize: 11, color: 'warning.main' }}>\r\n \"{scale.column}\" não é coluna numérica do gráfico: nada é pintado\r\n </Typography>\r\n )}\r\n <Box\r\n sx={{\r\n display: 'grid',\r\n gap: 0.5,\r\n gridTemplateColumns: 'repeat(auto-fit, minmax(130px, 1fr))',\r\n alignItems: 'end'\r\n }}\r\n >\r\n {field(\r\n 'Cor mínima',\r\n <ColorInput\r\n value={scale.minColor}\r\n fallback={DEFAULT_SCALE_MIN_COLOR}\r\n onCommit={(color) =>\r\n update(index, (current) =>\r\n withField(\r\n current,\r\n 'minColor',\r\n color === DEFAULT_SCALE_MIN_COLOR ? undefined : color\r\n )\r\n )\r\n }\r\n />\r\n )}\r\n {field(\r\n 'Mínimo',\r\n <CommitText\r\n value={scale.min === undefined ? '' : String(scale.min)}\r\n placeholder=\"menor da coluna\"\r\n error={inverted}\r\n onCommit={(text) =>\r\n update(index, (current) => withField(current, 'min', parseNumber(text)))\r\n }\r\n />\r\n )}\r\n {field(\r\n 'Cor máxima',\r\n <ColorInput\r\n value={scale.color}\r\n fallback={DEFAULT_SCALE_COLOR}\r\n onCommit={(color) =>\r\n update(index, (current) => ({\r\n ...current,\r\n color: color ?? DEFAULT_SCALE_COLOR\r\n }))\r\n }\r\n />\r\n )}\r\n {field(\r\n 'Máximo',\r\n <CommitText\r\n value={scale.max === undefined ? '' : String(scale.max)}\r\n placeholder=\"maior da coluna\"\r\n error={inverted}\r\n onCommit={(text) =>\r\n update(index, (current) => withField(current, 'max', parseNumber(text)))\r\n }\r\n />\r\n )}\r\n </Box>\r\n {inverted && (\r\n <Typography sx={{ fontSize: 11, color: 'error.main' }}>\r\n O mínimo precisa ser menor que o máximo\r\n </Typography>\r\n )}\r\n </Box>\r\n )\r\n })}\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n disabled={!columnOptions.length}\r\n onClick={() =>\r\n onChange([\r\n ...scales,\r\n {\r\n column:\r\n columns.find((name) => !scales.some((scale) => scale.column === name)) ??\r\n columns[0] ??\r\n '',\r\n color: DEFAULT_SCALE_COLOR\r\n }\r\n ])\r\n }\r\n sx={{ alignSelf: 'flex-start', textTransform: 'none' }}\r\n >\r\n + escala\r\n </Button>\r\n </Box>\r\n )\r\n}\r\n\r\n/** Campo de texto que só manda o valor no Enter ou ao sair (número parcial não vira valor). */\r\nfunction CommitText({\r\n value,\r\n placeholder,\r\n error,\r\n onCommit\r\n}: {\r\n value: string\r\n placeholder?: string\r\n error?: boolean\r\n onCommit: (text: string) => void\r\n}) {\r\n const [typing, setTyping] = useState<string | null>(null)\r\n const commit = () => {\r\n if (typing === null) return\r\n setTyping(null)\r\n if (typing !== value) onCommit(typing)\r\n }\r\n return (\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={typing ?? value}\r\n placeholder={placeholder}\r\n error={error && typing === null}\r\n onChange={(e) => setTyping(e.target.value)}\r\n onBlur={commit}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') commit()\r\n if (e.key === 'Escape') setTyping(null)\r\n }}\r\n sx={inputSx}\r\n />\r\n )\r\n}\r\n\r\n/**\r\n * Cor com o seletor nativo. Mexer no seletor só muda a amostra: o valor vai para o editor quando\r\n * ele fecha — o `change` nativo; o `onChange` do React dispara a cada movimento. O texto entra no\r\n * Enter ou ao sair do campo.\r\n */\r\nfunction ColorInput({\r\n value,\r\n fallback,\r\n onCommit\r\n}: {\r\n value: string | undefined\r\n fallback: string\r\n onCommit: (color: string | undefined) => void\r\n}) {\r\n const [picking, setPicking] = useState<string | null>(null)\r\n const [typing, setTyping] = useState<string | null>(null)\r\n const picker = useRef<HTMLInputElement>(null)\r\n const commit = useRef(onCommit)\r\n useEffect(() => {\r\n commit.current = onCommit\r\n })\r\n useEffect(() => {\r\n const input = picker.current\r\n if (!input) return\r\n const listener = () => {\r\n commit.current(input.value)\r\n setPicking(null)\r\n }\r\n input.addEventListener('change', listener)\r\n return () => input.removeEventListener('change', listener)\r\n }, [])\r\n\r\n const commitText = () => {\r\n if (typing === null) return\r\n const text = typing.trim()\r\n setTyping(null)\r\n if (text !== (value ?? '')) onCommit(text || undefined)\r\n }\r\n\r\n return (\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>\r\n <Box\r\n component=\"input\"\r\n type=\"color\"\r\n ref={picker}\r\n value={picking ?? value ?? fallback}\r\n onChange={(e: ChangeEvent<HTMLInputElement>) => setPicking(e.target.value)}\r\n sx={{\r\n width: 32,\r\n height: 30,\r\n p: 0,\r\n border: 0,\r\n bgcolor: 'transparent',\r\n cursor: 'pointer'\r\n }}\r\n />\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={typing ?? picking ?? value ?? ''}\r\n placeholder={fallback}\r\n onChange={(e) => setTyping(e.target.value)}\r\n onBlur={commitText}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') commitText()\r\n if (e.key === 'Escape') setTyping(null)\r\n }}\r\n sx={inputSx}\r\n />\r\n </Box>\r\n )\r\n}\r\n\r\n/**\r\n * Regra de um valor (`ValueRule`): a checkbox liga (com \"diferente de 0\") e desliga (sai do JSON);\r\n * ligada, escolhe o operador e o número (e o fim do intervalo no \"entre\").\r\n */\r\nfunction ValueRuleInput({\r\n rule,\r\n label,\r\n onChange\r\n}: {\r\n rule: ValueRule | undefined\r\n label: string\r\n onChange: (rule: ValueRule | undefined) => void\r\n}) {\r\n const setOperator = (operator: ValueRuleOperator) => {\r\n const { to, ...rest } = rule ?? { value: 0 }\r\n onChange(\r\n operator === 'between' ? { ...rest, operator, to: to ?? rest.value } : { ...rest, operator }\r\n )\r\n }\r\n return (\r\n <Box>\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={!!rule}\r\n onChange={(e) => onChange(e.target.checked ? { operator: '!=', value: 0 } : undefined)}\r\n />\r\n }\r\n label={<Typography sx={{ fontSize: 12 }}>{label}</Typography>}\r\n />\r\n {rule && (\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center', pl: 3.5 }}>\r\n <Typography sx={{ fontSize: 12, whiteSpace: 'nowrap' }}>valor</Typography>\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={rule.operator}\r\n onChange={(e) => setOperator(e.target.value as ValueRuleOperator)}\r\n sx={{ ...inputSx, minWidth: 130 }}\r\n >\r\n {VALUE_RULE_OPERATORS.map((operator) => (\r\n <MenuItem key={operator} value={operator} sx={{ fontSize: 12 }}>\r\n {RULE_OPERATOR_LABEL[operator]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n <RuleNumber value={rule.value} onCommit={(value) => onChange({ ...rule, value })} />\r\n {rule.operator === 'between' && (\r\n <>\r\n <Typography sx={{ fontSize: 12 }}>e</Typography>\r\n <RuleNumber\r\n value={rule.to ?? rule.value}\r\n onCommit={(to) => onChange({ ...rule, to })}\r\n />\r\n </>\r\n )}\r\n </Box>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\n/** Número digitado (aceita vírgula); só grava quando o texto é um número. */\r\nfunction RuleNumber({ value, onCommit }: { value: number; onCommit: (value: number) => void }) {\r\n const [typing, setTyping] = useState<string | null>(null)\r\n return (\r\n <TextField\r\n size=\"small\"\r\n value={typing ?? String(value)}\r\n error={typing !== null && !Number.isFinite(Number(typing.trim().replace(',', '.')))}\r\n onChange={(e) => {\r\n setTyping(e.target.value)\r\n const text = e.target.value.trim().replace(',', '.')\r\n const number = Number(text)\r\n if (text && Number.isFinite(number)) onCommit(number)\r\n }}\r\n onBlur={() => setTyping(null)}\r\n sx={{ ...inputSx, width: 90 }}\r\n />\r\n )\r\n}\r\n\r\n/**\r\n * Cor por série (`{ série: cor }`). `measures`: uma linha por medida do gráfico (padrão: a paleta,\r\n * na ordem); `null`: as séries são valores de uma dimensão, que o devtools não conhece — digita o\r\n * valor e adiciona.\r\n */\r\nfunction ColorsInput({\r\n colors,\r\n measures,\r\n onChange\r\n}: {\r\n colors: Record<string, string>\r\n measures: string[] | null\r\n onChange: (colors: Record<string, string>) => void\r\n}) {\r\n const [draft, setDraft] = useState('')\r\n const palette = (index: number) => SERIES_COLORS[index % SERIES_COLORS.length] as string\r\n const row = (name: string, fallback: string, remove: boolean) => (\r\n <Box key={name} sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>\r\n <Typography\r\n title={name}\r\n sx={{\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n minWidth: 90,\r\n maxWidth: 140,\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n whiteSpace: 'nowrap'\r\n }}\r\n >\r\n {name}\r\n </Typography>\r\n <ColorInput\r\n value={colors[name]}\r\n fallback={fallback}\r\n onCommit={(color) => onChange(withField(colors, name, color))}\r\n />\r\n {remove && (\r\n <IconButton\r\n size=\"small\"\r\n title=\"Tirar a cor\"\r\n onClick={() => onChange(withField(colors, name, undefined))}\r\n >\r\n ✕\r\n </IconButton>\r\n )}\r\n </Box>\r\n )\r\n const add = () => {\r\n const name = draft.trim()\r\n if (!name || colors[name]) return\r\n onChange({ ...colors, [name]: palette(Object.keys(colors).length) })\r\n setDraft('')\r\n }\r\n\r\n if (measures)\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>\r\n {measures.length ? (\r\n measures.map((measure, index) => row(measure, palette(index), false))\r\n ) : (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled' }}>sem medidas</Typography>\r\n )}\r\n </Box>\r\n )\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>\r\n {Object.keys(colors).map((name, index) => row(name, palette(index), true))}\r\n <Box sx={{ display: 'flex', gap: 0.5, alignItems: 'center' }}>\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={draft}\r\n placeholder='Valor da série (ou \"(em branco)\", \"Outros\")'\r\n onChange={(e) => setDraft(e.target.value)}\r\n onKeyDown={(e) => e.key === 'Enter' && add()}\r\n sx={inputSx}\r\n />\r\n <Button size=\"small\" onClick={add} disabled={!draft.trim() || !!colors[draft.trim()]}>\r\n + cor\r\n </Button>\r\n </Box>\r\n </Box>\r\n )\r\n}\r\n\r\n/** Sem as chaves de colunas que saíram do gráfico; vazio = `undefined` (sai do JSON). */\r\nfunction pruned<T>(map: Record<string, T>, keep: string[]) {\r\n const next = Object.fromEntries(Object.entries(map).filter(([key]) => keep.includes(key)))\r\n return Object.keys(next).length ? next : undefined\r\n}\r\n\r\nconst ALIGN_LABEL: Record<ColumnAlign, string> = {\r\n left: 'à esquerda',\r\n center: 'centralizado',\r\n right: 'à direita'\r\n}\r\n\r\nconst VERTICAL_ALIGN_LABEL: Record<ColumnVerticalAlign, string> = {\r\n top: 'em cima',\r\n middle: 'no meio',\r\n bottom: 'embaixo'\r\n}\r\n\r\nconst FORMAT_LABEL: Record<string, string> = {\r\n number: 'número',\r\n integer: 'inteiro',\r\n currency: 'R$',\r\n percent: '%'\r\n}\r\n\r\n/** Número de exemplo da prévia do formato. */\r\nconst SAMPLE = 1234567.891\r\n\r\n/**\r\n * Ícone à direita de uma dimensão/medida que abre as opções dela no gráfico: rótulo, formatter\r\n * (dimensão) e formato (medida). Vazio = o do dicionário do modelo (que aparece como placeholder).\r\n * Opção ausente (`undefined`) = o tipo do gráfico não tem esse campo.\r\n */\r\nfunction ColumnOptions({\r\n kind,\r\n name,\r\n model,\r\n label,\r\n onLabel,\r\n format,\r\n onFormat,\r\n formatter,\r\n formatters,\r\n onFormatter,\r\n align,\r\n defaultAlign,\r\n onAlign,\r\n verticalAlign,\r\n onVerticalAlign,\r\n onReset\r\n}: {\r\n kind: ColumnKind\r\n name: string\r\n model: ModelDef\r\n label: string | undefined\r\n onLabel: (label: string) => void\r\n format: ChartNumberFormat | undefined\r\n onFormat: (format: ChartNumberFormat) => void\r\n formatter: string | undefined\r\n formatters: string[]\r\n onFormatter: (formatter: string) => void\r\n /** Alinhamento horizontal; `''` = padrão (`defaultAlign`). */\r\n align: ColumnAlign | '' | undefined\r\n defaultAlign: ColumnAlign\r\n onAlign: (align: ColumnAlign | undefined) => void\r\n /** Alinhamento vertical; `''` = padrão (no meio). */\r\n verticalAlign: ColumnVerticalAlign | '' | undefined\r\n onVerticalAlign: (align: ColumnVerticalAlign | undefined) => void\r\n /** Volta rótulo, formato, formatter e alinhamento da coluna ao padrão (numa mudança só). */\r\n onReset: () => void\r\n}) {\r\n const [anchor, setAnchor] = useState<HTMLElement | null>(null)\r\n const fromModel = kind === 'measure' ? model.measures[name] : model.dimensions[name]\r\n const measureMeta = kind === 'measure' ? model.measures[name] : undefined\r\n const customized =\r\n !!label ||\r\n !!formatter ||\r\n !!align ||\r\n !!verticalAlign ||\r\n (format !== undefined && Object.keys(format).length > 0)\r\n const setFormat = (key: keyof ChartNumberFormat, next: unknown) =>\r\n onFormat(withField(format ?? {}, key, next))\r\n const decimals = format?.decimals\r\n const resolved: ChartNumberFormat = {\r\n ...(measureMeta?.format !== undefined && { format: measureMeta.format }),\r\n ...(measureMeta?.decimals !== undefined && { decimals: measureMeta.decimals }),\r\n ...format\r\n }\r\n const small = { ...inputSx, '& .MuiInputBase-input': { fontFamily: MONO, fontSize: 12, px: 1 } }\r\n\r\n return (\r\n <>\r\n <Tooltip title={customized ? 'Opções da coluna (personalizada)' : 'Opções da coluna'}>\r\n <IconButton\r\n size=\"small\"\r\n aria-label={`Opções de ${name}`}\r\n onClick={(e) => setAnchor(e.currentTarget)}\r\n sx={{\r\n p: 0.25,\r\n fontSize: 14,\r\n color: customized ? 'primary.main' : 'text.secondary'\r\n }}\r\n >\r\n ⚙\r\n </IconButton>\r\n </Tooltip>\r\n <Popover\r\n open={!!anchor}\r\n anchorEl={anchor}\r\n onClose={() => setAnchor(null)}\r\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\r\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\r\n slotProps={{ paper: { sx: { p: 1.5, width: 320 } } }}\r\n >\r\n <Typography sx={{ fontSize: 12, fontWeight: 700, mb: 1 }}>\r\n <Box component=\"span\" sx={{ color: KIND_STYLE[kind].color, mr: 0.75 }}>\r\n {KIND_STYLE[kind].icon}\r\n </Box>\r\n <Box component=\"span\" sx={{ fontFamily: MONO }}>\r\n {name}\r\n </Box>\r\n <Box component=\"span\" sx={{ color: 'text.secondary', fontWeight: 400, ml: 1 }}>\r\n {KIND_STYLE[kind].noun}\r\n </Box>\r\n </Typography>\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.25 }}>\r\n {label !== undefined &&\r\n field(\r\n 'Rótulo',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n autoFocus\r\n value={label}\r\n placeholder={fromModel?.label ?? name}\r\n onChange={(e) => onLabel(e.target.value)}\r\n sx={inputSx}\r\n />,\r\n 'Legenda, tooltip e cabeçalho, só neste gráfico; vazio = rótulo do dicionário'\r\n )}\r\n {align !== undefined &&\r\n field(\r\n 'Alinhamento',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={align}\r\n onChange={(e) => onAlign((e.target.value as ColumnAlign) || undefined)}\r\n slotProps={{ select: { displayEmpty: true } }}\r\n sx={small}\r\n >\r\n <MenuItem value=\"\">\r\n <em>padrão ({ALIGN_LABEL[defaultAlign]})</em>\r\n </MenuItem>\r\n {COLUMN_ALIGNS.map((option) => (\r\n <MenuItem key={option} value={option}>\r\n {ALIGN_LABEL[option]}\r\n </MenuItem>\r\n ))}\r\n </TextField>,\r\n 'Horizontal: cabeçalho, células e total da coluna'\r\n )}\r\n {verticalAlign !== undefined &&\r\n field(\r\n 'Alinhamento vertical',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={verticalAlign}\r\n onChange={(e) =>\r\n onVerticalAlign((e.target.value as ColumnVerticalAlign) || undefined)\r\n }\r\n slotProps={{ select: { displayEmpty: true } }}\r\n sx={small}\r\n >\r\n <MenuItem value=\"\">\r\n <em>padrão ({VERTICAL_ALIGN_LABEL.middle})</em>\r\n </MenuItem>\r\n {COLUMN_VERTICAL_ALIGNS.map((option) => (\r\n <MenuItem key={option} value={option}>\r\n {VERTICAL_ALIGN_LABEL[option]}\r\n </MenuItem>\r\n ))}\r\n </TextField>,\r\n 'Aparece quando a linha tem texto em mais de uma linha'\r\n )}\r\n {formatter !== undefined &&\r\n field(\r\n 'Formatter',\r\n <NameSelect\r\n value={formatter}\r\n options={formatters.map((option) => ({ name: option }))}\r\n onChange={onFormatter}\r\n />,\r\n 'Built-in (to_month_name, to_date, ...) e os passados ao <DashboardCharts formatters={{ ... }}> da página'\r\n )}\r\n {format !== undefined && (\r\n <>\r\n <Box sx={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 1 }}>\r\n {field(\r\n 'Formato',\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={format.format ?? ''}\r\n onChange={(e) => setFormat('format', e.target.value || undefined)}\r\n slotProps={{ select: { displayEmpty: true } }}\r\n sx={small}\r\n >\r\n <MenuItem value=\"\">\r\n <em>\r\n padrão\r\n {measureMeta?.format ? ` (${FORMAT_LABEL[measureMeta.format]})` : ''}\r\n </em>\r\n </MenuItem>\r\n {VALUE_FORMATS.map((option) => (\r\n <MenuItem key={option} value={option}>\r\n {FORMAT_LABEL[option]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )}\r\n {field(\r\n 'Casas decimais',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n type=\"number\"\r\n value={decimals ?? ''}\r\n placeholder={\r\n measureMeta?.decimals === undefined ? 'padrão' : String(measureMeta.decimals)\r\n }\r\n error={\r\n decimals !== undefined &&\r\n (!Number.isInteger(decimals) || decimals < 0 || decimals > 10)\r\n }\r\n onChange={(e) =>\r\n setFormat(\r\n 'decimals',\r\n e.target.value.trim() === '' ? undefined : Number(e.target.value)\r\n )\r\n }\r\n slotProps={{ htmlInput: { min: 0, max: 10 } }}\r\n sx={small}\r\n />\r\n )}\r\n {field(\r\n 'Prefixo',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={format.prefix ?? ''}\r\n placeholder=\"ex.: ~\"\r\n onChange={(e) => setFormat('prefix', e.target.value)}\r\n sx={small}\r\n />\r\n )}\r\n {field(\r\n 'Sufixo',\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n value={format.suffix ?? ''}\r\n placeholder=\"ex.: t\"\r\n onChange={(e) => setFormat('suffix', e.target.value)}\r\n sx={small}\r\n />\r\n )}\r\n </Box>\r\n <FormControlLabel\r\n sx={{ m: 0 }}\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n sx={{ p: 0.25, mr: 0.5 }}\r\n checked={format.compact ?? false}\r\n onChange={(e) => setFormat('compact', e.target.checked || undefined)}\r\n />\r\n }\r\n label={\r\n <Typography sx={{ fontSize: 12 }}>Notação curta (1,2 mil / 3,4 mi)</Typography>\r\n }\r\n />\r\n <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>\r\n Exemplo:{' '}\r\n <Box component=\"span\" sx={{ fontFamily: MONO, color: 'text.primary' }}>\r\n {formatMeasure(SAMPLE, resolved, 2)}\r\n </Box>\r\n </Typography>\r\n </>\r\n )}\r\n <Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>\r\n <Button size=\"small\" disabled={!customized} onClick={onReset}>\r\n Restaurar padrão\r\n </Button>\r\n </Box>\r\n </Box>\r\n </Popover>\r\n </>\r\n )\r\n}\r\n\r\nconst formGrid = (columns: number) => ({\r\n display: 'grid',\r\n gap: 1.5,\r\n gridTemplateColumns: `repeat(${columns}, minmax(0, 1fr))`\r\n})\r\n\r\n/** Rótulo padrão (do dicionário) como placeholder do `label` do filtro. */\r\nfunction labelPlaceholder(key: string, values: Record<string, unknown>, model: ModelDef) {\r\n if (key === 'label' && typeof values.dimension === 'string')\r\n return model.dimensions[values.dimension]?.label ?? values.dimension\r\n return undefined\r\n}\r\n\r\nfunction field(label: string, input: ReactNode, hint?: string) {\r\n return (\r\n <Box>\r\n <Typography sx={{ fontSize: 11, color: 'text.secondary', mb: 0.25 }}>\r\n {label}\r\n {hint && (\r\n <Tooltip title={hint}>\r\n <Box component=\"span\" sx={{ ml: 0.5, cursor: 'help' }}>\r\n ⓘ\r\n </Box>\r\n </Tooltip>\r\n )}\r\n </Typography>\r\n {input}\r\n </Box>\r\n )\r\n}\r\n\r\nfunction withHint(input: ReactNode, hint?: string) {\r\n return hint ? (\r\n <Tooltip title={hint} placement=\"top-start\">\r\n <Box>{input}</Box>\r\n </Tooltip>\r\n ) : (\r\n input\r\n )\r\n}\r\n\r\nfunction OptionText({ option }: { option: Option }) {\r\n return (\r\n <>\r\n {option.name}\r\n {option.label && option.label !== option.name && (\r\n <Box component=\"span\" sx={{ color: 'text.secondary', ml: 1 }}>\r\n {option.label}\r\n </Box>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\nfunction NameSelect({\r\n value,\r\n options,\r\n required,\r\n emptyLabel,\r\n onChange\r\n}: {\r\n value: string\r\n options: Option[]\r\n required?: boolean\r\n /** Texto da opção vazia (padrão: \"(nenhum)\"). */\r\n emptyLabel?: string\r\n onChange: (value: string) => void\r\n}) {\r\n const known = !value || options.some((option) => option.name === value)\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={value}\r\n error={!known || (!!required && !value)}\r\n onChange={(e) => onChange(e.target.value)}\r\n sx={inputSx}\r\n >\r\n {!required && (\r\n <MenuItem value=\"\">\r\n <em>{emptyLabel ?? '(nenhum)'}</em>\r\n </MenuItem>\r\n )}\r\n {!known && <MenuItem value={value}>{value} (não existe)</MenuItem>}\r\n {options.flatMap((option, index) => [\r\n ...(option.group && option.group !== options[index - 1]?.group\r\n ? [<ListSubheader key={`h:${option.group}`}>{option.group}</ListSubheader>]\r\n : []),\r\n <MenuItem key={option.name} value={option.name}>\r\n <OptionText option={option} />\r\n </MenuItem>\r\n ])}\r\n </TextField>\r\n )\r\n}\r\n\r\ntype ColumnKind = 'dimension' | 'measure' | 'percent' | 'chart'\r\n/** `percent`: coluna de % do total da medida `name` (`%:name` no `columnOrder`). */\r\ntype ColumnItem = { kind: ColumnKind; name: string }\r\n\r\nconst itemColumn = (item: ColumnItem) =>\r\n item.kind === 'percent' ? percentColumn(item.name) : item.name\r\n\r\nconst KIND_STYLE: Record<ColumnKind, { icon: string; color: string; noun: string; group: string }> =\r\n {\r\n dimension: { icon: '◇', color: '#4dabf7', noun: 'dimensão', group: 'Dimensões' },\r\n measure: { icon: 'Σ', color: '#F58220', noun: 'medida', group: 'Medidas' },\r\n percent: { icon: '%', color: '#9775fa', noun: '% do total', group: '% do total (da medida)' },\r\n chart: { icon: '▦', color: '#51cf66', noun: 'gráfico', group: 'Gráficos' }\r\n }\r\n\r\n/**\r\n * Lista ordenada, uma linha por item: a ordem é a das séries/colunas. Reordena arrastando pela alça\r\n * (⋮⋮) ou com ↑/↓; um único \"+ adicionar\" no fim (já com o nome escolhido, sem linha vazia). Com\r\n * dois tipos (dimensões e medidas juntas), o adicionar agrupa as opções por tipo e a ordem mistura\r\n * os dois.\r\n */\r\nfunction ColumnList({\r\n items,\r\n options,\r\n extra,\r\n error,\r\n onChange\r\n}: {\r\n items: ColumnItem[]\r\n /** Fica à direita de cada linha, sempre visível (ex.: o ícone de opções da coluna). */\r\n extra?: (item: ColumnItem) => ReactNode\r\n /** Opções por tipo; só os tipos presentes aqui entram no adicionar. */\r\n options: Partial<Record<ColumnKind, Option[]>>\r\n /** Marca o adicionar (campo obrigatório vazio). */\r\n error?: boolean\r\n onChange: (items: ColumnItem[]) => void\r\n}) {\r\n const [drag, setDrag] = useState<{ from: number; to: number } | null>(null)\r\n // Só a alça arrasta: a linha inteira arrastável atrapalharia o select\r\n const [grabbed, setGrabbed] = useState<number | null>(null)\r\n const kinds = Object.keys(options) as ColumnKind[]\r\n const mixed = kinds.length > 1\r\n const used = (kind: ColumnKind, name: string) =>\r\n items.some((item) => item.kind === kind && item.name === name)\r\n const free = (kind: ColumnKind, keep?: string) =>\r\n (options[kind] ?? []).filter((option) => option.name === keep || !used(kind, option.name))\r\n const replace = (index: number, name: string) =>\r\n onChange(items.map((item, i) => (i === index ? { ...item, name } : item)))\r\n const marker = {\r\n content: '\"\"',\r\n position: 'absolute',\r\n left: 0,\r\n right: 0,\r\n height: 2,\r\n bgcolor: 'primary.main'\r\n }\r\n const addable = kinds.filter((kind) => free(kind).length)\r\n // Valor do adicionar: `tipo:nome` (dimensão e medida podem ter o mesmo nome)\r\n const addOptions = addable.flatMap((kind) => [\r\n ...(mixed ? [<ListSubheader key={`h:${kind}`}>{KIND_STYLE[kind].group}</ListSubheader>] : []),\r\n ...free(kind).map((option) => (\r\n <MenuItem key={`${kind}:${option.name}`} value={`${kind}:${option.name}`}>\r\n {mixed && (\r\n <Box component=\"span\" sx={{ color: KIND_STYLE[kind].color, mr: 0.75 }}>\r\n {KIND_STYLE[kind].icon}\r\n </Box>\r\n )}\r\n <OptionText option={option} />\r\n </MenuItem>\r\n ))\r\n ])\r\n const addNoun = mixed\r\n ? kinds.map((kind) => KIND_STYLE[kind].noun).join(' ou ')\r\n : KIND_STYLE[kinds[0] ?? 'measure'].noun\r\n\r\n return (\r\n // Ocupa a linha do formulário, mas sem esticar demais em telas largas\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5, maxWidth: 760 }}>\r\n {items.map((item, index) => (\r\n <Box\r\n key={`${item.kind}:${item.name}`}\r\n draggable={grabbed === index}\r\n onDragStart={(e) => {\r\n e.dataTransfer.effectAllowed = 'move'\r\n // Firefox só arrasta com algum dado\r\n e.dataTransfer.setData('text/plain', item.name)\r\n setDrag({ from: index, to: index })\r\n }}\r\n onDragOver={(e) => {\r\n if (!drag) return\r\n e.preventDefault()\r\n const rect = e.currentTarget.getBoundingClientRect()\r\n const to = e.clientY < rect.top + rect.height / 2 ? index : index + 1\r\n if (to !== drag.to) setDrag({ ...drag, to })\r\n }}\r\n onDrop={(e) => {\r\n e.preventDefault()\r\n if (drag && drag.to !== drag.from && drag.to !== drag.from + 1)\r\n onChange(moveTo(items, drag.from, drag.to))\r\n setDrag(null)\r\n }}\r\n onDragEnd={() => {\r\n setDrag(null)\r\n setGrabbed(null)\r\n }}\r\n sx={{\r\n position: 'relative',\r\n display: 'flex',\r\n gap: 0.25,\r\n alignItems: 'center',\r\n opacity: drag?.from === index ? 0.4 : 1,\r\n '&:hover .row-actions': { visibility: 'visible' },\r\n '&::before':\r\n drag && drag.from !== index && drag.to === index ? { ...marker, top: -3 } : undefined,\r\n '&::after':\r\n drag && index === items.length - 1 && drag.to === items.length\r\n ? { ...marker, bottom: -3 }\r\n : undefined\r\n }}\r\n >\r\n <Box\r\n component=\"span\"\r\n title=\"Arraste para reordenar\"\r\n onMouseDown={() => setGrabbed(index)}\r\n onMouseUp={() => setGrabbed(null)}\r\n sx={{\r\n color: 'text.disabled',\r\n fontSize: 12,\r\n cursor: 'grab',\r\n userSelect: 'none',\r\n px: 0.25\r\n }}\r\n >\r\n ⋮⋮\r\n </Box>\r\n <Typography sx={{ fontFamily: MONO, fontSize: 11, color: 'primary.main', minWidth: 14 }}>\r\n {index + 1}\r\n </Typography>\r\n {mixed && (\r\n <Tooltip title={KIND_STYLE[item.kind].noun}>\r\n <Box\r\n component=\"span\"\r\n sx={{ color: KIND_STYLE[item.kind].color, fontSize: 12, minWidth: 12 }}\r\n >\r\n {KIND_STYLE[item.kind].icon}\r\n </Box>\r\n </Tooltip>\r\n )}\r\n <NameSelect\r\n value={item.name}\r\n options={free(item.kind, item.name)}\r\n required\r\n onChange={(next) => replace(index, next)}\r\n />\r\n <Box className=\"row-actions\" sx={{ display: 'flex', visibility: 'hidden' }}>\r\n <SmallButton\r\n title=\"Subir\"\r\n disabled={index === 0}\r\n onClick={() => onChange(moveTo(items, index, index - 1))}\r\n >\r\n ↑\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Descer\"\r\n disabled={index === items.length - 1}\r\n onClick={() => onChange(moveTo(items, index, index + 2))}\r\n >\r\n ↓\r\n </SmallButton>\r\n <SmallButton\r\n title=\"Remover\"\r\n onClick={() => onChange(items.filter((_, i) => i !== index))}\r\n >\r\n ×\r\n </SmallButton>\r\n </Box>\r\n {extra?.(item)}\r\n </Box>\r\n ))}\r\n {addable.length > 0 && (\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value=\"\"\r\n error={error}\r\n onChange={(e) => {\r\n const [kind, ...rest] = e.target.value.split(':')\r\n const name = rest.join(':')\r\n if (name) onChange([...items, { kind: kind as ColumnKind, name }])\r\n }}\r\n slotProps={{\r\n select: {\r\n displayEmpty: true,\r\n renderValue: () => (\r\n <Box component=\"span\" sx={{ color: 'text.secondary' }}>\r\n + adicionar {addNoun}\r\n </Box>\r\n )\r\n }\r\n }}\r\n sx={inputSx}\r\n >\r\n {addOptions}\r\n </TextField>\r\n )}\r\n </Box>\r\n )\r\n}\r\n","import {\r\n type Aggregation,\r\n type DiagramPosition,\r\n type DimensionDef,\r\n type FieldMeta,\r\n isAggregate,\r\n type MeasureDef,\r\n type MeasureMeta,\r\n type ModelDef,\r\n type TableDef,\r\n type ValueFormat,\r\n validateModel\r\n} from '../model'\r\nimport { parseColumnRef } from '../star'\r\n\r\n/**\r\n * Conversão entre o modelo (objetos indexados por nome) e as linhas da tabela do editor. As linhas\r\n * têm `uid` próprio para que renomear uma dimensão/medida não perca o foco nem a posição. Os\r\n * metadados ficam como texto (vazio = ausente) e só viram o formato do modelo em `fromEditor`.\r\n */\r\n\r\ntype MetaFields = { label: string; description: string }\r\n\r\nexport type DimensionRow = MetaFields & {\r\n uid: string\r\n name: string\r\n type: 'number' | 'string'\r\n sql: string\r\n}\r\nexport type MeasureRow = MetaFields & {\r\n uid: string\r\n name: string\r\n type: Aggregation | 'ratio' | 'formula'\r\n /** Expressão agregada (`sum`, `count`, `avg`...). */\r\n sql: string\r\n /** Fórmula (`{medida}`). */\r\n expression: string\r\n numerator: string\r\n denominator: string\r\n format: ValueFormat | ''\r\n decimals: string\r\n}\r\nexport type TableRow = MetaFields & {\r\n uid: string\r\n name: string\r\n key: string\r\n sql: string\r\n}\r\n/** Lado N (`from`) e lado 1 (`to`); a tabela vai pelo `uid`, para renomear sem quebrar. */\r\nexport type RelationshipRow = {\r\n uid: string\r\n fromTable: string\r\n fromColumn: string\r\n toTable: string\r\n toColumn: string\r\n inner: boolean\r\n}\r\n\r\nexport type EditorModel = {\r\n name: string\r\n dimensions: DimensionRow[]\r\n measures: MeasureRow[]\r\n tables: TableRow[]\r\n relationships: RelationshipRow[]\r\n /**\r\n * Posições do diagrama pelo `uid` da tabela: renomear não perde a posição, e o que foi removido\r\n * some do arquivo sozinho.\r\n */\r\n positions: Record<string, DiagramPosition>\r\n}\r\n\r\nlet uidCounter = 0\r\nexport const newUid = () => `row-${++uidCounter}`\r\n\r\nconst metaFields = (field: FieldMeta): MetaFields => ({\r\n label: field.label ?? '',\r\n description: field.description ?? ''\r\n})\r\n\r\nexport function toEditor(model: ModelDef): EditorModel {\r\n const tables: TableRow[] = Object.entries(model.tables).map(([name, table]) => ({\r\n uid: newUid(),\r\n name,\r\n key: table.key ?? '',\r\n sql: table.sql,\r\n ...metaFields(table)\r\n }))\r\n const uidOf = (name: string) => tables.find((table) => table.name === name)?.uid ?? ''\r\n const positions = Object.fromEntries(\r\n Object.entries(model.diagram ?? {}).flatMap(([name, point]) => {\r\n const uid = uidOf(name)\r\n return uid ? [[uid, { ...point }]] : []\r\n })\r\n )\r\n return {\r\n name: model.name,\r\n tables,\r\n relationships: (model.relationships ?? []).map((relationship) => {\r\n const from = parseColumnRef(relationship.from)\r\n const to = parseColumnRef(relationship.to)\r\n return {\r\n uid: newUid(),\r\n fromTable: uidOf(from?.table ?? ''),\r\n fromColumn: from?.column ?? '',\r\n toTable: uidOf(to?.table ?? ''),\r\n toColumn: to?.column ?? '',\r\n inner: relationship.inner === true\r\n }\r\n }),\r\n dimensions: Object.entries(model.dimensions).map(([name, dimension]) => ({\r\n uid: newUid(),\r\n name,\r\n type: dimension.type,\r\n sql: dimension.sql,\r\n ...metaFields(dimension)\r\n })),\r\n measures: Object.entries(model.measures).map(([name, measure]) => ({\r\n uid: newUid(),\r\n name,\r\n type: measure.type,\r\n sql: isAggregate(measure) ? measure.sql : '',\r\n expression: measure.type === 'formula' ? measure.expression : '',\r\n numerator: measure.type === 'ratio' ? measure.numerator : '',\r\n denominator: measure.type === 'ratio' ? measure.denominator : '',\r\n format: measure.format ?? '',\r\n decimals: measure.decimals === undefined ? '' : String(measure.decimals),\r\n ...metaFields(measure)\r\n })),\r\n positions\r\n }\r\n}\r\n\r\nconst fieldMeta = (row: MetaFields): FieldMeta => ({\r\n ...(row.label.trim() && { label: row.label.trim() }),\r\n ...(row.description.trim() && { description: row.description.trim() })\r\n})\r\n\r\nexport const dimensionOf = (row: DimensionRow): DimensionDef => ({\r\n sql: row.sql,\r\n type: row.type,\r\n ...fieldMeta(row)\r\n})\r\n\r\nexport function measureOf(row: MeasureRow): MeasureDef {\r\n const meta: MeasureMeta = {\r\n ...fieldMeta(row),\r\n ...(row.format && { format: row.format }),\r\n // Texto inválido vira NaN e a validação do modelo acusa\r\n ...(row.decimals.trim() && { decimals: Number(row.decimals) })\r\n }\r\n if (isAggregate(row)) return { type: row.type, sql: row.sql, ...meta }\r\n if (row.type === 'formula') return { type: 'formula', expression: row.expression, ...meta }\r\n return { type: 'ratio', numerator: row.numerator, denominator: row.denominator, ...meta }\r\n}\r\n\r\nexport const tableOf = (row: TableRow): TableDef => ({\r\n ...(row.key.trim() && { key: row.key.trim() }),\r\n sql: row.sql,\r\n ...fieldMeta(row)\r\n})\r\n\r\nexport function relationshipOf(editor: EditorModel, row: RelationshipRow) {\r\n const name = (uid: string) => editor.tables.find((table) => table.uid === uid)?.name ?? '?'\r\n return {\r\n from: `${name(row.fromTable)}.${row.fromColumn}`,\r\n to: `${name(row.toTable)}.${row.toColumn}`,\r\n ...(row.inner && { inner: true })\r\n }\r\n}\r\n\r\nexport function fromEditor(editor: EditorModel): ModelDef {\r\n const diagram = diagramOf(editor)\r\n return {\r\n name: editor.name,\r\n tables: Object.fromEntries(editor.tables.map((row) => [row.name, tableOf(row)])),\r\n ...(editor.relationships.length && {\r\n relationships: editor.relationships.map((row) => relationshipOf(editor, row))\r\n }),\r\n dimensions: Object.fromEntries(editor.dimensions.map((row) => [row.name, dimensionOf(row)])),\r\n measures: Object.fromEntries(editor.measures.map((row) => [row.name, measureOf(row)])),\r\n ...(Object.keys(diagram).length && { diagram })\r\n }\r\n}\r\n\r\n/** Posições (e tamanhos) pelo nome, na ordem dos cards; arredonda (o arquivo não precisa de frações). */\r\nfunction diagramOf(editor: EditorModel): Record<string, DiagramPosition> {\r\n return Object.fromEntries(\r\n editor.tables.flatMap(({ uid, name }) => {\r\n const point = editor.positions[uid]\r\n if (!point || !name) return []\r\n const { x, y, width, height } = point\r\n return [\r\n [\r\n name,\r\n {\r\n x: Math.round(x),\r\n y: Math.round(y),\r\n ...(width !== undefined && { width: Math.round(width) }),\r\n ...(height !== undefined && { height: Math.round(height) })\r\n }\r\n ]\r\n ]\r\n })\r\n )\r\n}\r\n\r\n/** O modelo sem as posições do diagrama: o que muda as consultas. */\r\nexport const withoutDiagram = ({ diagram: _, ...model }: ModelDef): ModelDef => model\r\n\r\n/** Erros do editor: nomes repetidos (que o objeto do modelo esconderia) + validação do modelo. */\r\nexport function validateEditor(editor: EditorModel): string[] {\r\n const repeated = (names: string[]) => [\r\n ...new Set(names.filter((name, index) => names.indexOf(name) !== index))\r\n ]\r\n const names = [...editor.dimensions, ...editor.measures].map((row) => row.name)\r\n const tables = editor.tables.map((row) => row.name)\r\n return [\r\n ...repeated(names).map((name) => `nome repetido: \"${name}\"`),\r\n ...repeated(tables).map((name) => `tabela repetida: \"${name}\"`),\r\n ...validateModel(fromEditor(editor)).filter((error) => !error.startsWith('nome repetido'))\r\n ]\r\n}\r\n\r\nconst escapeRegex = (text: string) => text.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\r\n\r\n/**\r\n * Renomeia uma tabela e as referências `antigo.coluna` nas dimensões e medidas (os\r\n * relacionamentos e as posições do diagrama apontam pelo `uid` e acompanham sozinhos).\r\n */\r\nexport function renameTable(editor: EditorModel, uid: string, name: string): EditorModel {\r\n const previous = editor.tables.find((row) => row.uid === uid)?.name\r\n if (!previous || previous === name) return editor\r\n const pattern = new RegExp(`(?<![\\\\w.\\`])${escapeRegex(previous)}\\\\.`, 'g')\r\n const replace = (sql: string) => sql.replace(pattern, `${name}.`)\r\n return {\r\n ...editor,\r\n tables: editor.tables.map((table) => (table.uid === uid ? { ...table, name } : table)),\r\n dimensions: editor.dimensions.map((row) => ({ ...row, sql: replace(row.sql) })),\r\n measures: editor.measures.map((row) => ({ ...row, sql: replace(row.sql) }))\r\n }\r\n}\r\n\r\nexport const emptyMeasure = (changes: Partial<MeasureRow> = {}): MeasureRow => ({\r\n uid: newUid(),\r\n name: '',\r\n type: 'sum',\r\n sql: '',\r\n expression: '',\r\n numerator: '',\r\n denominator: '',\r\n format: '',\r\n decimals: '',\r\n label: '',\r\n description: '',\r\n ...changes\r\n})\r\n\r\nexport const emptyDimension = (changes: Partial<DimensionRow> = {}): DimensionRow => ({\r\n uid: newUid(),\r\n name: '',\r\n type: 'string',\r\n sql: '',\r\n label: '',\r\n description: '',\r\n ...changes\r\n})\r\n\r\n/** Nome livre a partir de `prefixo`, `prefixo2`, `prefixo3`... */\r\nexport function freeName(prefix: string, taken: string[]) {\r\n if (!taken.includes(prefix)) return prefix\r\n for (let index = 2; ; index++)\r\n if (!taken.includes(`${prefix}${index}`)) return `${prefix}${index}`\r\n}\r\n","import {\r\n Autocomplete,\r\n Box,\r\n Button,\r\n Checkbox,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n FormControlLabel,\r\n TextField,\r\n Typography\r\n} from '@mui/material'\r\nimport { useMemo, useState } from 'react'\r\nimport type { SchemaTable } from '../types'\r\nimport { HighlightedSql } from './sqlHighlight'\r\nimport { MONO } from './ui'\r\n\r\n/**\r\n * Monta um `SELECT colunas FROM tabela` escolhendo a tabela do banco e marcando as colunas. Abre já\r\n * com a tabela e as colunas do SQL atual quando ele é um SELECT simples desse tipo.\r\n */\r\n\r\ntype Props = {\r\n open: boolean\r\n onClose: () => void\r\n /** Tabelas e views do banco (vazio enquanto carrega). */\r\n tables: SchemaTable[]\r\n /** SQL atual, para abrir com a mesma tabela e colunas. */\r\n sql: string\r\n onApply: (sql: string) => void\r\n}\r\n\r\nconst RESERVED = new Set(\r\n 'select from where group order by limit key keys index table desc asc and or not in is null like as on join case when then else end interval range rows'.split(\r\n ' '\r\n )\r\n)\r\n\r\nexport const quote = (name: string) =>\r\n /^[A-Za-z_]\\w*$/.test(name) && !RESERVED.has(name.toLowerCase()) ? name : `\\`${name}\\``\r\n\r\nconst unquote = (name: string) => name.trim().replace(/^`(.*)`$/, '$1')\r\n\r\nexport function buildSelect(table: string, columns: string[]) {\r\n const list = columns.length ? columns.map((column) => ` ${quote(column)}`).join(',\\n') : ' *'\r\n return `SELECT\\n${list}\\nFROM ${quote(table)}`\r\n}\r\n\r\n/** Tabela e colunas de um `SELECT a, b FROM t` (sem WHERE, JOIN etc.); senão `null`. */\r\nexport function parseSelect(sql: string) {\r\n const match = /^\\s*SELECT\\s+([\\s\\S]+?)\\s+FROM\\s+(`[^`]+`|\\w+)\\s*;?\\s*$/i.exec(sql)\r\n if (!match) return null\r\n const columns = match[1].trim() === '*' ? [] : match[1].split(',').map(unquote)\r\n if (columns.some((column) => !/^[^\\s`().]+$/.test(column))) return null\r\n return { table: unquote(match[2]), columns }\r\n}\r\n\r\nexport function QueryBuilder({ open, onClose, tables, sql, onApply }: Props) {\r\n return (\r\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\r\n {/* Remonta a cada abertura: começa do SQL atual */}\r\n {open && <Builder tables={tables} sql={sql} onClose={onClose} onApply={onApply} />}\r\n </Dialog>\r\n )\r\n}\r\n\r\nfunction Builder({ tables, sql, onClose, onApply }: Omit<Props, 'open'>) {\r\n const [initial] = useState(() => {\r\n const parsed = parseSelect(sql)\r\n const table = parsed && tables.find((item) => item.name === parsed.table)\r\n if (!parsed || !table) return { table: null, columns: [] }\r\n const known = new Set(table.columns.map((column) => column.name))\r\n return { table, columns: parsed.columns.filter((column) => known.has(column)) }\r\n })\r\n const [table, setTable] = useState<SchemaTable | null>(initial.table)\r\n const [selected, setSelected] = useState<string[]>(initial.columns)\r\n const [search, setSearch] = useState('')\r\n\r\n const visible = useMemo(() => {\r\n const lower = search.trim().toLowerCase()\r\n return (table?.columns ?? []).filter((column) => column.name.toLowerCase().includes(lower))\r\n }, [table, search])\r\n\r\n // Na ordem da tabela, não na ordem em que foram marcadas\r\n const ordered = (table?.columns ?? [])\r\n .map((column) => column.name)\r\n .filter((name) => selected.includes(name))\r\n const result = table ? buildSelect(table.name, ordered) : ''\r\n const allVisible = visible.length > 0 && visible.every((column) => selected.includes(column.name))\r\n\r\n const toggle = (name: string) =>\r\n setSelected((current) =>\r\n current.includes(name) ? current.filter((item) => item !== name) : [...current, name]\r\n )\r\n const toggleVisible = () => {\r\n const names = visible.map((column) => column.name)\r\n setSelected((current) =>\r\n allVisible\r\n ? current.filter((name) => !names.includes(name))\r\n : [...new Set([...current, ...names])]\r\n )\r\n }\r\n\r\n return (\r\n <>\r\n <DialogTitle sx={{ fontSize: 14 }}>Criar query</DialogTitle>\r\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>\r\n <Autocomplete\r\n size=\"small\"\r\n options={tables}\r\n value={table}\r\n onChange={(_, value) => {\r\n setTable(value)\r\n setSelected([])\r\n setSearch('')\r\n }}\r\n getOptionLabel={(option) => option.name}\r\n isOptionEqualToValue={(option, value) => option.name === value.name}\r\n noOptionsText={tables.length ? 'Nenhuma tabela' : 'Carregando as tabelas do banco…'}\r\n renderOption={({ key, ...props }, option) => (\r\n <Box\r\n component=\"li\"\r\n key={key}\r\n {...props}\r\n sx={{ gap: 2, fontFamily: MONO, fontSize: 12 }}\r\n >\r\n {option.name}\r\n <Box component=\"span\" sx={{ ml: 'auto', color: 'text.secondary', fontSize: 11 }}>\r\n {option.type} · {option.columns.length} colunas\r\n </Box>\r\n </Box>\r\n )}\r\n renderInput={(params) => <TextField {...params} label=\"tabela\" sx={{ mt: 1 }} />}\r\n />\r\n\r\n {table && (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={allVisible}\r\n indeterminate={!allVisible && visible.some((c) => selected.includes(c.name))}\r\n onChange={toggleVisible}\r\n />\r\n }\r\n label={<Typography sx={{ fontSize: 12 }}>Todas</Typography>}\r\n />\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n {selected.length} de {table.columns.length} marcadas\r\n {!selected.length && ' (nenhuma = *)'}\r\n </Typography>\r\n <TextField\r\n size=\"small\"\r\n placeholder=\"filtrar colunas\"\r\n value={search}\r\n onChange={(event) => setSearch(event.target.value)}\r\n sx={{ ml: 'auto', width: 200 }}\r\n />\r\n </Box>\r\n <Box\r\n sx={{\r\n maxHeight: 280,\r\n overflow: 'auto',\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 1,\r\n px: 1,\r\n display: 'grid',\r\n gridTemplateColumns: 'repeat(auto-fill, minmax(220px, 1fr))'\r\n }}\r\n >\r\n {visible.map((column) => (\r\n <FormControlLabel\r\n key={column.name}\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={selected.includes(column.name)}\r\n onChange={() => toggle(column.name)}\r\n />\r\n }\r\n label={\r\n <Box component=\"span\" sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {column.name}{' '}\r\n <Box component=\"span\" sx={{ color: 'text.secondary', fontSize: 11 }}>\r\n {column.type}\r\n </Box>\r\n </Box>\r\n }\r\n sx={{ m: 0, minWidth: 0 }}\r\n />\r\n ))}\r\n </Box>\r\n </Box>\r\n )}\r\n\r\n {result && (\r\n <Box\r\n component=\"pre\"\r\n sx={{\r\n m: 0,\r\n p: 1,\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 1,\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n maxHeight: 200,\r\n overflow: 'auto'\r\n }}\r\n >\r\n <HighlightedSql code={result} />\r\n </Box>\r\n )}\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={onClose}>Cancelar</Button>\r\n <Button\r\n variant=\"contained\"\r\n disabled={!table}\r\n onClick={() => {\r\n onApply(result)\r\n onClose()\r\n }}\r\n title=\"Substitui o SQL atual\"\r\n >\r\n Usar no SQL\r\n </Button>\r\n </DialogActions>\r\n </>\r\n )\r\n}\r\n","import { quote } from './QueryBuilder'\r\n\r\n/**\r\n * Templates de query do editor de SQL (\"Importar template\"): consultas prontas montadas a partir de\r\n * uma tabela (do banco ou do modelo) e de uma coluna dela.\r\n */\r\n\r\n/** De onde o template lê: uma tabela do banco (nome) ou do modelo (o SQL dela, como subconsulta). */\r\nexport type TemplateSource = { kind: 'database'; table: string } | { kind: 'model'; sql: string }\r\n\r\nexport type QueryTemplate = {\r\n id: string\r\n label: string\r\n description: string\r\n /** Rótulo do campo da coluna no diálogo. */\r\n columnLabel: string\r\n /** Tipos do banco sugeridos primeiro na lista de colunas. */\r\n preferredTypes?: RegExp\r\n build: (source: TemplateSource, column: string) => string\r\n}\r\n\r\n/**\r\n * `WITH` da origem: a tabela do banco entra pelo nome; o SQL de uma tabela do modelo vira o CTE\r\n * `origem`, antes dos CTEs do template.\r\n */\r\nfunction withSource(source: TemplateSource): { ctes: string[]; from: string } {\r\n if (source.kind === 'database') return { ctes: [], from: quote(source.table) }\r\n const sql = source.sql.trim().replace(/;+\\s*$/, '')\r\n return { ctes: [`origem AS (\\n${sql.replace(/^/gm, ' ')}\\n)`], from: 'origem' }\r\n}\r\n\r\n/**\r\n * Um dia por linha, do menor ao maior valor da coluna, com ano e mês. É a tabela \"Calendário\" do\r\n * Power BI: relacione a coluna de data da fato com `dia`.\r\n *\r\n * Não é um `WITH RECURSIVE` de um dia por iteração: o MySQL (`cte_max_recursion_depth`) e o MariaDB\r\n * (`max_recursive_iterations`) param em 1000 iterações, e o MariaDB corta em silêncio — o calendário\r\n * acabaria ~2,7 anos depois do início. A recursão só gera 0–999 e o dia sai de `mil * 1000 + n`.\r\n */\r\nexport function calendarSql(source: TemplateSource, column: string) {\r\n const { ctes, from } = withSource(source)\r\n const col = quote(column)\r\n const parts = [\r\n ...ctes,\r\n [\r\n 'limites AS (',\r\n ` SELECT DATE(MIN(${col})) AS inicio, DATE(MAX(${col})) AS fim`,\r\n ` FROM ${from}`,\r\n ')'\r\n ],\r\n [\r\n 'numeros AS (',\r\n ' SELECT 0 AS n',\r\n ' UNION ALL',\r\n ' SELECT n + 1 FROM numeros WHERE n < 999',\r\n ')'\r\n ],\r\n [\r\n 'dias AS (',\r\n ' SELECT inicio + INTERVAL (mil.n * 1000 + numeros.n) DAY AS dia',\r\n ' FROM limites, numeros mil, numeros',\r\n ' WHERE mil.n <= DATEDIFF(fim, inicio) DIV 1000',\r\n ' AND mil.n * 1000 + numeros.n <= DATEDIFF(fim, inicio)',\r\n ')'\r\n ]\r\n ].map((part) => (Array.isArray(part) ? part.join('\\n') : part))\r\n return [\r\n `WITH RECURSIVE ${parts.join(',\\n')}`,\r\n 'SELECT',\r\n ' dia,',\r\n ' YEAR(dia) AS ano,',\r\n ' MONTH(dia) AS mes',\r\n 'FROM dias'\r\n ].join('\\n')\r\n}\r\n\r\nexport const QUERY_TEMPLATES: QueryTemplate[] = [\r\n {\r\n id: 'calendar',\r\n label: 'Calendário',\r\n description:\r\n 'Um dia por linha (com ano e mês) entre a menor e a maior data da coluna. Relacione a data da fato com `dia`.',\r\n columnLabel: 'coluna de data',\r\n preferredTypes: /date|time/i,\r\n build: calendarSql\r\n }\r\n]\r\n","import {\r\n Autocomplete,\r\n Box,\r\n Button,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n MenuItem,\r\n TextField,\r\n Typography\r\n} from '@mui/material'\r\nimport { useMemo, useState } from 'react'\r\nimport type { SchemaTable } from '../types'\r\nimport { QUERY_TEMPLATES, type TemplateSource } from './queryTemplateDefs'\r\nimport { HighlightedSql } from './sqlHighlight'\r\nimport { MONO } from './ui'\r\n\r\n/**\r\n * \"Importar template\": escolhe um template de query (`QUERY_TEMPLATES`), a tabela de origem (do\r\n * modelo ou do banco) e a coluna, e substitui o SQL pelo que o template monta.\r\n */\r\n\r\ntype Props = {\r\n open: boolean\r\n onClose: () => void\r\n /** Tabelas e views do banco (vazio enquanto carrega). */\r\n tables: SchemaTable[]\r\n /** SQL e colunas de cada tabela do modelo. */\r\n modelTables: Record<string, { sql: string; columns: string[] }>\r\n onApply: (sql: string) => void\r\n}\r\n\r\ntype SourceOption = {\r\n key: string\r\n name: string\r\n group: string\r\n columns: { name: string; type?: string }[]\r\n source: TemplateSource\r\n}\r\n\r\nexport function QueryTemplates({ open, onClose, ...props }: Props) {\r\n return (\r\n <Dialog open={open} onClose={onClose} maxWidth=\"md\" fullWidth>\r\n {/* Remonta a cada abertura: começa vazio */}\r\n {open && <Templates onClose={onClose} {...props} />}\r\n </Dialog>\r\n )\r\n}\r\n\r\nfunction Templates({ tables, modelTables, onClose, onApply }: Omit<Props, 'open'>) {\r\n const [templateId, setTemplateId] = useState(QUERY_TEMPLATES[0].id)\r\n const [source, setSource] = useState<SourceOption | null>(null)\r\n const [column, setColumn] = useState<string | null>(null)\r\n const template = QUERY_TEMPLATES.find((item) => item.id === templateId) ?? QUERY_TEMPLATES[0]\r\n\r\n const sources = useMemo<SourceOption[]>(\r\n () => [\r\n ...Object.entries(modelTables).map(([name, table]) => ({\r\n key: `model:${name}`,\r\n name,\r\n group: 'Tabelas do modelo',\r\n columns: table.columns.map((column) => ({ name: column })),\r\n source: { kind: 'model' as const, sql: table.sql }\r\n })),\r\n ...tables.map((table) => ({\r\n key: `database:${table.name}`,\r\n name: table.name,\r\n group: 'Tabelas do banco',\r\n columns: table.columns,\r\n source: { kind: 'database' as const, table: table.name }\r\n }))\r\n ],\r\n [tables, modelTables]\r\n )\r\n\r\n // As do tipo sugerido pelo template (datas, no calendário) primeiro\r\n const columns = useMemo(() => {\r\n const list = source?.columns ?? []\r\n const preferred = (type?: string) => !!type && !!template.preferredTypes?.test(type)\r\n return [...list.filter((c) => preferred(c.type)), ...list.filter((c) => !preferred(c.type))]\r\n }, [source, template])\r\n\r\n const result = source && column ? template.build(source.source, column) : ''\r\n\r\n return (\r\n <>\r\n <DialogTitle sx={{ fontSize: 14 }}>Importar template</DialogTitle>\r\n <DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>\r\n <TextField\r\n select\r\n size=\"small\"\r\n label=\"template\"\r\n value={template.id}\r\n onChange={(event) => setTemplateId(event.target.value)}\r\n helperText={template.description}\r\n sx={{ mt: 1 }}\r\n >\r\n {QUERY_TEMPLATES.map((item) => (\r\n <MenuItem key={item.id} value={item.id}>\r\n {item.label}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n\r\n <Autocomplete\r\n size=\"small\"\r\n options={sources}\r\n value={source}\r\n onChange={(_, value) => {\r\n setSource(value)\r\n setColumn(null)\r\n }}\r\n groupBy={(option) => option.group}\r\n getOptionLabel={(option) => option.name}\r\n isOptionEqualToValue={(option, value) => option.key === value.key}\r\n noOptionsText=\"Nenhuma tabela\"\r\n renderOption={({ key, ...props }, option) => (\r\n <Box\r\n component=\"li\"\r\n key={key}\r\n {...props}\r\n sx={{ gap: 2, fontFamily: MONO, fontSize: 12 }}\r\n >\r\n {option.name}\r\n <Box component=\"span\" sx={{ ml: 'auto', color: 'text.secondary', fontSize: 11 }}>\r\n {option.columns.length} colunas\r\n </Box>\r\n </Box>\r\n )}\r\n renderInput={(params) => <TextField {...params} label=\"tabela\" />}\r\n />\r\n\r\n {source && (\r\n <Autocomplete\r\n size=\"small\"\r\n options={columns.map((item) => item.name)}\r\n value={column}\r\n onChange={(_, value) => setColumn(value)}\r\n noOptionsText={\r\n source.source.kind === 'model'\r\n ? 'Sem colunas: valide o SQL dessa tabela'\r\n : 'Nenhuma coluna'\r\n }\r\n renderOption={({ key, ...props }, name) => (\r\n <Box\r\n component=\"li\"\r\n key={key}\r\n {...props}\r\n sx={{ gap: 2, fontFamily: MONO, fontSize: 12 }}\r\n >\r\n {name}\r\n <Box component=\"span\" sx={{ ml: 'auto', color: 'text.secondary', fontSize: 11 }}>\r\n {columns.find((item) => item.name === name)?.type}\r\n </Box>\r\n </Box>\r\n )}\r\n renderInput={(params) => <TextField {...params} label={template.columnLabel} />}\r\n />\r\n )}\r\n\r\n {result ? (\r\n <Box\r\n component=\"pre\"\r\n sx={{\r\n m: 0,\r\n p: 1,\r\n border: 1,\r\n borderColor: 'divider',\r\n borderRadius: 1,\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n maxHeight: 280,\r\n overflow: 'auto'\r\n }}\r\n >\r\n <HighlightedSql code={result} />\r\n </Box>\r\n ) : (\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n Escolha a tabela e a coluna para ver o SQL.\r\n </Typography>\r\n )}\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={onClose}>Cancelar</Button>\r\n <Button\r\n variant=\"contained\"\r\n disabled={!result}\r\n onClick={() => {\r\n onApply(result)\r\n onClose()\r\n }}\r\n title=\"Substitui o SQL atual\"\r\n >\r\n Usar no SQL\r\n </Button>\r\n </DialogActions>\r\n </>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Button,\r\n Chip,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n MenuItem,\r\n MenuList,\r\n Paper,\r\n Popper,\r\n TextField\r\n} from '@mui/material'\r\nimport { createContext, useContext, useRef, useState } from 'react'\r\nimport type { SchemaTable, SqlTestResult } from '../types'\r\nimport { QueryBuilder } from './QueryBuilder'\r\nimport { QueryTemplates } from './QueryTemplates'\r\nimport { HighlightedSql } from './sqlHighlight'\r\nimport { errorMessage } from './store'\r\nimport { MONO, ResultTable } from './ui'\r\n\r\n/**\r\n * Campo de SQL com destaque de sintaxe e autocomplete de tabelas e colunas. As colunas vêm do\r\n * `information_schema` (tabelas/views do banco) e das colunas de cada tabela do modelo (lidas do banco).\r\n * O ⤢ abre o mesmo SQL num editor grande; com `queryTools`, ele traz \"Criar query\" (escolher tabela e\r\n * colunas do banco), \"Importar template\" (calendário etc.) e \"Validar SQL\" (executa no banco e\r\n * mostra uma amostra).\r\n *\r\n * O destaque é um `<pre>` colorido por baixo do `<textarea>` de texto transparente: mesma fonte,\r\n * mesmo recuo e mesma quebra de linha, com a rolagem sincronizada. O cursor, a seleção e o\r\n * autocomplete continuam sendo do textarea.\r\n */\r\n\r\n// Recuo do texto dentro do campo (o lado direito abre espaço para o ⤢)\r\nconst PAD = { top: 8.5, right: 30, bottom: 8.5, left: 12 }\r\nconst LINE_HEIGHT = '18px'\r\n\r\nexport type SqlCompletions = {\r\n tables: SchemaTable[]\r\n /** Colunas de cada tabela do modelo (`tabela.` completa com elas). */\r\n modelColumns: Record<string, string[]>\r\n /** SQL de cada tabela do modelo (origem do \"Importar template\"). */\r\n modelSql?: Record<string, string>\r\n /** Executa o SQL no banco com poucas linhas (\"Validar SQL\" do editor grande). */\r\n testSql?: (sql: string) => Promise<SqlTestResult>\r\n}\r\n\r\nexport const SqlCompletionsContext = createContext<SqlCompletions>({\r\n tables: [],\r\n modelColumns: {}\r\n})\r\n\r\ntype Suggestion = { text: string; detail: string }\r\n\r\nconst KEYWORDS = new Set(\r\n 'WHERE ON LEFT RIGHT INNER OUTER JOIN GROUP ORDER LIMIT USING AND OR AS SET HAVING UNION'.split(\r\n ' '\r\n )\r\n)\r\n\r\n/** `alias -> tabela` a partir dos `FROM x a` / `JOIN x AS a` do texto. */\r\nfunction aliases(sql: string) {\r\n const map = new Map<string, string>()\r\n for (const match of sql.matchAll(/\\b(?:FROM|JOIN)\\s+`?(\\w+)`?(?:\\s+(?:AS\\s+)?`?(\\w+)`?)?/gi)) {\r\n const [, table, alias] = match\r\n map.set(table.toLowerCase(), table)\r\n if (alias && !KEYWORDS.has(alias.toUpperCase())) map.set(alias.toLowerCase(), table)\r\n }\r\n return map\r\n}\r\n\r\nfunction suggest(sql: string, caret: number, completions: SqlCompletions) {\r\n const before = sql.slice(0, caret)\r\n const tables = new Map(completions.tables.map((table) => [table.name.toLowerCase(), table]))\r\n const columnsOf = (table: string): Suggestion[] =>\r\n tables.get(table.toLowerCase())?.columns.map((column) => ({\r\n text: column.name,\r\n detail: column.type\r\n })) ?? []\r\n\r\n let prefix: string\r\n let candidates: Suggestion[]\r\n const qualified = /([A-Za-z_]\\w*)\\.(\\w*)$/.exec(before)\r\n if (qualified) {\r\n const [, qualifier, typed] = qualified\r\n prefix = typed\r\n if (completions.modelColumns[qualifier])\r\n candidates = completions.modelColumns[qualifier].map((text) => ({ text, detail: qualifier }))\r\n else candidates = columnsOf(aliases(sql).get(qualifier.toLowerCase()) ?? qualifier)\r\n } else {\r\n const word = /[A-Za-z_]\\w*$/.exec(before)\r\n if (!word || word[0].length < 2) return null\r\n prefix = word[0]\r\n const referenced = [...new Set(aliases(sql).values())]\r\n candidates = [\r\n ...Object.keys(completions.modelColumns).map((text) => ({\r\n text,\r\n detail: 'tabela do modelo'\r\n })),\r\n ...completions.tables.map((table) => ({ text: table.name, detail: table.type })),\r\n ...referenced.flatMap(columnsOf)\r\n ]\r\n }\r\n\r\n const lower = prefix.toLowerCase()\r\n const seen = new Set<string>()\r\n const items = candidates\r\n .filter((item) => {\r\n const text = item.text.toLowerCase()\r\n if (seen.has(text) || text === lower || !text.includes(lower)) return false\r\n seen.add(text)\r\n return true\r\n })\r\n .sort(\r\n (a, b) =>\r\n Number(!a.text.toLowerCase().startsWith(lower)) -\r\n Number(!b.text.toLowerCase().startsWith(lower)) || a.text.localeCompare(b.text)\r\n )\r\n .slice(0, 8)\r\n return items.length ? { from: caret - prefix.length, items } : null\r\n}\r\n\r\ntype Props = {\r\n value: string\r\n onChange: (value: string) => void\r\n label?: string\r\n placeholder?: string\r\n minRows?: number\r\n maxRows?: number\r\n /** Erro do banco (validação). */\r\n error?: string\r\n warning?: string\r\n /** Mostra o ⤢ que abre o editor grande (desligado dentro do próprio editor grande). */\r\n expandable?: boolean\r\n /** O SQL é uma consulta inteira (tabela do modelo): o editor grande ganha \"Criar query\" e \"Validar SQL\". */\r\n queryTools?: boolean\r\n}\r\n\r\nexport function SqlEditor({\r\n value,\r\n onChange,\r\n label,\r\n placeholder = 'SQL',\r\n minRows,\r\n maxRows = 6,\r\n error,\r\n warning,\r\n expandable = true,\r\n queryTools = false\r\n}: Props) {\r\n const completions = useContext(SqlCompletionsContext)\r\n const anchor = useRef<HTMLDivElement>(null)\r\n const input = useRef<HTMLTextAreaElement>(null)\r\n const highlight = useRef<HTMLPreElement>(null)\r\n const [expanded, setExpanded] = useState(false)\r\n const [building, setBuilding] = useState(false)\r\n const [importing, setImporting] = useState(false)\r\n // Resultado do \"Validar SQL\"; vale só para o SQL que foi testado\r\n const [test, setTest] = useState<{\r\n sql: string\r\n result?: SqlTestResult\r\n error?: string\r\n } | null>(null)\r\n const [testing, setTesting] = useState(false)\r\n const currentTest = test?.sql === value ? test : null\r\n const testSql = completions.testSql\r\n\r\n const runTest = async () => {\r\n if (!testSql) return\r\n const sql = value\r\n setTesting(true)\r\n try {\r\n setTest({ sql, result: await testSql(sql) })\r\n } catch (error) {\r\n setTest({ sql, error: errorMessage(error) })\r\n } finally {\r\n setTesting(false)\r\n }\r\n }\r\n const [state, setState] = useState<{ from: number; items: Suggestion[]; index: number } | null>(\r\n null\r\n )\r\n\r\n const accept = (item: Suggestion) => {\r\n const element = input.current\r\n if (!element || !state) return\r\n const caret = element.selectionStart\r\n const next = value.slice(0, state.from) + item.text + value.slice(caret)\r\n onChange(next)\r\n setState(null)\r\n const position = state.from + item.text.length\r\n requestAnimationFrame(() => {\r\n element.focus()\r\n element.setSelectionRange(position, position)\r\n })\r\n }\r\n\r\n return (\r\n <>\r\n <TextField\r\n ref={anchor}\r\n inputRef={input}\r\n size=\"small\"\r\n fullWidth\r\n multiline\r\n label={label}\r\n minRows={minRows}\r\n maxRows={maxRows}\r\n value={value}\r\n placeholder={placeholder}\r\n error={!value.trim() || !!error}\r\n helperText={error ?? warning}\r\n onChange={(event) => {\r\n onChange(event.target.value)\r\n const found = suggest(event.target.value, event.target.selectionStart ?? 0, completions)\r\n setState(found && { ...found, index: 0 })\r\n }}\r\n onKeyDown={(event) => {\r\n if (!state) return\r\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\r\n event.preventDefault()\r\n const step = event.key === 'ArrowDown' ? 1 : -1\r\n setState({\r\n ...state,\r\n index: (state.index + step + state.items.length) % state.items.length\r\n })\r\n } else if (event.key === 'Enter' || event.key === 'Tab') {\r\n event.preventDefault()\r\n accept(state.items[state.index])\r\n } else if (event.key === 'Escape') {\r\n event.stopPropagation()\r\n setState(null)\r\n }\r\n }}\r\n onBlur={() => setState(null)}\r\n slotProps={{\r\n htmlInput: {\r\n spellCheck: false,\r\n onScroll: (event: React.UIEvent<HTMLTextAreaElement>) => {\r\n if (highlight.current) highlight.current.scrollTop = event.currentTarget.scrollTop\r\n }\r\n },\r\n input: {\r\n endAdornment: (\r\n <>\r\n <Box\r\n component=\"pre\"\r\n ref={highlight}\r\n aria-hidden\r\n sx={{\r\n ...textSx,\r\n // Exatamente sobre a caixa do textarea: recorta a rolagem no mesmo lugar\r\n m: 0,\r\n p: 0,\r\n position: 'absolute',\r\n top: PAD.top,\r\n right: PAD.right,\r\n bottom: PAD.bottom,\r\n left: PAD.left,\r\n overflow: 'hidden',\r\n pointerEvents: 'none',\r\n color: 'text.primary'\r\n }}\r\n >\r\n <HighlightedSql code={value} />\r\n {/* Linha final vazia: o textarea mostra, o <pre> sem isso esconderia */}\r\n {'\\n'}\r\n </Box>\r\n {expandable && (\r\n <Box\r\n component=\"button\"\r\n type=\"button\"\r\n title=\"Expandir o SQL\"\r\n aria-label=\"Expandir o SQL\"\r\n onClick={() => setExpanded(true)}\r\n sx={{\r\n position: 'absolute',\r\n top: 4,\r\n right: 4,\r\n zIndex: 2,\r\n border: 0,\r\n borderRadius: 0.5,\r\n bgcolor: 'transparent',\r\n color: 'text.secondary',\r\n cursor: 'pointer',\r\n fontSize: 14,\r\n lineHeight: 1,\r\n p: 0.25,\r\n '&:hover': { color: 'primary.main', bgcolor: 'rgba(255,255,255,.08)' }\r\n }}\r\n >\r\n ⤢\r\n </Box>\r\n )}\r\n </>\r\n )\r\n }\r\n }}\r\n sx={{\r\n '& .MuiInputBase-root': { ...padSx, position: 'relative', alignItems: 'flex-start' },\r\n '& textarea': {\r\n ...textSx,\r\n position: 'relative',\r\n zIndex: 1,\r\n color: 'transparent',\r\n caretColor: (theme) => theme.palette.text.primary,\r\n '&::placeholder': { color: 'text.disabled', opacity: 1 },\r\n '&::selection': { bgcolor: 'rgba(245,130,32,.35)' }\r\n },\r\n '& .MuiFormHelperText-root': {\r\n fontFamily: MONO,\r\n color: error ? 'error.main' : 'warning.main'\r\n }\r\n }}\r\n />\r\n {expandable && (\r\n <Dialog open={expanded} onClose={() => setExpanded(false)} maxWidth=\"lg\" fullWidth>\r\n <DialogTitle sx={{ fontSize: 14 }}>{label ?? 'SQL'}</DialogTitle>\r\n <DialogContent>\r\n <Box sx={{ pt: 1 }}>\r\n <SqlEditor\r\n value={value}\r\n onChange={onChange}\r\n placeholder={placeholder}\r\n minRows={20}\r\n maxRows={36}\r\n error={error}\r\n warning={warning}\r\n expandable={false}\r\n />\r\n </Box>\r\n {currentTest?.error && (\r\n <Alert severity=\"error\" sx={{ mt: 1, fontFamily: MONO, fontSize: 12 }}>\r\n {currentTest.error}\r\n </Alert>\r\n )}\r\n {currentTest?.result && (\r\n <Box sx={{ mt: 1, display: 'flex', flexDirection: 'column', gap: 1 }}>\r\n <Box>\r\n <Chip\r\n color=\"success\"\r\n size=\"small\"\r\n label={`SQL válido · ${currentTest.result.columns.length} colunas · ${currentTest.result.durationMs} ms`}\r\n />\r\n </Box>\r\n <ResultTable rows={currentTest.result.rows} maxHeight={240} />\r\n </Box>\r\n )}\r\n </DialogContent>\r\n <DialogActions>\r\n {queryTools && (\r\n <>\r\n <Button onClick={() => setBuilding(true)} title=\"Escolher a tabela e as colunas\">\r\n Criar query\r\n </Button>\r\n <Button\r\n onClick={() => setImporting(true)}\r\n title=\"Calendário e outras queries prontas\"\r\n >\r\n Importar template\r\n </Button>\r\n {testSql && (\r\n <Button\r\n disabled={!value.trim() || testing}\r\n onClick={runTest}\r\n title=\"Executa o SQL no banco e mostra as primeiras linhas\"\r\n >\r\n {testing ? 'Validando…' : 'Validar SQL'}\r\n </Button>\r\n )}\r\n </>\r\n )}\r\n <Box sx={{ flex: 1 }} />\r\n <Button onClick={() => setExpanded(false)}>Fechar</Button>\r\n </DialogActions>\r\n </Dialog>\r\n )}\r\n {queryTools && (\r\n <QueryBuilder\r\n open={building}\r\n onClose={() => setBuilding(false)}\r\n tables={completions.tables}\r\n sql={value}\r\n onApply={onChange}\r\n />\r\n )}\r\n {queryTools && (\r\n <QueryTemplates\r\n open={importing}\r\n onClose={() => setImporting(false)}\r\n tables={completions.tables}\r\n modelTables={Object.fromEntries(\r\n Object.entries(completions.modelSql ?? {}).map(([name, sql]) => [\r\n name,\r\n { sql, columns: completions.modelColumns[name] ?? [] }\r\n ])\r\n )}\r\n onApply={onChange}\r\n />\r\n )}\r\n <Popper\r\n open={!!state}\r\n anchorEl={anchor.current}\r\n placement=\"bottom-start\"\r\n sx={{ zIndex: 1400 }}\r\n >\r\n <Paper elevation={8}>\r\n <MenuList dense>\r\n {state?.items.map((item, index) => (\r\n <MenuItem\r\n key={item.text}\r\n selected={index === state.index}\r\n // mousedown: antes do blur do campo fechar a lista\r\n onMouseDown={(event) => {\r\n event.preventDefault()\r\n accept(item)\r\n }}\r\n sx={{ gap: 2, fontFamily: MONO, fontSize: 12 }}\r\n >\r\n {item.text}\r\n <Box component=\"span\" sx={{ ml: 'auto', color: 'text.secondary', fontSize: 11 }}>\r\n {item.detail}\r\n </Box>\r\n </MenuItem>\r\n ))}\r\n </MenuList>\r\n </Paper>\r\n </Popper>\r\n </>\r\n )\r\n}\r\n\r\n/** Tudo que muda a posição dos caracteres: igual no textarea e no <pre> colorido. */\r\nconst textSx = {\r\n fontFamily: MONO,\r\n fontSize: 12,\r\n lineHeight: LINE_HEIGHT,\r\n letterSpacing: 0,\r\n whiteSpace: 'pre-wrap',\r\n overflowWrap: 'break-word',\r\n wordBreak: 'normal',\r\n tabSize: 2,\r\n // Mesma largura útil com ou sem barra de rolagem\r\n scrollbarGutter: 'stable'\r\n} as const\r\n\r\nconst padSx = {\r\n padding: `${PAD.top}px ${PAD.right}px ${PAD.bottom}px ${PAD.left}px`\r\n}\r\n","import { Box, MenuItem, TextField, Typography } from '@mui/material'\r\nimport { AGGREGATION_LABEL, AGGREGATIONS, isAggregate, VALUE_FORMATS } from '../model'\r\nimport type { MeasureRow } from './modelCode'\r\nimport { SqlEditor } from './SqlEditor'\r\nimport { MONO } from './ui'\r\n\r\n/** Campos do editor do modelo, usados pela tabela e pelo painel de propriedades do diagrama. */\r\n\r\nexport const inputSx = { '& .MuiInputBase-input': { fontFamily: MONO, fontSize: 12 } }\r\n\r\nexport const MEASURE_TYPES: { value: MeasureRow['type']; label: string }[] = [\r\n ...AGGREGATIONS.map((value) => ({ value, label: `${value} · ${AGGREGATION_LABEL[value]}` })),\r\n { value: 'ratio', label: 'ratio · Razão' },\r\n { value: 'formula', label: 'formula · Fórmula' }\r\n]\r\n\r\nexport function NameField({\r\n value,\r\n onChange,\r\n onBlur,\r\n label\r\n}: {\r\n value: string\r\n onChange: (value: string) => void\r\n onBlur?: () => void\r\n label?: string\r\n}) {\r\n return (\r\n <TextField\r\n size=\"small\"\r\n fullWidth\r\n label={label}\r\n value={value}\r\n placeholder=\"nome\"\r\n error={!/^[A-Za-z_][A-Za-z0-9_]*$/.test(value)}\r\n onChange={(e) => onChange(e.target.value)}\r\n onBlur={onBlur}\r\n onKeyDown={(e) => {\r\n if (e.key === 'Enter') (e.target as HTMLInputElement).blur()\r\n }}\r\n sx={inputSx}\r\n />\r\n )\r\n}\r\n\r\nexport function MeasureSelect({\r\n value,\r\n options,\r\n onChange\r\n}: {\r\n value: string\r\n options: string[]\r\n onChange: (value: string) => void\r\n}) {\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={options.includes(value) ? value : ''}\r\n error={!options.includes(value)}\r\n onChange={(e) => onChange(e.target.value)}\r\n sx={{ ...inputSx, minWidth: 140, flex: 1 }}\r\n >\r\n {options.map((name) => (\r\n <MenuItem key={name} value={name}>\r\n {name}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )\r\n}\r\n\r\nexport function MeasureTypeSelect({\r\n value,\r\n onChange\r\n}: {\r\n value: MeasureRow['type']\r\n onChange: (value: MeasureRow['type']) => void\r\n}) {\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n fullWidth\r\n value={value}\r\n onChange={(e) => onChange(e.target.value as MeasureRow['type'])}\r\n sx={inputSx}\r\n >\r\n {MEASURE_TYPES.map((type) => (\r\n <MenuItem key={type.value} value={type.value}>\r\n {type.label}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )\r\n}\r\n\r\n/** Definição da medida conforme o tipo: SQL da soma, as duas medidas da razão ou a fórmula. */\r\nexport function MeasureDefinition({\r\n row,\r\n measureNames,\r\n error,\r\n onPatch\r\n}: {\r\n row: MeasureRow\r\n measureNames: string[]\r\n error?: string\r\n onPatch: (changes: Partial<MeasureRow>) => void\r\n}) {\r\n const others = measureNames.filter((name) => name !== row.name)\r\n if (isAggregate(row))\r\n return (\r\n <SqlEditor\r\n value={row.sql}\r\n placeholder={\r\n row.type === 'count' || row.type === 'countDistinct'\r\n ? 'tabela.coluna (conta os valores não nulos)'\r\n : 'tabela.coluna'\r\n }\r\n error={error}\r\n onChange={(sql) => onPatch({ sql })}\r\n />\r\n )\r\n if (row.type === 'formula')\r\n return (\r\n <SqlEditor\r\n value={row.expression}\r\n placeholder=\"COALESCE({medidaA}, 0) + COALESCE({medidaB}, 0)\"\r\n error={error}\r\n warning={others.length ? `medidas: ${others.map((name) => `{${name}}`).join(' ')}` : ''}\r\n onChange={(expression) => onPatch({ expression })}\r\n />\r\n )\r\n return (\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>\r\n <MeasureSelect\r\n value={row.numerator}\r\n options={others}\r\n onChange={(numerator) => onPatch({ numerator })}\r\n />\r\n <Typography sx={{ fontFamily: MONO }}>/</Typography>\r\n <MeasureSelect\r\n value={row.denominator}\r\n options={others}\r\n onChange={(denominator) => onPatch({ denominator })}\r\n />\r\n </Box>\r\n )\r\n}\r\n\r\nexport function FormatFields({\r\n row,\r\n onPatch\r\n}: {\r\n row: MeasureRow\r\n onPatch: (changes: Partial<MeasureRow>) => void\r\n}) {\r\n return (\r\n <Box sx={{ display: 'flex', gap: 0.5 }}>\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={row.format}\r\n onChange={(e) => onPatch({ format: e.target.value as MeasureRow['format'] })}\r\n sx={{ ...inputSx, flex: 1 }}\r\n slotProps={{ select: { displayEmpty: true } }}\r\n >\r\n <MenuItem value=\"\">\r\n <em>padrão</em>\r\n </MenuItem>\r\n {VALUE_FORMATS.map((format) => (\r\n <MenuItem key={format} value={format}>\r\n {format}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n <TextField\r\n size=\"small\"\r\n placeholder=\"casas\"\r\n value={row.decimals}\r\n error={!!row.decimals.trim() && !/^\\d+$/.test(row.decimals.trim())}\r\n onChange={(e) => onPatch({ decimals: e.target.value })}\r\n sx={{ ...inputSx, width: 64 }}\r\n />\r\n </Box>\r\n )\r\n}\r\n\r\nexport function DictionaryFields({\r\n row,\r\n onPatch\r\n}: {\r\n row: { label: string; description: string }\r\n onPatch: (changes: { label?: string; description?: string }) => void\r\n}) {\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>\r\n <TextField\r\n size=\"small\"\r\n placeholder=\"rótulo\"\r\n value={row.label}\r\n onChange={(e) => onPatch({ label: e.target.value })}\r\n sx={inputSx}\r\n />\r\n <TextField\r\n size=\"small\"\r\n placeholder=\"descrição\"\r\n multiline\r\n maxRows={4}\r\n value={row.description}\r\n onChange={(e) => onPatch({ description: e.target.value })}\r\n sx={inputSx}\r\n />\r\n </Box>\r\n )\r\n}\r\n","import {\r\n Box,\r\n Checkbox,\r\n MenuItem,\r\n TextField,\r\n ToggleButton,\r\n ToggleButtonGroup,\r\n Typography\r\n} from '@mui/material'\r\nimport { useState } from 'react'\r\nimport type { ModelColumns } from '../types'\r\nimport { type DimensionRow, type EditorModel, emptyDimension, freeName } from './modelCode'\r\nimport { inputSx } from './modelFields'\r\nimport { SqlEditor } from './SqlEditor'\r\nimport { MONO } from './ui'\r\n\r\n/**\r\n * Modo simples das dimensões: marcar as colunas da tabela que viram dimensão. Marcar cria\r\n * `tabela.coluna` (tipo pelo valor lido do banco); desmarcar remove a dimensão que é exatamente\r\n * essa coluna. Dimensão com SQL próprio (`YEAR(tabela.data)`) não aparece marcada aqui — essa se\r\n * edita no painel dela.\r\n */\r\n\r\n/** `tabela.coluna` puro (o que o modo simples sabe editar). */\r\nexport const SIMPLE_DIMENSION = /^\\s*([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z_][A-Za-z0-9_]*)\\s*$/\r\n\r\ntype Props = {\r\n editor: EditorModel\r\n setEditor: (update: (current: EditorModel) => EditorModel) => void\r\n columns: ModelColumns | null\r\n table: string\r\n /** Abre a dimensão no painel. */\r\n onOpen: (uid: string) => void\r\n}\r\n\r\nexport function DimensionPicker({ editor, setEditor, columns, table, onOpen }: Props) {\r\n const [search, setSearch] = useState('')\r\n const loaded = columns?.tables[table]\r\n if (!loaded)\r\n return (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled' }}>\r\n Colunas ainda não lidas: use \"Recarregar colunas\".\r\n </Typography>\r\n )\r\n\r\n const numeric = new Set(columns?.numeric ?? [])\r\n const dimensionsOf = (column: string) =>\r\n editor.dimensions.filter((row) => {\r\n const match = SIMPLE_DIMENSION.exec(row.sql)\r\n return match?.[1] === table && match[2] === column\r\n })\r\n\r\n const toggle = (column: string, checked: boolean) =>\r\n setEditor((current) => {\r\n if (!checked) {\r\n const removed = new Set(dimensionsOf(column).map((row) => row.uid))\r\n return { ...current, dimensions: current.dimensions.filter((row) => !removed.has(row.uid)) }\r\n }\r\n const taken = [...current.dimensions, ...current.measures].map((row) => row.name)\r\n // Nome da coluna; se já existir, com a tabela na frente\r\n const name = taken.includes(column) ? freeName(`${table}_${column}`, taken) : column\r\n const dimension = emptyDimension({\r\n name,\r\n type: numeric.has(`${table}.${column}`) ? 'number' : 'string',\r\n sql: `${table}.${column}`\r\n })\r\n return { ...current, dimensions: [...current.dimensions, dimension] }\r\n })\r\n\r\n const visible = loaded.filter((column) => column.toLowerCase().includes(search.toLowerCase()))\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column' }}>\r\n {loaded.length > 10 && (\r\n <TextField\r\n size=\"small\"\r\n placeholder=\"filtrar colunas\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n sx={{ ...inputSx, mb: 0.5 }}\r\n />\r\n )}\r\n {visible.map((column) => {\r\n const existing = dimensionsOf(column)\r\n return (\r\n <Box\r\n key={column}\r\n component=\"label\"\r\n sx={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.5,\r\n fontSize: 12,\r\n fontFamily: MONO,\r\n cursor: 'pointer',\r\n borderRadius: 0.5,\r\n '&:hover': { bgcolor: 'rgba(255,255,255,.05)' }\r\n }}\r\n >\r\n <Checkbox\r\n size=\"small\"\r\n sx={{ p: 0.25 }}\r\n checked={!!existing.length}\r\n onChange={(e) => toggle(column, e.target.checked)}\r\n />\r\n <Box component=\"span\" sx={{ flex: 1 }}>\r\n {column}\r\n {numeric.has(`${table}.${column}`) && (\r\n <Box component=\"span\" sx={{ color: 'text.disabled', ml: 0.5 }}>\r\n Σ\r\n </Box>\r\n )}\r\n </Box>\r\n {existing.map((row) => (\r\n <Box\r\n key={row.uid}\r\n component=\"button\"\r\n type=\"button\"\r\n title=\"Abrir a dimensão\"\r\n onClick={(event) => {\r\n event.preventDefault()\r\n onOpen(row.uid)\r\n }}\r\n sx={{\r\n border: 0,\r\n bgcolor: 'transparent',\r\n color: '#a5d8ff',\r\n cursor: 'pointer',\r\n fontFamily: MONO,\r\n fontSize: 11,\r\n p: 0\r\n }}\r\n >\r\n ◇ {row.name || 'sem nome'}\r\n </Box>\r\n ))}\r\n </Box>\r\n )\r\n })}\r\n </Box>\r\n )\r\n}\r\n\r\nconst PARTIAL = /^\\s*([A-Za-z_][A-Za-z0-9_]*)\\.([A-Za-z0-9_]*)\\s*$/\r\n\r\n/**\r\n * Origem de uma dimensão: no modo simples, tabela + coluna (vira `tabela.coluna`); no modo SQL, a\r\n * expressão livre (`YEAR(tabela.data)`, `CONCAT(...)`). Abre no simples quando o SQL é só a coluna.\r\n */\r\nexport function DimensionSource({\r\n row,\r\n editor,\r\n columns,\r\n error,\r\n warning,\r\n onPatch\r\n}: {\r\n row: DimensionRow\r\n editor: EditorModel\r\n columns: ModelColumns | null\r\n error?: string\r\n warning?: string\r\n onPatch: (changes: Partial<DimensionRow>) => void\r\n}) {\r\n const [mode, setMode] = useState<'simple' | 'sql'>(() =>\r\n !row.sql.trim() || PARTIAL.test(row.sql) ? 'simple' : 'sql'\r\n )\r\n const parsed = PARTIAL.exec(row.sql)\r\n const table = parsed?.[1] ?? ''\r\n const column = parsed?.[2] ?? ''\r\n const tableColumns = columns?.tables[table] ?? []\r\n const numeric = new Set(columns?.numeric ?? [])\r\n\r\n const choose = (nextTable: string, nextColumn: string) => {\r\n const changes: Partial<DimensionRow> = { sql: `${nextTable}.${nextColumn}` }\r\n if (nextColumn) {\r\n changes.type = numeric.has(`${nextTable}.${nextColumn}`) ? 'number' : 'string'\r\n // Nome ainda automático: acompanha a coluna\r\n if (!row.name || /^novaDimensao\\d*$/.test(row.name)) {\r\n const taken = [...editor.dimensions, ...editor.measures]\r\n .filter((item) => item.uid !== row.uid)\r\n .map((item) => item.name)\r\n changes.name = freeName(nextColumn, taken)\r\n }\r\n }\r\n onPatch(changes)\r\n }\r\n\r\n return (\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>\r\n <ToggleButtonGroup\r\n size=\"small\"\r\n exclusive\r\n value={mode}\r\n onChange={(_, next: 'simple' | 'sql' | null) => next && setMode(next)}\r\n >\r\n <ToggleButton value=\"simple\" sx={{ textTransform: 'none', py: 0.25, flex: 1 }}>\r\n Tabela e coluna\r\n </ToggleButton>\r\n <ToggleButton value=\"sql\" sx={{ textTransform: 'none', py: 0.25, flex: 1 }}>\r\n SQL\r\n </ToggleButton>\r\n </ToggleButtonGroup>\r\n {mode === 'simple' ? (\r\n <>\r\n {!parsed && row.sql.trim() && (\r\n <Typography sx={{ fontSize: 11, color: 'warning.main' }}>\r\n O SQL atual ({row.sql.trim()}) não é uma coluna só; escolher aqui substitui ele.\r\n </Typography>\r\n )}\r\n <Box sx={{ display: 'flex', gap: 1 }}>\r\n <TextField\r\n select\r\n size=\"small\"\r\n label=\"tabela\"\r\n value={editor.tables.some((item) => item.name === table) ? table : ''}\r\n onChange={(e) =>\r\n choose(\r\n e.target.value,\r\n columns?.tables[e.target.value]?.includes(column) ? column : ''\r\n )\r\n }\r\n sx={{ ...inputSx, flex: 1 }}\r\n >\r\n {editor.tables.map((item) => (\r\n <MenuItem key={item.uid} value={item.name}>\r\n {item.name}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n {tableColumns.length ? (\r\n <TextField\r\n select\r\n size=\"small\"\r\n label=\"coluna\"\r\n value={tableColumns.includes(column) ? column : ''}\r\n error={!!error}\r\n onChange={(e) => choose(table, e.target.value)}\r\n sx={{ ...inputSx, flex: 1 }}\r\n >\r\n {tableColumns.map((name) => (\r\n <MenuItem key={name} value={name}>\r\n {name}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n ) : (\r\n // Colunas ainda não lidas: digita\r\n <TextField\r\n size=\"small\"\r\n label=\"coluna\"\r\n value={column}\r\n disabled={!table}\r\n onChange={(e) => choose(table, e.target.value)}\r\n sx={{ ...inputSx, flex: 1 }}\r\n />\r\n )}\r\n </Box>\r\n {(error || warning) && (\r\n <Typography\r\n sx={{ fontSize: 11, fontFamily: MONO, color: error ? 'error.main' : 'warning.main' }}\r\n >\r\n {error ?? warning}\r\n </Typography>\r\n )}\r\n </>\r\n ) : (\r\n <SqlEditor\r\n label=\"sql\"\r\n value={row.sql}\r\n error={error}\r\n warning={warning}\r\n onChange={(sql) => onPatch({ sql })}\r\n />\r\n )}\r\n </Box>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Button,\r\n Checkbox,\r\n Divider,\r\n FormControlLabel,\r\n IconButton,\r\n Menu,\r\n MenuItem,\r\n TextField,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport {\r\n type ChangeEvent,\r\n type FocusEvent,\r\n type KeyboardEvent,\r\n type MouseEvent as ReactMouseEvent,\r\n type ReactNode,\r\n useEffect,\r\n useMemo,\r\n useRef,\r\n useState,\r\n type WheelEvent\r\n} from 'react'\r\nimport { isAggregate } from '../model'\r\nimport { measureHome, modelEdges, referencedTables } from '../star'\r\nimport type { ModelColumns } from '../types'\r\nimport { DimensionPicker, DimensionSource } from './DimensionPicker'\r\nimport {\r\n type DimensionRow,\r\n type EditorModel,\r\n emptyDimension,\r\n emptyMeasure,\r\n freeName,\r\n fromEditor,\r\n type MeasureRow,\r\n newUid,\r\n type RelationshipRow,\r\n renameTable,\r\n type TableRow\r\n} from './modelCode'\r\nimport {\r\n DictionaryFields,\r\n FormatFields,\r\n inputSx,\r\n MeasureDefinition,\r\n MeasureTypeSelect,\r\n NameField\r\n} from './modelFields'\r\nimport { SqlEditor } from './SqlEditor'\r\nimport { MONO, Section } from './ui'\r\n\r\n/**\r\n * Diagrama do modelo, no estilo da \"Exibição de modelo\" do Power BI: um card por tabela (colunas,\r\n * dimensões e medidas que saem dela) e uma linha por relacionamento, com `*` no lado N e `1` no\r\n * lado 1. Edita o mesmo rascunho da tabela do editor.\r\n *\r\n * - arrastar o cabeçalho move o card; arrastar o fundo move a tela; Ctrl+roda dá zoom;\r\n * - arrastar uma coluna até a coluna de outra tabela cria o relacionamento (quem foi arrastado é o\r\n * lado N; de dimensão para fato, inverte sozinho);\r\n * - clicar num card, linha, dimensão ou medida abre as propriedades à direita; Delete remove;\r\n * - duplo clique no nome da tabela renomeia; botão direito no card ou campo abre editar/remover;\r\n * - os botões `+◇`/`+Σ` de uma coluna criam a dimensão/medida dela.\r\n *\r\n * As posições dos cards fazem parte do modelo (`diagram`) e vão para o arquivo ao salvar.\r\n */\r\n\r\ntype Props = {\r\n editor: EditorModel\r\n setEditor: (update: (current: EditorModel) => EditorModel) => void\r\n columns: ModelColumns | null\r\n /** Pedaços que o banco recusou (`table:<nome>`, `relationship:<i>`, `dimension:<nome>`...). */\r\n errors: Record<string, string>\r\n warnings: Record<string, string>\r\n loadingColumns: boolean\r\n onLoadColumns: () => void\r\n onTry: (selection: { dimensions: string[]; measures: string[] }) => void\r\n /** Consultas ativas que usam cada nome. */\r\n usage: Map<string, number>\r\n}\r\n\r\n/**\r\n * Papel da tabela, tirado dos relacionamentos (não é configurado): `one` só aparece no lado 1\r\n * (cadastro que filtra), `many` tem relacionamento saindo (lançamentos), `alone` não tem nenhum.\r\n */\r\ntype NodeRole = 'one' | 'many' | 'alone'\r\n\r\ntype ColumnItem = {\r\n kind: 'column'\r\n name: string\r\n numeric: boolean\r\n isKey: boolean\r\n linked: boolean\r\n /** Citada no modelo, mas a tabela (já lida do banco) não tem. */\r\n missing: boolean\r\n}\r\ntype FieldItem = { kind: 'dimension' | 'measure'; uid: string; name: string; icon: string }\r\ntype Item = ColumnItem | FieldItem\r\n\r\ntype DiagramNode = {\r\n /** Chave das posições: `uid` da tabela. */\r\n id: string\r\n uid: string\r\n name: string\r\n role: NodeRole\r\n /** Coluna única da tabela (`key`). */\r\n key: string\r\n items: Item[]\r\n error?: string\r\n}\r\n\r\ntype Selection =\r\n | { kind: 'table'; uid: string }\r\n | { kind: 'relationship'; uid: string }\r\n | { kind: 'dimension'; uid: string }\r\n | { kind: 'measure'; uid: string }\r\n | null\r\n\r\n/** O que o menu de contexto (botão direito) edita/remove. */\r\ntype MenuTarget = { kind: 'table' | 'dimension' | 'measure'; uid: string }\r\n\r\nconst TARGET_NAME: Record<MenuTarget['kind'], string> = {\r\n table: 'tabela',\r\n dimension: 'dimensão',\r\n measure: 'medida'\r\n}\r\n\r\ntype Point = { x: number; y: number }\r\n\r\n/** Põe uma medida calculada (fórmula) nova, com nome livre, no fim; devolve o `uid` dela. */\r\nfunction addFormulaTo(setEditor: Props['setEditor']) {\r\n const uid = newUid()\r\n setEditor((current) => {\r\n const taken = [...current.dimensions, ...current.measures].map((item) => item.name)\r\n const measure = emptyMeasure({ uid, type: 'formula', name: freeName('novaMedida', taken) })\r\n return { ...current, measures: [...current.measures, measure] }\r\n })\r\n return uid\r\n}\r\ntype View = { x: number; y: number; zoom: number }\r\n\r\nconst CARD_WIDTH = 230\r\nconst HEADER = 34\r\nconst ROW = 22\r\nconst MAX_BODY = 264\r\nconst PADDING = 4\r\n/** Limites do redimensionamento do card. */\r\nconst MIN_WIDTH = 160\r\nconst MAX_WIDTH = 800\r\nconst MIN_HEIGHT = HEADER + ROW + PADDING * 2\r\nconst MAX_HEIGHT = 1600\r\n\r\ntype Size = { width: number; height: number }\r\n\r\nconst ROLE_STYLE: Record<NodeRole, { color: string; label: string; title: string }> = {\r\n one: { color: '#4dabf7', label: 'lado 1', title: 'Só aparece no lado 1: filtra outras tabelas' },\r\n many: { color: '#F58220', label: 'lado N', title: 'Tem relacionamento saindo (lado N)' },\r\n alone: { color: '#868e96', label: 'solta', title: 'Sem relacionamentos' }\r\n}\r\n\r\nconst PANEL_KEY = 'bm-dashboard-devtools:diagram-panel'\r\nconst PANEL_MIN = 260\r\nconst PANEL_MAX = 720\r\n\r\ntype PanelState = { open: boolean; width: number }\r\n\r\nfunction loadPanel(): PanelState {\r\n try {\r\n const saved = JSON.parse(localStorage.getItem(PANEL_KEY) ?? 'null')\r\n if (typeof saved?.width === 'number')\r\n return {\r\n open: saved.open !== false,\r\n width: Math.min(PANEL_MAX, Math.max(PANEL_MIN, saved.width))\r\n }\r\n } catch {}\r\n return { open: true, width: 340 }\r\n}\r\n\r\n/** Acompanha o mouse até soltar o botão. */\r\nfunction track(\r\n event: ReactMouseEvent,\r\n onMove: (dx: number, dy: number, event: MouseEvent) => void,\r\n onUp?: (event: MouseEvent, moved: boolean) => void\r\n) {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n const start = { x: event.clientX, y: event.clientY }\r\n // Janela do elemento: com o devtools em janela separada, o mouse se move nela, não na página\r\n const win = event.currentTarget.ownerDocument.defaultView ?? window\r\n let moved = false\r\n const move = (moveEvent: MouseEvent) => {\r\n const dx = moveEvent.clientX - start.x\r\n const dy = moveEvent.clientY - start.y\r\n if (Math.abs(dx) + Math.abs(dy) > 3) moved = true\r\n if (moved) onMove(dx, dy, moveEvent)\r\n }\r\n const up = (upEvent: MouseEvent) => {\r\n win.removeEventListener('mousemove', move)\r\n win.removeEventListener('mouseup', up)\r\n onUp?.(upEvent, moved)\r\n }\r\n win.addEventListener('mousemove', move)\r\n win.addEventListener('mouseup', up)\r\n}\r\n\r\n/** Colunas citadas como `tabela.coluna` no SQL das dimensões/medidas. */\r\nfunction citedColumns(sql: string, table: string) {\r\n const code = sql.replace(/'(?:[^'\\\\]|\\\\.)*'/g, \"''\")\r\n const pattern = new RegExp(`(?<![\\\\w.\\`])${table}\\\\.([A-Za-z_][A-Za-z0-9_]*)`, 'g')\r\n return [...code.matchAll(pattern)].map((match) => match[1])\r\n}\r\n\r\n/** Ícone de cada agregação no card (a soma fica com o Σ). */\r\nconst MEASURE_ICON: Partial<Record<MeasureRow['type'], string>> = {\r\n count: '#',\r\n countDistinct: '#',\r\n avg: 'x̄',\r\n min: '↓',\r\n max: '↑'\r\n}\r\n\r\nconst fieldItems = (\r\n dimensions: DimensionRow[],\r\n measures: MeasureRow[],\r\n belongs: (sql: string) => boolean\r\n): FieldItem[] => [\r\n ...dimensions\r\n .filter((row) => belongs(row.sql))\r\n .map((row) => ({ kind: 'dimension' as const, uid: row.uid, name: row.name, icon: '◇' })),\r\n ...measures\r\n .filter((row) => isAggregate(row) && belongs(row.sql))\r\n .map((row) => ({\r\n kind: 'measure' as const,\r\n uid: row.uid,\r\n name: row.name,\r\n icon: MEASURE_ICON[row.type] ?? 'Σ'\r\n }))\r\n]\r\n\r\nfunction buildNodes(\r\n editor: EditorModel,\r\n columns: ModelColumns | null,\r\n errors: Record<string, string>\r\n): DiagramNode[] {\r\n const numeric = new Set(columns?.numeric ?? [])\r\n const columnItems = (\r\n node: string,\r\n loaded: string[] | undefined,\r\n extra: string[],\r\n key: string,\r\n linked: Set<string>\r\n ): ColumnItem[] => {\r\n const names = [...(loaded ?? []), ...extra.filter((name) => !loaded?.includes(name))]\r\n return [...new Set(names)].map((name) => ({\r\n kind: 'column',\r\n name,\r\n numeric: numeric.has(`${node}.${name}`),\r\n isKey: name === key,\r\n linked: linked.has(name),\r\n missing: !!loaded?.length && !loaded.includes(name)\r\n }))\r\n }\r\n\r\n const tableNames = editor.tables.map((table) => table.name)\r\n const edges = modelEdges(fromEditor(editor))\r\n // Tabela onde a medida/dimensão agrega (a que alcança as outras que ela cita)\r\n const homeOf = (sql: string) => measureHome(referencedTables(sql, tableNames), edges)\r\n return editor.tables.map((table) => {\r\n const linked = new Set(\r\n editor.relationships.flatMap((row) => [\r\n ...(row.fromTable === table.uid ? [row.fromColumn] : []),\r\n ...(row.toTable === table.uid ? [row.toColumn] : [])\r\n ])\r\n )\r\n const cited = [...editor.dimensions, ...editor.measures].flatMap((row) =>\r\n citedColumns(row.sql, table.name)\r\n )\r\n return {\r\n id: table.uid,\r\n uid: table.uid,\r\n name: table.name,\r\n role: editor.relationships.some((row) => row.fromTable === table.uid)\r\n ? ('many' as const)\r\n : editor.relationships.some((row) => row.toTable === table.uid)\r\n ? ('one' as const)\r\n : ('alone' as const),\r\n key: table.key,\r\n error: errors[`table:${table.name}`],\r\n items: [\r\n ...columnItems(\r\n table.name,\r\n columns?.tables[table.name],\r\n [...(table.key ? [table.key] : []), ...linked, ...cited],\r\n table.key,\r\n linked\r\n ),\r\n ...fieldItems(editor.dimensions, editor.measures, (sql) => homeOf(sql) === table.name)\r\n ]\r\n }\r\n })\r\n}\r\n\r\n/** Altura do conteúdo (sem tamanho salvo): até `MAX_BODY` de linhas, o resto rola. */\r\nconst contentHeight = (node: DiagramNode) =>\r\n HEADER + Math.min(node.items.length * ROW, MAX_BODY) + PADDING * 2\r\n\r\nconst clamp = (value: number, min: number, max: number) => Math.min(max, Math.max(min, value))\r\n\r\n/** Quem só filtra (lado 1) em cima, o resto embaixo (como costuma ficar no Power BI). */\r\nfunction autoLayout(nodes: DiagramNode[], sizes: Map<string, Size>) {\r\n const top = nodes.filter((node) => node.role === 'one')\r\n const bottom = nodes.filter((node) => node.role !== 'one')\r\n const positions: Record<string, Point> = {}\r\n const gap = 60\r\n const row = (list: DiagramNode[], y: number) => {\r\n let x = 40\r\n for (const node of list) {\r\n positions[node.id] = { x, y }\r\n x += (sizes.get(node.id)?.width ?? CARD_WIDTH) + gap\r\n }\r\n }\r\n row(top, 40)\r\n const topHeight = Math.max(0, ...top.map((node) => sizes.get(node.id)?.height ?? HEADER))\r\n row(bottom, 40 + topHeight + 140)\r\n return positions\r\n}\r\n\r\nexport function ModelDiagram({\r\n editor,\r\n setEditor,\r\n columns,\r\n errors,\r\n warnings,\r\n loadingColumns,\r\n onLoadColumns,\r\n onTry,\r\n usage\r\n}: Props) {\r\n const nodes = useMemo(() => buildNodes(editor, columns, errors), [editor, columns, errors])\r\n // Card sendo arrastado/redimensionado: a posição e o tamanho só vão para o modelo ao soltar\r\n const [moving, setMoving] = useState<{ id: string; point: Point } | null>(null)\r\n const [resizing, setResizing] = useState<({ id: string } & Size) | null>(null)\r\n const [collapsed, setCollapsed] = useState<Record<string, boolean>>({})\r\n const [scrolls, setScrolls] = useState<Record<string, number>>({})\r\n const [view, setView] = useState<View>({ x: 0, y: 0, zoom: 1 })\r\n const [selection, setSelection] = useState<Selection>(null)\r\n const [panel, setPanel] = useState<PanelState>(loadPanel)\r\n // Tabela com o nome em edição no próprio card (duplo clique)\r\n const [renaming, setRenaming] = useState<string | null>(null)\r\n // Fechado, mantém o alvo: o texto não some durante a animação de saída\r\n const [menu, setMenu] = useState<{\r\n open: boolean\r\n x: number\r\n y: number\r\n /** `null`: o fundo do diagrama (criar tabela/medida, recarregar, organizar). */\r\n target: MenuTarget | null\r\n } | null>(null)\r\n const closeMenu = () => setMenu((current) => current && { ...current, open: false })\r\n\r\n useEffect(() => {\r\n try {\r\n localStorage.setItem(PANEL_KEY, JSON.stringify(panel))\r\n } catch {}\r\n }, [panel])\r\n\r\n // Selecionou algo com o painel recolhido: abre para mostrar as propriedades\r\n useEffect(() => {\r\n if (selection) setPanel((current) => (current.open ? current : { ...current, open: true }))\r\n }, [selection])\r\n\r\n const startPanelResize = (event: ReactMouseEvent) => {\r\n const start = panel.width\r\n track(event, (dx) =>\r\n setPanel((current) => ({\r\n ...current,\r\n width: Math.min(PANEL_MAX, Math.max(PANEL_MIN, start - dx))\r\n }))\r\n )\r\n }\r\n const [linking, setLinking] = useState<{ node: DiagramNode; column: string; to: Point } | null>(\r\n null\r\n )\r\n const [hoveredEdge, setHoveredEdge] = useState<string | null>(null)\r\n const canvas = useRef<HTMLDivElement>(null)\r\n\r\n // Colunas do banco: carrega uma vez ao abrir o diagrama\r\n const requested = useRef(false)\r\n useEffect(() => {\r\n if (requested.current || columns) return\r\n requested.current = true\r\n onLoadColumns()\r\n }, [columns, onLoadColumns])\r\n\r\n // Tamanho de cada card: o salvo no modelo (redimensionado) ou o padrão; recolhido, só o cabeçalho\r\n const sizes = useMemo(\r\n () =>\r\n new Map(\r\n nodes.map((node): [string, Size] => {\r\n const saved = resizing?.id === node.id ? resizing : editor.positions[node.id]\r\n const width = saved?.width ?? CARD_WIDTH\r\n if (collapsed[node.id]) return [node.id, { width, height: HEADER }]\r\n return [node.id, { width, height: saved?.height ?? contentHeight(node) }]\r\n })\r\n ),\r\n [nodes, collapsed, editor.positions, resizing]\r\n )\r\n const sizeOf = (node: DiagramNode): Size =>\r\n sizes.get(node.id) ?? { width: CARD_WIDTH, height: HEADER }\r\n // Card sem posição salva entra no layout automático (sem mexer nos que já foram arrumados)\r\n const fallback = useMemo(() => autoLayout(nodes, sizes), [nodes, sizes])\r\n const placed = (node: DiagramNode): Point => {\r\n if (moving?.id === node.id) return moving.point\r\n const saved = editor.positions[node.id]\r\n return saved ? { x: saved.x, y: saved.y } : (fallback[node.id] ?? { x: 0, y: 0 })\r\n }\r\n const setPositions = (update: (current: EditorModel['positions']) => EditorModel['positions']) =>\r\n setEditor((current) => ({ ...current, positions: update(current.positions) }))\r\n\r\n const nodeOf = (uid: string) => nodes.find((node) => node.uid === uid)\r\n\r\n /** Ponto da linha na coluna do card (lado esquerdo ou direito). */\r\n const anchor = (node: DiagramNode, column: string, side: 'left' | 'right'): Point => {\r\n const { x, y } = placed(node)\r\n const { width, height } = sizeOf(node)\r\n const index = node.items.findIndex((item) => item.kind === 'column' && item.name === column)\r\n let rowY = y + HEADER / 2\r\n if (!collapsed[node.id] && index >= 0) {\r\n const raw = y + HEADER + PADDING + index * ROW + ROW / 2 - (scrolls[node.id] ?? 0)\r\n rowY = Math.min(Math.max(raw, y + HEADER + 2), y + height - 2)\r\n }\r\n return { x: side === 'left' ? x : x + width, y: rowY }\r\n }\r\n\r\n const toWorld = (clientX: number, clientY: number): Point => {\r\n const rect = canvas.current?.getBoundingClientRect()\r\n return {\r\n x: (clientX - (rect?.left ?? 0) - view.x) / view.zoom,\r\n y: (clientY - (rect?.top ?? 0) - view.y) / view.zoom\r\n }\r\n }\r\n\r\n // --- edição ---\r\n\r\n const patchTable = (uid: string, changes: Partial<TableRow>) =>\r\n setEditor((current) => ({\r\n ...current,\r\n tables: current.tables.map((row) => (row.uid === uid ? { ...row, ...changes } : row))\r\n }))\r\n const patchRelationship = (uid: string, changes: Partial<RelationshipRow>) =>\r\n setEditor((current) => ({\r\n ...current,\r\n relationships: current.relationships.map((row) =>\r\n row.uid === uid ? { ...row, ...changes } : row\r\n )\r\n }))\r\n const patchDimension = (uid: string, changes: Partial<DimensionRow>) =>\r\n setEditor((current) => ({\r\n ...current,\r\n dimensions: current.dimensions.map((row) => (row.uid === uid ? { ...row, ...changes } : row))\r\n }))\r\n const patchMeasure = (uid: string, changes: Partial<MeasureRow>) =>\r\n setEditor((current) => ({\r\n ...current,\r\n measures: current.measures.map((row) => (row.uid === uid ? { ...row, ...changes } : row))\r\n }))\r\n\r\n /** Perto do centro da área visível (onde entra um card novo). */\r\n const visibleCenter = () => {\r\n const rect = canvas.current?.getBoundingClientRect()\r\n return toWorld(\r\n (rect?.left ?? 0) + (rect?.width ?? 600) / 2 - CARD_WIDTH / 2,\r\n (rect?.top ?? 0) + (rect?.height ?? 400) / 3\r\n )\r\n }\r\n\r\n /** `at`: canto do card (o ponto do botão direito); sem ele, perto do centro da tela. */\r\n const addTable = (at?: Point) => {\r\n const uid = newUid()\r\n const name = freeName(\r\n 'novaTabela',\r\n editor.tables.map((table) => table.name)\r\n )\r\n const position = at ?? visibleCenter()\r\n setEditor((current) => ({\r\n ...current,\r\n positions: { ...current.positions, [uid]: position },\r\n tables: [\r\n ...current.tables,\r\n {\r\n uid,\r\n name,\r\n key: '',\r\n sql: 'SELECT * FROM tabela',\r\n label: '',\r\n description: ''\r\n }\r\n ]\r\n }))\r\n setSelection({ kind: 'table', uid })\r\n }\r\n\r\n const organize = () => {\r\n const layout = autoLayout(nodes, sizes)\r\n // Troca as posições, mas mantém o tamanho de quem foi redimensionado\r\n setPositions((current) =>\r\n Object.fromEntries(\r\n Object.entries(layout).map(([id, point]) => [id, { ...current[id], ...point }])\r\n )\r\n )\r\n fitToScreen(layout)\r\n }\r\n\r\n const addFormula = () => {\r\n setSelection({ kind: 'measure', uid: addFormulaTo(setEditor) })\r\n }\r\n\r\n const removeTable = (uid: string) => {\r\n setEditor((current) => ({\r\n ...current,\r\n tables: current.tables.filter((row) => row.uid !== uid),\r\n relationships: current.relationships.filter(\r\n (row) => row.fromTable !== uid && row.toTable !== uid\r\n )\r\n }))\r\n setSelection(null)\r\n }\r\n\r\n const remove = (target: NonNullable<Selection>) => {\r\n if (target.kind === 'table') return removeTable(target.uid)\r\n const list = (\r\n { relationship: 'relationships', dimension: 'dimensions', measure: 'measures' } as const\r\n )[target.kind]\r\n setEditor((current) => ({\r\n ...current,\r\n [list]: (current[list] as { uid: string }[]).filter((row) => row.uid !== target.uid)\r\n }))\r\n setSelection((current) => (current?.uid === target.uid ? null : current))\r\n }\r\n\r\n // Corrige as referências `tabela.coluna` (a posição vai pelo uid)\r\n const commitRename = (uid: string, name: string) =>\r\n setEditor((current) => renameTable(current, uid, name))\r\n\r\n const connect = (from: DiagramNode, fromColumn: string, to: DiagramNode, toColumn: string) => {\r\n if (from.uid === to.uid) return\r\n // O lado 1 é quem entra pela própria chave: arrastou da chave para uma coluna comum, inverte\r\n const swap = fromColumn === from.key && toColumn !== to.key\r\n const [many, manyColumn, one, oneColumn] = swap\r\n ? [to, toColumn, from, fromColumn]\r\n : [from, fromColumn, to, toColumn]\r\n const uid = newUid()\r\n setEditor((current) => ({\r\n ...current,\r\n relationships: [\r\n ...current.relationships,\r\n {\r\n uid,\r\n fromTable: many.uid,\r\n fromColumn: manyColumn,\r\n toTable: one.uid,\r\n toColumn: oneColumn,\r\n inner: false\r\n }\r\n ]\r\n }))\r\n setSelection({ kind: 'relationship', uid })\r\n }\r\n\r\n /** Dimensão/medida nova a partir da tabela (ou de uma coluna dela, já preenchida). */\r\n const addField = (\r\n kind: 'dimension' | 'measure',\r\n table: string,\r\n column?: { name: string; numeric: boolean }\r\n ) => {\r\n const uid = newUid()\r\n const taken = [...editor.dimensions, ...editor.measures].map((row) => row.name)\r\n const sql = `${table}.${column?.name ?? ''}`\r\n if (kind === 'dimension')\r\n setEditor((current) => ({\r\n ...current,\r\n dimensions: [\r\n ...current.dimensions,\r\n emptyDimension({\r\n uid,\r\n name: freeName(column?.name ?? 'novaDimensao', taken),\r\n type: column?.numeric ? 'number' : 'string',\r\n sql\r\n })\r\n ]\r\n }))\r\n else\r\n setEditor((current) => ({\r\n ...current,\r\n measures: [\r\n ...current.measures,\r\n // Coluna de texto/data não soma: vira contagem\r\n emptyMeasure({\r\n uid,\r\n name: freeName(\r\n column ? `${column.numeric ? 'total' : 'qtd'}_${column.name}` : 'novaMedida',\r\n taken\r\n ),\r\n type: column && !column.numeric ? 'count' : 'sum',\r\n sql\r\n })\r\n ]\r\n }))\r\n setSelection({ kind, uid })\r\n }\r\n\r\n const removeSelection = () => {\r\n if (selection) remove(selection)\r\n }\r\n\r\n // --- mouse ---\r\n\r\n const startPan = (event: ReactMouseEvent) => {\r\n if (event.button !== 0) return\r\n const start = view\r\n track(\r\n event,\r\n (dx, dy) => setView((current) => ({ ...current, x: start.x + dx, y: start.y + dy })),\r\n (_, moved) => {\r\n if (!moved) setSelection(null)\r\n }\r\n )\r\n }\r\n\r\n const startMove = (event: ReactMouseEvent, node: DiagramNode) => {\r\n if (event.button !== 0) return\r\n const start = placed(node)\r\n const { zoom } = view\r\n let point = start\r\n track(\r\n event,\r\n (dx, dy) => {\r\n point = { x: start.x + dx / zoom, y: start.y + dy / zoom }\r\n setMoving({ id: node.id, point })\r\n },\r\n (_, moved) => {\r\n setMoving(null)\r\n // Mantém o tamanho salvo do card\r\n if (moved)\r\n setPositions((current) => ({ ...current, [node.id]: { ...current[node.id], ...point } }))\r\n else selectNode(node)\r\n }\r\n )\r\n }\r\n\r\n /** Arrasta a borda direita (`width`), a de baixo (`height`) ou o canto (as duas). */\r\n const startResize = (\r\n event: ReactMouseEvent,\r\n node: DiagramNode,\r\n edges: { width: boolean; height: boolean }\r\n ) => {\r\n if (event.button !== 0) return\r\n const start = sizeOf(node)\r\n const { zoom } = view\r\n let size = start\r\n track(\r\n event,\r\n (dx, dy) => {\r\n size = {\r\n width: edges.width ? clamp(start.width + dx / zoom, MIN_WIDTH, MAX_WIDTH) : start.width,\r\n height: edges.height\r\n ? clamp(start.height + dy / zoom, MIN_HEIGHT, MAX_HEIGHT)\r\n : start.height\r\n }\r\n setResizing({ id: node.id, ...size })\r\n },\r\n (_, moved) => {\r\n setResizing(null)\r\n if (!moved) return\r\n const point = placed(node)\r\n setPositions((current) => ({\r\n ...current,\r\n [node.id]: {\r\n ...point,\r\n ...current[node.id],\r\n ...(edges.width && { width: size.width }),\r\n ...(edges.height && { height: size.height })\r\n }\r\n }))\r\n }\r\n )\r\n }\r\n\r\n /** Duplo clique na alça: volta ao tamanho automático (largura padrão, altura do conteúdo). */\r\n const resetSize = (node: DiagramNode) =>\r\n setPositions((current) => {\r\n const saved = current[node.id]\r\n if (!saved) return current\r\n return { ...current, [node.id]: { x: saved.x, y: saved.y } }\r\n })\r\n\r\n const startLink = (event: ReactMouseEvent, node: DiagramNode, column: string) => {\r\n if (event.button !== 0) return\r\n track(\r\n event,\r\n (_, __, moveEvent) =>\r\n setLinking({ node, column, to: toWorld(moveEvent.clientX, moveEvent.clientY) }),\r\n (upEvent, moved) => {\r\n setLinking(null)\r\n if (!moved) {\r\n selectNode(node)\r\n return\r\n }\r\n const target = (canvas.current?.ownerDocument ?? document)\r\n .elementFromPoint(upEvent.clientX, upEvent.clientY)\r\n ?.closest<HTMLElement>('[data-diagram-column]')\r\n const targetNode = nodes.find((item) => item.id === target?.dataset.diagramNode)\r\n const targetColumn = target?.dataset.diagramColumn\r\n if (targetNode && targetColumn) connect(node, column, targetNode, targetColumn)\r\n }\r\n )\r\n }\r\n\r\n const onWheel = (event: WheelEvent) => {\r\n if (!event.ctrlKey && !event.metaKey) {\r\n setView((current) => ({\r\n ...current,\r\n x: current.x - event.deltaX,\r\n y: current.y - event.deltaY\r\n }))\r\n return\r\n }\r\n const rect = canvas.current?.getBoundingClientRect()\r\n const px = event.clientX - (rect?.left ?? 0)\r\n const py = event.clientY - (rect?.top ?? 0)\r\n setView((current) => {\r\n const zoom = Math.min(2, Math.max(0.3, current.zoom * (event.deltaY > 0 ? 0.9 : 1.1)))\r\n const ratio = zoom / current.zoom\r\n return { zoom, x: px - (px - current.x) * ratio, y: py - (py - current.y) * ratio }\r\n })\r\n }\r\n\r\n // Ctrl+roda não pode dar zoom na página inteira\r\n useEffect(() => {\r\n const element = canvas.current\r\n if (!element) return\r\n const prevent = (event: globalThis.WheelEvent) => event.preventDefault()\r\n element.addEventListener('wheel', prevent, { passive: false })\r\n return () => element.removeEventListener('wheel', prevent)\r\n }, [])\r\n\r\n const fitToScreen = (layout?: Record<string, Point>) => {\r\n const rect = canvas.current?.getBoundingClientRect()\r\n if (!rect || !nodes.length) return\r\n const boxes = nodes.map((node) => ({\r\n ...(layout?.[node.id] ?? placed(node)),\r\n w: sizeOf(node).width,\r\n h: sizeOf(node).height\r\n }))\r\n const minX = Math.min(...boxes.map((box) => box.x))\r\n const minY = Math.min(...boxes.map((box) => box.y))\r\n const maxX = Math.max(...boxes.map((box) => box.x + box.w))\r\n const maxY = Math.max(...boxes.map((box) => box.y + box.h))\r\n const zoom = Math.min(\r\n 1.2,\r\n Math.max(0.3, Math.min((rect.width - 60) / (maxX - minX), (rect.height - 60) / (maxY - minY)))\r\n )\r\n setView({ zoom, x: 30 - minX * zoom, y: 30 - minY * zoom })\r\n }\r\n\r\n const selectNode = (node: DiagramNode) => setSelection({ kind: 'table', uid: node.uid })\r\n\r\n const isSelected = (node: DiagramNode) =>\r\n selection?.kind === 'table' && selection.uid === node.uid\r\n\r\n // --- linhas ---\r\n\r\n type Line = {\r\n id: string\r\n from: Point\r\n to: Point\r\n selected: boolean\r\n inner?: boolean\r\n error?: string\r\n onClick?: () => void\r\n }\r\n const lines: Line[] = []\r\n const pushLine = (\r\n id: string,\r\n many: DiagramNode,\r\n manyColumn: string,\r\n one: DiagramNode,\r\n oneColumn: string,\r\n extra: Partial<Line>\r\n ) => {\r\n const manyX = placed(many).x + sizeOf(many).width / 2\r\n const oneX = placed(one).x + sizeOf(one).width / 2\r\n const rightward = manyX <= oneX\r\n lines.push({\r\n id,\r\n from: anchor(many, manyColumn, rightward ? 'right' : 'left'),\r\n to: anchor(one, oneColumn, rightward ? 'left' : 'right'),\r\n selected: false,\r\n ...extra\r\n })\r\n }\r\n editor.relationships.forEach((row, index) => {\r\n const many = nodeOf(row.fromTable)\r\n const one = nodeOf(row.toTable)\r\n if (!many || !one) return\r\n pushLine(row.uid, many, row.fromColumn, one, row.toColumn, {\r\n inner: row.inner,\r\n selected: selection?.kind === 'relationship' && selection.uid === row.uid,\r\n error: errors[`relationship:${index}`],\r\n onClick: () => setSelection({ kind: 'relationship', uid: row.uid })\r\n })\r\n })\r\n\r\n // Dimensões/medidas que não caem em nenhum card (SQL sem `tabela.coluna` conhecido)\r\n const shown = new Set(\r\n nodes.flatMap((node) => node.items.map((item) => 'uid' in item && item.uid))\r\n )\r\n const unplaced = fieldItems(editor.dimensions, editor.measures, () => true).filter(\r\n (item) => !shown.has(item.uid)\r\n )\r\n\r\n const linkPreview =\r\n linking &&\r\n (() => {\r\n const start = anchor(\r\n linking.node,\r\n linking.column,\r\n linking.to.x < placed(linking.node).x ? 'left' : 'right'\r\n )\r\n return curve(start, linking.to)\r\n })()\r\n\r\n return (\r\n <Box sx={{ display: 'flex', height: '100%', minHeight: 0 }}>\r\n <Box\r\n ref={canvas}\r\n tabIndex={-1}\r\n onMouseDown={startPan}\r\n // O arrastar cancela o mouse down; o foco é o que faz o Delete chegar aqui\r\n onMouseDownCapture={() => canvas.current?.focus({ preventScroll: true })}\r\n onKeyDown={(event) => {\r\n if (\r\n (event.key === 'Delete' || event.key === 'Backspace') &&\r\n event.target === canvas.current\r\n )\r\n removeSelection()\r\n }}\r\n onWheel={onWheel}\r\n onContextMenu={(event) => {\r\n event.preventDefault()\r\n setMenu({ open: true, x: event.clientX, y: event.clientY, target: null })\r\n }}\r\n sx={{\r\n outline: 'none',\r\n flex: 1,\r\n position: 'relative',\r\n overflow: 'hidden',\r\n cursor: 'grab',\r\n bgcolor: '#15171b',\r\n backgroundImage: 'radial-gradient(rgba(255,255,255,.07) 1px, transparent 1px)',\r\n backgroundSize: `${20 * view.zoom}px ${20 * view.zoom}px`,\r\n backgroundPosition: `${view.x}px ${view.y}px`\r\n }}\r\n >\r\n <Box\r\n sx={{\r\n position: 'absolute',\r\n left: 0,\r\n top: 0,\r\n transformOrigin: '0 0',\r\n transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom})`\r\n }}\r\n >\r\n <svg\r\n width={1}\r\n height={1}\r\n style={{ position: 'absolute', overflow: 'visible', pointerEvents: 'none' }}\r\n aria-hidden\r\n >\r\n {lines.map((line) => (\r\n <RelationshipLine\r\n key={line.id}\r\n line={line}\r\n hovered={hoveredEdge === line.id}\r\n onHover={(hovered) => setHoveredEdge(hovered ? line.id : null)}\r\n />\r\n ))}\r\n {linkPreview && (\r\n <path\r\n d={linkPreview}\r\n fill=\"none\"\r\n stroke=\"#F58220\"\r\n strokeWidth={2}\r\n strokeDasharray=\"5 4\"\r\n />\r\n )}\r\n </svg>\r\n\r\n {nodes.map((node) => (\r\n <TableCard\r\n key={node.id}\r\n node={node}\r\n position={placed(node)}\r\n size={sizeOf(node)}\r\n collapsed={!!collapsed[node.id]}\r\n selected={!!isSelected(node)}\r\n linking={!!linking && linking.node.id !== node.id}\r\n selectedField={\r\n selection?.kind === 'dimension' || selection?.kind === 'measure'\r\n ? selection.uid\r\n : null\r\n }\r\n onToggle={() =>\r\n setCollapsed((current) => ({ ...current, [node.id]: !current[node.id] }))\r\n }\r\n onScroll={(top) => setScrolls((current) => ({ ...current, [node.id]: top }))}\r\n onHeaderDown={(event) => startMove(event, node)}\r\n onResizeDown={(event, edges) => startResize(event, node, edges)}\r\n onResizeReset={() => resetSize(node)}\r\n onColumnDown={(event, column) => startLink(event, node, column)}\r\n onFieldClick={(item) => setSelection({ kind: item.kind, uid: item.uid })}\r\n onAddField={(kind, column) => addField(kind, node.name, column)}\r\n renaming={renaming === node.uid}\r\n onRenameStart={() => setRenaming(node.uid)}\r\n onRename={(name) => {\r\n setRenaming(null)\r\n if (name !== null && name !== node.name) commitRename(node.uid, name)\r\n }}\r\n onContextMenu={(event, target) => {\r\n event.preventDefault()\r\n event.stopPropagation()\r\n setMenu({ open: true, x: event.clientX, y: event.clientY, target })\r\n }}\r\n />\r\n ))}\r\n </Box>\r\n\r\n <Box\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onContextMenu={(event) => event.stopPropagation()}\r\n sx={{\r\n position: 'absolute',\r\n top: 8,\r\n left: 8,\r\n right: 8,\r\n display: 'flex',\r\n gap: 0.75,\r\n flexWrap: 'wrap',\r\n alignItems: 'center',\r\n pointerEvents: 'none',\r\n '& > *': { pointerEvents: 'auto' }\r\n }}\r\n >\r\n <Button size=\"small\" variant=\"outlined\" onClick={() => addTable()}>\r\n + Tabela\r\n </Button>\r\n <Button\r\n size=\"small\"\r\n onClick={onLoadColumns}\r\n disabled={loadingColumns}\r\n title=\"Lê uma linha de cada tabela para listar as colunas\"\r\n sx={{ bgcolor: '#1b1e23' }}\r\n >\r\n {loadingColumns ? 'Lendo colunas…' : 'Recarregar colunas'}\r\n </Button>\r\n <Box sx={{ ml: 'auto', display: 'flex', gap: 0.5, alignItems: 'center' }}>\r\n <Button\r\n size=\"small\"\r\n onClick={organize}\r\n title=\"Dimensões em cima, fatos embaixo (troca as posições salvas)\"\r\n sx={{ bgcolor: '#1b1e23' }}\r\n >\r\n Organizar\r\n </Button>\r\n <Button size=\"small\" onClick={() => fitToScreen()} sx={{ bgcolor: '#1b1e23' }}>\r\n Ajustar à tela\r\n </Button>\r\n <IconButton\r\n size=\"small\"\r\n aria-label=\"Diminuir zoom\"\r\n onClick={() =>\r\n setView((current) => ({ ...current, zoom: Math.max(0.3, current.zoom - 0.1) }))\r\n }\r\n >\r\n −\r\n </IconButton>\r\n <Typography sx={{ fontSize: 11, fontFamily: MONO, width: 36, textAlign: 'center' }}>\r\n {Math.round(view.zoom * 100)}%\r\n </Typography>\r\n <IconButton\r\n size=\"small\"\r\n aria-label=\"Aumentar zoom\"\r\n onClick={() =>\r\n setView((current) => ({ ...current, zoom: Math.min(2, current.zoom + 0.1) }))\r\n }\r\n >\r\n +\r\n </IconButton>\r\n </Box>\r\n </Box>\r\n\r\n {!nodes.length && (\r\n <Box\r\n sx={{\r\n position: 'absolute',\r\n inset: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n pointerEvents: 'none',\r\n color: 'text.secondary',\r\n fontSize: 13,\r\n textAlign: 'center',\r\n px: 4\r\n }}\r\n >\r\n Modelo vazio. Adicione as tabelas dimensão (cadastros: navio, calendário…) e fato\r\n (lançamentos: pesagens, custos…) e arraste a coluna da fato até a chave da dimensão para\r\n relacioná-las.\r\n </Box>\r\n )}\r\n {!!nodes.length && (\r\n <Typography\r\n sx={{\r\n position: 'absolute',\r\n left: 10,\r\n bottom: 6,\r\n fontSize: 11,\r\n color: 'text.disabled',\r\n pointerEvents: 'none'\r\n }}\r\n >\r\n Arraste uma coluna até a coluna de outra tabela para relacionar · +◇/+Σ na coluna cria\r\n dimensão/medida · Duplo clique no nome renomeia · Botão direito: editar/remover (no\r\n fundo: nova tabela/medida, recarregar, organizar) · Delete remove · Ctrl+roda: zoom\r\n </Typography>\r\n )}\r\n </Box>\r\n\r\n <Menu\r\n open={!!menu?.open}\r\n onClose={closeMenu}\r\n anchorReference=\"anchorPosition\"\r\n anchorPosition={menu ? { top: menu.y, left: menu.x } : undefined}\r\n transitionDuration={{ enter: 90, exit: 60 }}\r\n // Botão direito de novo em cima do menu aberto não abre o do navegador\r\n onContextMenu={(event) => event.preventDefault()}\r\n >\r\n {menu?.target\r\n ? [\r\n <MenuItem\r\n key=\"edit\"\r\n dense\r\n onClick={() => {\r\n setSelection(menu.target)\r\n closeMenu()\r\n }}\r\n >\r\n Editar {TARGET_NAME[menu.target.kind]}\r\n </MenuItem>,\r\n <MenuItem\r\n key=\"remove\"\r\n dense\r\n sx={{ color: 'error.main' }}\r\n onClick={() => {\r\n if (menu.target) remove(menu.target)\r\n closeMenu()\r\n }}\r\n >\r\n Remover {TARGET_NAME[menu.target.kind]}\r\n </MenuItem>\r\n ]\r\n : [\r\n <MenuItem\r\n key=\"table\"\r\n dense\r\n onClick={() => {\r\n if (menu) addTable(toWorld(menu.x, menu.y))\r\n closeMenu()\r\n }}\r\n >\r\n Nova Tabela\r\n </MenuItem>,\r\n <MenuItem\r\n key=\"formula\"\r\n dense\r\n onClick={() => {\r\n addFormula()\r\n closeMenu()\r\n }}\r\n >\r\n Nova Medida Calculada\r\n </MenuItem>,\r\n <Divider key=\"divider\" />,\r\n <MenuItem\r\n key=\"columns\"\r\n dense\r\n disabled={loadingColumns}\r\n onClick={() => {\r\n onLoadColumns()\r\n closeMenu()\r\n }}\r\n >\r\n Recarregar colunas\r\n </MenuItem>,\r\n <MenuItem\r\n key=\"organize\"\r\n dense\r\n onClick={() => {\r\n organize()\r\n closeMenu()\r\n }}\r\n >\r\n Organizar\r\n </MenuItem>\r\n ]}\r\n </Menu>\r\n\r\n {panel.open ? (\r\n <Box\r\n sx={{\r\n width: panel.width,\r\n flexShrink: 0,\r\n borderLeft: 1,\r\n borderColor: 'divider',\r\n position: 'relative',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n minHeight: 0\r\n }}\r\n >\r\n {/* Borda arrastável: redimensiona o painel */}\r\n <Box\r\n onMouseDown={startPanelResize}\r\n title=\"Arraste para redimensionar\"\r\n sx={{\r\n position: 'absolute',\r\n left: -3,\r\n top: 0,\r\n bottom: 0,\r\n width: 6,\r\n cursor: 'ew-resize',\r\n zIndex: 2,\r\n '&:hover': { bgcolor: 'primary.main', opacity: 0.4 }\r\n }}\r\n />\r\n <Box\r\n sx={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n px: 1.5,\r\n py: 0.5,\r\n borderBottom: 1,\r\n borderColor: 'divider'\r\n }}\r\n >\r\n <Typography sx={{ fontSize: 12, fontWeight: 700, color: 'text.secondary', flex: 1 }}>\r\n Propriedades\r\n </Typography>\r\n <IconButton\r\n size=\"small\"\r\n aria-label=\"Recolher propriedades\"\r\n title=\"Recolher\"\r\n onClick={() => setPanel((current) => ({ ...current, open: false }))}\r\n >\r\n ⟩\r\n </IconButton>\r\n </Box>\r\n <Box sx={{ overflow: 'auto', flex: 1, p: 1.5 }}>\r\n <Properties\r\n editor={editor}\r\n selection={selection}\r\n columns={columns}\r\n errors={errors}\r\n warnings={warnings}\r\n usage={usage}\r\n onSelect={setSelection}\r\n onTry={onTry}\r\n setEditor={setEditor}\r\n patchTable={patchTable}\r\n patchRelationship={patchRelationship}\r\n patchDimension={patchDimension}\r\n patchMeasure={patchMeasure}\r\n removeTable={removeTable}\r\n commitRename={commitRename}\r\n addField={addField}\r\n unplaced={unplaced}\r\n />\r\n </Box>\r\n </Box>\r\n ) : (\r\n <Box\r\n component=\"button\"\r\n type=\"button\"\r\n title=\"Mostrar as propriedades\"\r\n onClick={() => setPanel((current) => ({ ...current, open: true }))}\r\n sx={{\r\n width: 28,\r\n flexShrink: 0,\r\n border: 0,\r\n borderLeft: 1,\r\n borderColor: 'divider',\r\n bgcolor: 'background.paper',\r\n color: 'text.secondary',\r\n cursor: 'pointer',\r\n writingMode: 'vertical-rl',\r\n fontSize: 12,\r\n py: 1,\r\n '&:hover': { color: 'primary.main' }\r\n }}\r\n >\r\n ⟨ Propriedades\r\n </Box>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\n/** Curva com tangentes horizontais (saída e chegada pelas laterais dos cards). */\r\nfunction curve(from: Point, to: Point) {\r\n const bend = Math.max(40, Math.abs(to.x - from.x) / 2)\r\n const out = to.x >= from.x ? 1 : -1\r\n return `M ${from.x} ${from.y} C ${from.x + bend * out} ${from.y}, ${to.x - bend * out} ${to.y}, ${to.x} ${to.y}`\r\n}\r\n\r\nfunction RelationshipLine({\r\n line,\r\n hovered,\r\n onHover\r\n}: {\r\n line: {\r\n from: Point\r\n to: Point\r\n selected: boolean\r\n inner?: boolean\r\n error?: string\r\n onClick?: () => void\r\n }\r\n hovered: boolean\r\n onHover: (hovered: boolean) => void\r\n}) {\r\n const { from, to } = line\r\n const d = curve(from, to)\r\n const color = line.error ? '#ff6b6b' : line.selected ? '#F58220' : hovered ? '#ced4da' : '#868e96'\r\n const out = to.x >= from.x ? 1 : -1\r\n // Ponto do meio da curva e a direção do filtro (do lado 1 para o lado N)\r\n const mid = { x: (from.x + to.x) / 2, y: (from.y + to.y) / 2 }\r\n const angle = (Math.atan2(from.y - to.y, from.x - to.x) * 180) / Math.PI\r\n return (\r\n <g style={{ pointerEvents: line.onClick ? 'auto' : 'none' }}>\r\n {line.error && <title>{line.error}</title>}\r\n {/* biome-ignore lint/a11y/noStaticElementInteractions: área de clique da linha; os relacionamentos também abrem pela lista do painel */}\r\n <path\r\n d={d}\r\n fill=\"none\"\r\n stroke=\"transparent\"\r\n strokeWidth={12}\r\n style={{ cursor: line.onClick ? 'pointer' : undefined, pointerEvents: 'stroke' }}\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onClick={line.onClick}\r\n onMouseEnter={() => onHover(true)}\r\n onMouseLeave={() => onHover(false)}\r\n />\r\n <path\r\n d={d}\r\n fill=\"none\"\r\n stroke={color}\r\n strokeWidth={line.selected || line.inner ? 2.4 : 1.4}\r\n />\r\n <polygon\r\n points=\"-5,-4 5,0 -5,4\"\r\n fill={color}\r\n transform={`translate(${mid.x} ${mid.y}) rotate(${angle})`}\r\n />\r\n <text\r\n x={from.x + 8 * out}\r\n y={from.y - 5}\r\n fill={color}\r\n fontSize={14}\r\n fontWeight={700}\r\n textAnchor=\"middle\"\r\n >\r\n *\r\n </text>\r\n <text\r\n x={to.x - 8 * out}\r\n y={to.y - 5}\r\n fill={color}\r\n fontSize={12}\r\n fontWeight={700}\r\n textAnchor=\"middle\"\r\n >\r\n 1\r\n </text>\r\n </g>\r\n )\r\n}\r\n\r\nfunction TableCard({\r\n node,\r\n position,\r\n size,\r\n collapsed,\r\n selected,\r\n linking,\r\n selectedField,\r\n onToggle,\r\n onScroll,\r\n onHeaderDown,\r\n onResizeDown,\r\n onResizeReset,\r\n onColumnDown,\r\n onFieldClick,\r\n onAddField,\r\n renaming,\r\n onRenameStart,\r\n onRename,\r\n onContextMenu\r\n}: {\r\n node: DiagramNode\r\n position: Point\r\n size: Size\r\n collapsed: boolean\r\n selected: boolean\r\n linking: boolean\r\n selectedField: string | null\r\n onToggle: () => void\r\n onScroll: (top: number) => void\r\n onHeaderDown: (event: ReactMouseEvent) => void\r\n onResizeDown: (event: ReactMouseEvent, edges: { width: boolean; height: boolean }) => void\r\n onResizeReset: () => void\r\n onColumnDown: (event: ReactMouseEvent, column: string) => void\r\n onFieldClick: (item: FieldItem) => void\r\n onAddField: (kind: 'dimension' | 'measure', column: { name: string; numeric: boolean }) => void\r\n renaming: boolean\r\n onRenameStart: () => void\r\n /** Nome novo (já validado) ou `null` para cancelar. */\r\n onRename: (name: string | null) => void\r\n onContextMenu: (event: ReactMouseEvent, target: MenuTarget) => void\r\n}) {\r\n const style = ROLE_STYLE[node.role]\r\n const columnActions = ['dimension', 'measure'] as const\r\n return (\r\n <Box\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onContextMenu={(event) => onContextMenu(event, { kind: 'table', uid: node.uid })}\r\n sx={{\r\n position: 'absolute',\r\n left: position.x,\r\n top: position.y,\r\n width: size.width,\r\n height: size.height,\r\n bgcolor: '#23272e',\r\n border: '1px solid',\r\n borderColor: node.error ? 'error.main' : selected ? style.color : '#3a3f47',\r\n borderTop: `3px solid ${style.color}`,\r\n borderRadius: 1,\r\n boxShadow: selected ? `0 0 0 2px ${style.color}55, 0 6px 18px rgba(0,0,0,.4)` : 3,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n userSelect: 'none',\r\n cursor: 'default'\r\n }}\r\n >\r\n <Box\r\n onMouseDown={onHeaderDown}\r\n title={node.error}\r\n sx={{\r\n height: HEADER - 3,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.75,\r\n px: 1,\r\n cursor: 'move',\r\n borderBottom: collapsed ? 0 : '1px solid #3a3f47',\r\n flexShrink: 0\r\n }}\r\n >\r\n <Box component=\"span\" sx={{ color: style.color, fontSize: 13 }}>\r\n ▦\r\n </Box>\r\n {renaming ? (\r\n <TableNameInput value={node.name} onDone={onRename} />\r\n ) : (\r\n <Typography\r\n onDoubleClick={onRenameStart}\r\n title=\"Duplo clique para renomear\"\r\n sx={{\r\n fontWeight: 700,\r\n fontSize: 13,\r\n overflow: 'hidden',\r\n textOverflow: 'ellipsis',\r\n whiteSpace: 'nowrap',\r\n flex: 1\r\n }}\r\n >\r\n {node.name || <em>sem nome</em>}\r\n </Typography>\r\n )}\r\n <Box component=\"span\" title={style.title} sx={{ fontSize: 10, color: style.color }}>\r\n {style.label}\r\n </Box>\r\n {node.error && (\r\n <Box component=\"span\" sx={{ color: 'error.main', fontSize: 12 }}>\r\n ⚠\r\n </Box>\r\n )}\r\n <Box\r\n component=\"button\"\r\n type=\"button\"\r\n aria-label={collapsed ? 'Expandir' : 'Recolher'}\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onClick={onToggle}\r\n sx={{\r\n border: 0,\r\n bgcolor: 'transparent',\r\n color: 'text.secondary',\r\n cursor: 'pointer',\r\n p: 0,\r\n fontSize: 11\r\n }}\r\n >\r\n {collapsed ? '▾' : '▴'}\r\n </Box>\r\n </Box>\r\n {!collapsed && (\r\n <Box\r\n onScroll={(event) => onScroll(event.currentTarget.scrollTop)}\r\n sx={{ overflow: 'auto', flex: 1, py: `${PADDING}px` }}\r\n >\r\n {!node.items.length && (\r\n <Typography\r\n sx={{ fontSize: 11, color: 'text.disabled', px: 1, lineHeight: `${ROW}px` }}\r\n >\r\n sem colunas lidas\r\n </Typography>\r\n )}\r\n {node.items.map((item) =>\r\n item.kind === 'column' ? (\r\n <Box\r\n key={`c:${item.name}`}\r\n data-diagram-node={node.id}\r\n data-diagram-column={item.name}\r\n onMouseDown={(event) => onColumnDown(event, item.name)}\r\n title={\r\n item.missing\r\n ? 'Citada no modelo, mas a tabela não devolve essa coluna'\r\n : 'Arraste até a coluna de outra tabela para relacionar'\r\n }\r\n sx={{\r\n height: ROW,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.75,\r\n px: 1,\r\n fontSize: 12,\r\n cursor: 'crosshair',\r\n '& .column-actions': { display: 'none' },\r\n '&:hover .column-actions': { display: linking ? 'none' : 'flex' },\r\n color: item.missing ? 'error.main' : item.linked ? 'text.primary' : '#adb5bd',\r\n fontWeight: item.linked ? 700 : 400,\r\n '&:hover': { bgcolor: linking ? 'rgba(245,130,32,.25)' : 'rgba(255,255,255,.06)' }\r\n }}\r\n >\r\n <Box\r\n component=\"span\"\r\n sx={{ width: 14, textAlign: 'center', color: 'text.secondary' }}\r\n >\r\n {item.isKey ? '🔑' : item.numeric ? 'Σ' : ''}\r\n </Box>\r\n <Box\r\n component=\"span\"\r\n sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}\r\n >\r\n {item.name}\r\n </Box>\r\n <Box className=\"column-actions\" sx={{ ml: 'auto', gap: 0.25 }}>\r\n {columnActions.map((kind) => (\r\n <Box\r\n key={kind}\r\n component=\"button\"\r\n type=\"button\"\r\n title={\r\n kind === 'dimension'\r\n ? `Nova dimensão com ${node.name}.${item.name}`\r\n : `Nova medida: ${item.numeric ? 'soma' : 'contagem'} de ${node.name}.${item.name}`\r\n }\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onClick={() => onAddField(kind, item)}\r\n sx={{\r\n border: '1px solid #3a3f47',\r\n borderRadius: 0.5,\r\n bgcolor: '#1b1e23',\r\n color: kind === 'measure' ? '#ffd8a8' : '#a5d8ff',\r\n cursor: 'pointer',\r\n fontSize: 10,\r\n lineHeight: '14px',\r\n px: 0.5\r\n }}\r\n >\r\n {kind === 'dimension' ? '+◇' : '+Σ'}\r\n </Box>\r\n ))}\r\n </Box>\r\n </Box>\r\n ) : (\r\n <Box\r\n key={`f:${item.uid}`}\r\n onMouseDown={(event) => event.stopPropagation()}\r\n onClick={() => onFieldClick(item)}\r\n onContextMenu={(event) => onContextMenu(event, { kind: item.kind, uid: item.uid })}\r\n sx={{\r\n height: ROW,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.75,\r\n px: 1,\r\n fontSize: 12,\r\n cursor: 'pointer',\r\n color: item.kind === 'measure' ? '#ffd8a8' : '#a5d8ff',\r\n bgcolor: selectedField === item.uid ? 'rgba(245,130,32,.2)' : undefined,\r\n '&:hover': { bgcolor: 'rgba(255,255,255,.06)' }\r\n }}\r\n >\r\n <Box component=\"span\" sx={{ width: 14, textAlign: 'center' }}>\r\n {item.icon}\r\n </Box>\r\n <Box\r\n component=\"span\"\r\n sx={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}\r\n >\r\n {item.name || <em>sem nome</em>}\r\n </Box>\r\n </Box>\r\n )\r\n )}\r\n </Box>\r\n )}\r\n {/* Alças de redimensionar: borda direita, borda de baixo e o canto (recolhido, só a largura) */}\r\n <Box\r\n onMouseDown={(event) => onResizeDown(event, { width: true, height: false })}\r\n onDoubleClick={onResizeReset}\r\n title=\"Arraste para mudar a largura (duplo clique: tamanho automático)\"\r\n sx={{ ...resizeHandleSx, top: 0, right: -4, bottom: 8, width: 8, cursor: 'ew-resize' }}\r\n />\r\n {!collapsed && (\r\n <>\r\n <Box\r\n onMouseDown={(event) => onResizeDown(event, { width: false, height: true })}\r\n onDoubleClick={onResizeReset}\r\n title=\"Arraste para mudar a altura (duplo clique: tamanho automático)\"\r\n sx={{\r\n ...resizeHandleSx,\r\n left: 0,\r\n right: 8,\r\n bottom: -4,\r\n height: 8,\r\n cursor: 'ns-resize'\r\n }}\r\n />\r\n <Box\r\n onMouseDown={(event) => onResizeDown(event, { width: true, height: true })}\r\n onDoubleClick={onResizeReset}\r\n title=\"Arraste para redimensionar (duplo clique: tamanho automático)\"\r\n sx={{\r\n ...resizeHandleSx,\r\n right: -4,\r\n bottom: -4,\r\n width: 14,\r\n height: 14,\r\n cursor: 'nwse-resize',\r\n // Marquinha no canto, como as janelas\r\n '&::after': {\r\n content: '\"\"',\r\n position: 'absolute',\r\n right: 6,\r\n bottom: 6,\r\n width: 6,\r\n height: 6,\r\n borderRight: '2px solid #5c636e',\r\n borderBottom: '2px solid #5c636e'\r\n },\r\n '&:hover::after': { borderColor: ROLE_STYLE[node.role].color }\r\n }}\r\n />\r\n </>\r\n )}\r\n </Box>\r\n )\r\n}\r\n\r\nconst resizeHandleSx = { position: 'absolute', zIndex: 1 } as const\r\n\r\nconst IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_]*$/\r\n\r\n/** Nome da tabela editado no cabeçalho do card: Enter/sair confirma, Esc cancela. */\r\nfunction TableNameInput({\r\n value,\r\n onDone\r\n}: {\r\n value: string\r\n onDone: (name: string | null) => void\r\n}) {\r\n const [text, setText] = useState(value)\r\n const valid = IDENTIFIER.test(text)\r\n // Enter e o blur que vem depois não confirmam duas vezes\r\n const done = useRef(false)\r\n const finish = (name: string | null) => {\r\n if (done.current) return\r\n done.current = true\r\n onDone(name)\r\n }\r\n return (\r\n <Box\r\n component=\"input\"\r\n autoFocus\r\n value={text}\r\n aria-label=\"Nome da tabela\"\r\n onFocus={(event: FocusEvent<HTMLInputElement>) => event.currentTarget.select()}\r\n onChange={(event: ChangeEvent<HTMLInputElement>) => setText(event.target.value)}\r\n onMouseDown={(event: ReactMouseEvent) => event.stopPropagation()}\r\n onKeyDown={(event: KeyboardEvent) => {\r\n // O Delete/Backspace não pode chegar no canvas (removeria a tabela)\r\n event.stopPropagation()\r\n if (event.key === 'Enter') finish(valid ? text : null)\r\n if (event.key === 'Escape') finish(null)\r\n }}\r\n onBlur={() => finish(valid ? text : null)}\r\n sx={{\r\n flex: 1,\r\n minWidth: 0,\r\n font: 'inherit',\r\n fontSize: 13,\r\n fontWeight: 700,\r\n color: 'text.primary',\r\n bgcolor: '#1b1e23',\r\n border: '1px solid',\r\n borderColor: valid ? 'primary.main' : 'error.main',\r\n borderRadius: 0.5,\r\n px: 0.5,\r\n outline: 'none'\r\n }}\r\n />\r\n )\r\n}\r\n\r\n/** Bloco do painel; com `collapseKey`, o título recolhe/expande (lembrado no navegador). */\r\nfunction PropertyBlock({\r\n title,\r\n collapseKey,\r\n children\r\n}: {\r\n title: string\r\n collapseKey?: string\r\n children: ReactNode\r\n}) {\r\n return (\r\n <Section title={title} collapseKey={collapseKey}>\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1 }}>{children}</Box>\r\n </Section>\r\n )\r\n}\r\n\r\nfunction ColumnSelect({\r\n label,\r\n value,\r\n options,\r\n onChange\r\n}: {\r\n label: string\r\n value: string\r\n options: string[]\r\n onChange: (value: string) => void\r\n}) {\r\n // Sem colunas lidas, digita livre\r\n if (!options.length)\r\n return (\r\n <TextField\r\n size=\"small\"\r\n label={label}\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n sx={{ ...inputSx, flex: 1 }}\r\n />\r\n )\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n label={label}\r\n value={options.includes(value) ? value : ''}\r\n error={!options.includes(value)}\r\n onChange={(e) => onChange(e.target.value)}\r\n sx={{ ...inputSx, flex: 1 }}\r\n >\r\n {options.map((name) => (\r\n <MenuItem key={name} value={name}>\r\n {name}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )\r\n}\r\n\r\nfunction TableSelect({\r\n label,\r\n value,\r\n tables,\r\n onChange\r\n}: {\r\n label: string\r\n value: string\r\n tables: TableRow[]\r\n onChange: (uid: string) => void\r\n}) {\r\n return (\r\n <TextField\r\n select\r\n size=\"small\"\r\n label={label}\r\n value={tables.some((table) => table.uid === value) ? value : ''}\r\n onChange={(e) => onChange(e.target.value)}\r\n sx={{ ...inputSx, flex: 1 }}\r\n >\r\n {tables.map((table) => (\r\n <MenuItem key={table.uid} value={table.uid}>\r\n {table.name}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n )\r\n}\r\n\r\nfunction Properties({\r\n editor,\r\n selection,\r\n columns,\r\n errors,\r\n warnings,\r\n usage,\r\n onSelect,\r\n onTry,\r\n setEditor,\r\n patchTable,\r\n patchRelationship,\r\n patchDimension,\r\n patchMeasure,\r\n removeTable,\r\n commitRename,\r\n addField,\r\n unplaced\r\n}: {\r\n editor: EditorModel\r\n selection: Selection\r\n columns: ModelColumns | null\r\n errors: Record<string, string>\r\n warnings: Record<string, string>\r\n usage: Map<string, number>\r\n onSelect: (selection: Selection) => void\r\n onTry: Props['onTry']\r\n setEditor: Props['setEditor']\r\n patchTable: (uid: string, changes: Partial<TableRow>) => void\r\n patchRelationship: (uid: string, changes: Partial<RelationshipRow>) => void\r\n patchDimension: (uid: string, changes: Partial<DimensionRow>) => void\r\n patchMeasure: (uid: string, changes: Partial<MeasureRow>) => void\r\n removeTable: (uid: string) => void\r\n commitRename: (uid: string, name: string) => void\r\n addField: (kind: 'dimension' | 'measure', table: string) => void\r\n unplaced: FieldItem[]\r\n}) {\r\n const tableName = (uid: string) => editor.tables.find((table) => table.uid === uid)?.name ?? '?'\r\n const columnsOf = (uid: string) => columns?.tables[tableName(uid)] ?? []\r\n const measureNames = editor.measures.map((row) => row.name).filter(Boolean)\r\n const inUse = (name: string) => usage.get(name) ?? 0\r\n const addButtons = (table: string, kinds: ('dimension' | 'measure')[]) =>\r\n kinds.map((kind) => (\r\n <Button key={kind} size=\"small\" onClick={() => addField(kind, table)}>\r\n {kind === 'dimension' ? '+ Dimensão daqui' : '+ Medida daqui'}\r\n </Button>\r\n ))\r\n\r\n if (selection?.kind === 'table') {\r\n const table = editor.tables.find((row) => row.uid === selection.uid)\r\n if (!table) return null\r\n return (\r\n <>\r\n <PropertyBlock title=\"Tabela\" collapseKey=\"diagram:table\">\r\n <RenameField\r\n key={table.uid}\r\n value={table.name}\r\n onCommit={(name) => commitRename(table.uid, name)}\r\n />\r\n <SqlEditor\r\n label=\"sql\"\r\n minRows={3}\r\n maxRows={12}\r\n value={table.sql}\r\n error={errors[`table:${table.name}`]}\r\n onChange={(sql) => patchTable(table.uid, { sql })}\r\n queryTools\r\n />\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Dimensões (marque as colunas)\" collapseKey=\"diagram:dimensions\">\r\n <DimensionPicker\r\n editor={editor}\r\n setEditor={setEditor}\r\n columns={columns}\r\n table={table.name}\r\n onOpen={(uid) => onSelect({ kind: 'dimension', uid })}\r\n />\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Dicionário\" collapseKey=\"diagram:dictionary\">\r\n <DictionaryFields row={table} onPatch={(changes) => patchTable(table.uid, changes)} />\r\n </PropertyBlock>\r\n <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>\r\n {addButtons(table.name, ['dimension', 'measure'])}\r\n <Button size=\"small\" color=\"error\" onClick={() => removeTable(table.uid)}>\r\n Remover tabela\r\n </Button>\r\n </Box>\r\n </>\r\n )\r\n }\r\n\r\n if (selection?.kind === 'relationship') {\r\n const index = editor.relationships.findIndex((row) => row.uid === selection.uid)\r\n const row = editor.relationships[index]\r\n if (!row) return null\r\n return (\r\n <>\r\n <PropertyBlock title=\"Relacionamento\">\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n Muitos para um (*:1). O filtro vai do lado 1 para o lado N: filtrar{' '}\r\n <b>{tableName(row.toTable)}</b> filtra as linhas de <b>{tableName(row.fromTable)}</b>.\r\n </Typography>\r\n {errors[`relationship:${index}`] && (\r\n <Alert severity=\"error\" sx={{ fontSize: 12 }}>\r\n {errors[`relationship:${index}`]}\r\n </Alert>\r\n )}\r\n <Typography sx={{ fontSize: 12, fontWeight: 700 }}>Lado N (*)</Typography>\r\n <Box sx={{ display: 'flex', gap: 1 }}>\r\n <TableSelect\r\n label=\"tabela\"\r\n value={row.fromTable}\r\n tables={editor.tables}\r\n onChange={(fromTable) => patchRelationship(row.uid, { fromTable })}\r\n />\r\n <ColumnSelect\r\n label=\"coluna\"\r\n value={row.fromColumn}\r\n options={columnsOf(row.fromTable)}\r\n onChange={(fromColumn) => patchRelationship(row.uid, { fromColumn })}\r\n />\r\n </Box>\r\n <Typography sx={{ fontSize: 12, fontWeight: 700 }}>Lado 1</Typography>\r\n <Box sx={{ display: 'flex', gap: 1 }}>\r\n <TableSelect\r\n label=\"tabela\"\r\n value={row.toTable}\r\n tables={editor.tables}\r\n onChange={(toTable) => patchRelationship(row.uid, { toTable })}\r\n />\r\n <ColumnSelect\r\n label=\"coluna\"\r\n value={row.toColumn}\r\n options={columnsOf(row.toTable)}\r\n onChange={(toColumn) => patchRelationship(row.uid, { toColumn })}\r\n />\r\n </Box>\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Opções\">\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={row.inner}\r\n onChange={(e) => patchRelationship(row.uid, { inner: e.target.checked })}\r\n />\r\n }\r\n label={\r\n <Typography sx={{ fontSize: 12 }}>\r\n Pressupor integridade referencial (INNER JOIN): linhas de {tableName(row.fromTable)}{' '}\r\n sem par em {tableName(row.toTable)} ficam de fora, em vez de virar um grupo em\r\n branco. A tabela do lado 1 entra sempre na consulta.\r\n </Typography>\r\n }\r\n />\r\n </PropertyBlock>\r\n <Box sx={{ display: 'flex', gap: 1 }}>\r\n <Button\r\n size=\"small\"\r\n onClick={() =>\r\n patchRelationship(row.uid, {\r\n fromTable: row.toTable,\r\n fromColumn: row.toColumn,\r\n toTable: row.fromTable,\r\n toColumn: row.fromColumn\r\n })\r\n }\r\n >\r\n Inverter lados\r\n </Button>\r\n <Button\r\n size=\"small\"\r\n color=\"error\"\r\n onClick={() => {\r\n setEditor((current) => ({\r\n ...current,\r\n relationships: current.relationships.filter((item) => item.uid !== row.uid)\r\n }))\r\n onSelect(null)\r\n }}\r\n >\r\n Remover\r\n </Button>\r\n </Box>\r\n </>\r\n )\r\n }\r\n\r\n if (selection?.kind === 'dimension') {\r\n const row = editor.dimensions.find((item) => item.uid === selection.uid)\r\n if (!row) return null\r\n return (\r\n <>\r\n <PropertyBlock title=\"Dimensão\">\r\n <NameField\r\n label=\"nome\"\r\n value={row.name}\r\n onChange={(name) => patchDimension(row.uid, { name })}\r\n />\r\n <TextField\r\n select\r\n size=\"small\"\r\n label=\"tipo\"\r\n value={row.type}\r\n onChange={(e) =>\r\n patchDimension(row.uid, { type: e.target.value as DimensionRow['type'] })\r\n }\r\n sx={inputSx}\r\n >\r\n <MenuItem value=\"string\">string</MenuItem>\r\n <MenuItem value=\"number\">number</MenuItem>\r\n </TextField>\r\n <DimensionSource\r\n key={row.uid}\r\n row={row}\r\n editor={editor}\r\n columns={columns}\r\n error={errors[`dimension:${row.name}`]}\r\n warning={warnings[`dimension:${row.name}`]}\r\n onPatch={(changes) => patchDimension(row.uid, changes)}\r\n />\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Dicionário\" collapseKey=\"diagram:dictionary\">\r\n <DictionaryFields row={row} onPatch={(changes) => patchDimension(row.uid, changes)} />\r\n </PropertyBlock>\r\n <FieldActions\r\n name={row.name}\r\n uses={inUse(row.name)}\r\n onTry={() => onTry({ dimensions: [row.name], measures: [] })}\r\n onRemove={() => {\r\n setEditor((current) => ({\r\n ...current,\r\n dimensions: current.dimensions.filter((item) => item.uid !== row.uid)\r\n }))\r\n onSelect(null)\r\n }}\r\n />\r\n </>\r\n )\r\n }\r\n\r\n if (selection?.kind === 'measure') {\r\n const row = editor.measures.find((item) => item.uid === selection.uid)\r\n if (!row) return null\r\n return (\r\n <>\r\n <PropertyBlock title=\"Medida\">\r\n <NameField\r\n label=\"nome\"\r\n value={row.name}\r\n onChange={(name) => patchMeasure(row.uid, { name })}\r\n />\r\n <MeasureTypeSelect\r\n value={row.type}\r\n onChange={(type) => patchMeasure(row.uid, { type })}\r\n />\r\n <MeasureDefinition\r\n row={row}\r\n measureNames={measureNames}\r\n error={errors[`measure:${row.name}`]}\r\n onPatch={(changes) => patchMeasure(row.uid, changes)}\r\n />\r\n <FormatFields row={row} onPatch={(changes) => patchMeasure(row.uid, changes)} />\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Dicionário\" collapseKey=\"diagram:dictionary\">\r\n <DictionaryFields row={row} onPatch={(changes) => patchMeasure(row.uid, changes)} />\r\n </PropertyBlock>\r\n <FieldActions\r\n name={row.name}\r\n uses={inUse(row.name)}\r\n onTry={() => onTry({ dimensions: [], measures: [row.name] })}\r\n onRemove={() => {\r\n setEditor((current) => ({\r\n ...current,\r\n measures: current.measures.filter((item) => item.uid !== row.uid)\r\n }))\r\n onSelect(null)\r\n }}\r\n />\r\n </>\r\n )\r\n }\r\n\r\n // Nada selecionado: resumo e a lista de relacionamentos (\"Gerenciar relações\")\r\n const formulas = editor.measures.filter((row) => !isAggregate(row))\r\n return (\r\n <>\r\n <PropertyBlock title=\"Modelo\" collapseKey=\"diagram:model\">\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n {`${editor.tables.length} tabela(s), ${editor.relationships.length} relacionamento(s), ${editor.dimensions.length} dimensão(ões), ${editor.measures.length} medida(s). Clique num card, linha ou campo para editar.`}\r\n </Typography>\r\n </PropertyBlock>\r\n <PropertyBlock title=\"Relacionamentos\" collapseKey=\"diagram:relationships\">\r\n {!editor.relationships.length && (\r\n <Typography sx={{ fontSize: 12, color: 'text.disabled' }}>\r\n Nenhum. Arraste a coluna da fato até a chave da dimensão.\r\n </Typography>\r\n )}\r\n {editor.relationships.map((row, index) => (\r\n <Box\r\n key={row.uid}\r\n component=\"button\"\r\n type=\"button\"\r\n onClick={() => onSelect({ kind: 'relationship', uid: row.uid })}\r\n sx={{\r\n textAlign: 'left',\r\n border: 1,\r\n borderColor: errors[`relationship:${index}`] ? 'error.main' : 'divider',\r\n borderRadius: 1,\r\n bgcolor: 'transparent',\r\n color: 'text.primary',\r\n fontFamily: MONO,\r\n fontSize: 11,\r\n p: 0.75,\r\n cursor: 'pointer',\r\n '&:hover': { bgcolor: 'rgba(255,255,255,.05)' }\r\n }}\r\n >\r\n {tableName(row.fromTable)}.{row.fromColumn} * → 1 {tableName(row.toTable)}.\r\n {row.toColumn}\r\n </Box>\r\n ))}\r\n </PropertyBlock>\r\n {!!unplaced.length && (\r\n <PropertyBlock title=\"Fora dos cards\">\r\n <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>\r\n O SQL não cita uma tabela do modelo (<code>tabela.coluna</code>).\r\n </Typography>\r\n {unplaced.map((item) => (\r\n <Button\r\n key={item.uid}\r\n size=\"small\"\r\n onClick={() => onSelect({ kind: item.kind, uid: item.uid })}\r\n sx={{ justifyContent: 'flex-start', fontFamily: MONO }}\r\n >\r\n {item.icon} {item.name || 'sem nome'}\r\n </Button>\r\n ))}\r\n </PropertyBlock>\r\n )}\r\n <PropertyBlock title=\"Medidas calculadas\" collapseKey=\"diagram:formulas\">\r\n {formulas.map((row) => (\r\n <Button\r\n key={row.uid}\r\n size=\"small\"\r\n onClick={() => onSelect({ kind: 'measure', uid: row.uid })}\r\n sx={{ justifyContent: 'flex-start', fontFamily: MONO }}\r\n >\r\n {row.type === 'ratio' ? '÷' : 'ƒ'} {row.name}\r\n </Button>\r\n ))}\r\n <Button\r\n size=\"small\"\r\n onClick={() => onSelect({ kind: 'measure', uid: addFormulaTo(setEditor) })}\r\n >\r\n + Medida calculada\r\n </Button>\r\n </PropertyBlock>\r\n <Divider sx={{ my: 1 }} />\r\n <Typography sx={{ fontSize: 11, color: 'text.disabled' }}>\r\n Razões e fórmulas não pertencem a uma tabela: aparecem em \"Medidas calculadas\".\r\n </Typography>\r\n </>\r\n )\r\n}\r\n\r\n/** Nome da tabela: renomeia (e corrige as referências `tabela.coluna`) ao sair do campo. */\r\nfunction RenameField({ value, onCommit }: { value: string; onCommit: (name: string) => void }) {\r\n const [text, setText] = useState(value)\r\n useEffect(() => setText(value), [value])\r\n return (\r\n <NameField\r\n label=\"nome (renomeia as referências ao sair do campo)\"\r\n value={text}\r\n onChange={setText}\r\n onBlur={() => {\r\n if (IDENTIFIER.test(text)) onCommit(text)\r\n else setText(value)\r\n }}\r\n />\r\n )\r\n}\r\n\r\nfunction FieldActions({\r\n name,\r\n uses,\r\n onTry,\r\n onRemove\r\n}: {\r\n name: string\r\n uses: number\r\n onTry: () => void\r\n onRemove: () => void\r\n}) {\r\n return (\r\n <Box sx={{ display: 'flex', gap: 1, alignItems: 'center' }}>\r\n <Button size=\"small\" onClick={onTry} disabled={!name}>\r\n ▶ Testar no playground\r\n </Button>\r\n <Tooltip title={uses ? 'Em uso na página: as consultas que usam vão falhar' : ''}>\r\n <span>\r\n <Button size=\"small\" color=\"error\" onClick={onRemove}>\r\n Remover\r\n </Button>\r\n </span>\r\n </Tooltip>\r\n {!!uses && (\r\n <Typography sx={{ fontSize: 11, color: 'text.secondary' }}>\r\n {uses} consulta(s) usando\r\n </Typography>\r\n )}\r\n </Box>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Button,\r\n Chip,\r\n Dialog,\r\n DialogActions,\r\n DialogContent,\r\n DialogTitle,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport { useEffect, useMemo, useRef, useState, useSyncExternalStore } from 'react'\r\nimport type { DashboardDevtoolsContext } from '../client/DashboardProvider'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport { canonicalJson } from '../codegen'\r\nimport type { ModelDef } from '../model'\r\nimport type {\r\n DevtoolsCapabilities,\r\n ModelColumns,\r\n ModelValidation,\r\n SaveModelResult,\r\n SchemaTable\r\n} from '../types'\r\nimport { AUTO_APPLY_DELAY, useAutoApply } from './autoApply'\r\nimport { lineDiff } from './lineDiff'\r\nimport { ModelDiagram } from './ModelDiagram'\r\nimport { type EditorModel, fromEditor, toEditor, validateEditor, withoutDiagram } from './modelCode'\r\nimport { SqlCompletionsContext } from './SqlEditor'\r\nimport { errorMessage } from './store'\r\nimport { AutoApplySwitch, ConfirmButton, FileDiff, MONO } from './ui'\r\n\r\ntype Props = {\r\n devtools: DashboardDevtoolsContext\r\n /** Modelo registrado no servidor. */\r\n original: ModelDef\r\n capabilities: DevtoolsCapabilities | null\r\n /** Tabelas do banco, para o autocomplete (vazio enquanto carrega). */\r\n tables: SchemaTable[]\r\n /** Abre o playground com essa combinação. */\r\n onTry: (selection: { dimensions: string[]; measures: string[] }) => void\r\n /** O arquivo do modelo foi reescrito: recarregar o modelo registrado. */\r\n onSaved: () => void\r\n}\r\n\r\nconst same = (a: unknown, b: unknown) => canonicalJson(a) === canonicalJson(b)\r\n\r\n/**\r\n * Editor do modelo: o diagrama (cards e relacionamentos, como a exibição de modelo do Power BI) e o\r\n * painel de propriedades ao lado. As edições ficam locais até \"Aplicar\": aí o SQL de cada pedaço é\r\n * validado no banco e o rascunho vai junto de todas as consultas da página (o servidor usa ele no\r\n * lugar do modelo registrado). \"Salvar no arquivo\" reescreve `src/dashboard/models/<nome>.ts`.\r\n */\r\nexport function ModelPanel({ devtools, original, capabilities, tables, onTry, onSaved }: Props) {\r\n const { store, draft, setDraft } = devtools\r\n const { fetcher, model: modelName } = useDashboard()\r\n const [editor, setEditor] = useState<EditorModel>(() => toEditor(draft ?? original))\r\n const [checked, setChecked] = useState<{ structure: string; result: ModelValidation } | null>(\r\n null\r\n )\r\n const [columns, setColumns] = useState<ModelColumns | null>(null)\r\n const [columnErrors, setColumnErrors] = useState<Record<string, string>>({})\r\n const [busy, setBusy] = useState<string | null>(null)\r\n const [actionError, setActionError] = useState<string | null>(null)\r\n const [save, setSave] = useState<SaveModelResult | null>(null)\r\n\r\n // Rascunho que o próprio editor aplicou: o editor já está nele (ou adiante, se continuaram\r\n // editando enquanto o SQL era validado) e não volta\r\n const applied = useRef<string | null>(null)\r\n // Rascunho descartado ou modelo recarregado: o editor acompanha\r\n useEffect(() => {\r\n const next = draft ?? original\r\n if (draft && canonicalJson(draft) === applied.current) return\r\n setEditor((current) => (same(fromEditor(current), next) ? current : toEditor(next)))\r\n }, [draft, original])\r\n const errors = useMemo(() => validateEditor(editor), [editor])\r\n const edited = useMemo(() => fromEditor(editor), [editor])\r\n // Erro de validação é do SQL validado; editou, deixa de valer (mover card no diagrama não conta)\r\n const structure = useMemo(() => canonicalJson(withoutDiagram(edited)), [edited])\r\n const validation = checked?.structure === structure ? checked.result : null\r\n const reference = draft ?? original\r\n const dirty = !same(edited, reference)\r\n const differsFromOriginal = !same(edited, original)\r\n\r\n // Quantas consultas ativas usam cada nome (dimensão, filtro ou medida)\r\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\r\n const usage = useMemo(() => {\r\n const count = new Map<string, number>()\r\n for (const { last } of snapshot.instances) {\r\n const { dimensions = [], measures = [], filters = {} } = last.query\r\n for (const name of new Set([...dimensions, ...measures, ...Object.keys(filters)]))\r\n count.set(name, (count.get(name) ?? 0) + 1)\r\n }\r\n return count\r\n }, [snapshot])\r\n\r\n const removed = [\r\n ...Object.keys(original.dimensions).filter((name) => !edited.dimensions[name]),\r\n ...Object.keys(original.measures).filter((name) => !edited.measures[name]),\r\n ...Object.keys(original.tables).filter((name) => !edited.tables[name])\r\n ]\r\n\r\n // --- ações que vão ao servidor ---\r\n\r\n const validateSql = async () => {\r\n const result = await fetcher({ model: modelName, devtools: { validate: true, model: edited } })\r\n const next = result.devtools?.validation ?? null\r\n setChecked(next && { structure, result: next })\r\n if (next) setColumns(next.columns)\r\n return next\r\n }\r\n\r\n // Só as colunas (uma linha de cada tabela): o diagrama precisa delas para listar e relacionar\r\n const loadColumns = async () => {\r\n if (validateEditor(editor).length) {\r\n setActionError('Corrija os erros do modelo antes de ler as colunas.')\r\n return\r\n }\r\n await act('columns', async () => {\r\n const result = await fetcher({ model: modelName, devtools: { columns: true, model: edited } })\r\n setColumns(result.devtools?.columns ?? null)\r\n setColumnErrors(result.devtools?.columnErrors ?? {})\r\n })\r\n }\r\n\r\n const act = async (name: string, action: () => Promise<void>) => {\r\n setBusy(name)\r\n setActionError(null)\r\n try {\r\n await action()\r\n } catch (error) {\r\n setActionError(errorMessage(error))\r\n } finally {\r\n setBusy(null)\r\n }\r\n }\r\n\r\n const apply = () =>\r\n act('apply', async () => {\r\n // Só moveu cards: não há SQL novo para validar\r\n const onlyLayout = canonicalJson(withoutDiagram(reference)) === structure\r\n const result = onlyLayout ? null : await validateSql()\r\n if (result && Object.keys(result.errors).length) return\r\n applied.current = differsFromOriginal ? canonicalJson(edited) : null\r\n setDraft(differsFromOriginal ? edited : null)\r\n })\r\n\r\n // Aplicar automaticamente: depois de uma pausa nas edições; cada versão do modelo é tentada uma\r\n // vez só (SQL recusado ou erro de rede não ficam repetindo — edite de novo ou aplique à mão)\r\n const autoApply = useAutoApply()\r\n const editedKey = canonicalJson(edited)\r\n const attempted = useRef<string | null>(null)\r\n useEffect(() => {\r\n if (!autoApply || !dirty || errors.length || busy || attempted.current === editedKey) return\r\n const timer = setTimeout(() => {\r\n attempted.current = editedKey\r\n void apply()\r\n }, AUTO_APPLY_DELAY.model)\r\n return () => clearTimeout(timer)\r\n }, [autoApply, editedKey, dirty, errors.length, busy])\r\n\r\n const previewSave = () =>\r\n act('save', async () => {\r\n const result = await fetcher({\r\n model: modelName,\r\n devtools: { save: 'preview', model: edited }\r\n })\r\n setSave(result.devtools?.save ?? null)\r\n })\r\n\r\n const writeSave = () =>\r\n act('save', async () => {\r\n await fetcher({ model: modelName, devtools: { save: 'write', model: edited } })\r\n setSave(null)\r\n setDraft(null)\r\n onSaved()\r\n })\r\n\r\n const completions = useMemo(\r\n () => ({\r\n tables,\r\n // `tabela.` completa as colunas da tabela do modelo\r\n modelColumns: Object.fromEntries(\r\n editor.tables.map((row) => [row.name, columns?.tables[row.name] ?? []])\r\n ),\r\n modelSql: Object.fromEntries(editor.tables.map((row) => [row.name, row.sql])),\r\n testSql: async (sql: string) => {\r\n const result = await fetcher({ model: modelName, devtools: { testSql: sql } })\r\n if (!result.devtools?.sqlTest) throw new Error('O servidor não devolveu o teste do SQL')\r\n return result.devtools.sqlTest\r\n }\r\n }),\r\n [tables, columns, editor.tables, fetcher, modelName]\r\n )\r\n\r\n const validationErrors = validation ? Object.entries(validation.errors) : []\r\n\r\n return (\r\n <SqlCompletionsContext.Provider value={completions}>\r\n <Box sx={{ display: 'flex', flexDirection: 'column', height: '100%', minHeight: 0 }}>\r\n <Box sx={{ px: 1.5, '& .MuiAlert-root': { my: 0.5, py: 0 } }}>\r\n {draft && (\r\n <Alert severity=\"warning\">\r\n Rascunho aplicado: as consultas desta página estão usando o modelo editado, não o\r\n registrado em <code>src/dashboard/models</code>.\r\n {capabilities?.saveModel\r\n ? ' Use \"Salvar no arquivo\" quando terminar.'\r\n : ' Copie o código para o arquivo quando terminar.'}\r\n </Alert>\r\n )}\r\n {actionError && (\r\n <Alert severity=\"error\" sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {actionError}\r\n </Alert>\r\n )}\r\n {!!validationErrors.length && (\r\n <Alert severity=\"error\">\r\n O banco recusou {validationErrors.length} pedaço(s) do modelo — veja os campos\r\n marcados. O rascunho não foi aplicado.\r\n {validation?.errors.model && <div>{validation.errors.model}</div>}\r\n </Alert>\r\n )}\r\n </Box>\r\n\r\n <Box sx={{ flex: 1, minHeight: 0, borderTop: 1, borderColor: 'divider' }}>\r\n <ModelDiagram\r\n editor={editor}\r\n setEditor={setEditor}\r\n columns={columns}\r\n errors={{ ...columnErrors, ...validation?.errors }}\r\n warnings={validation?.warnings ?? {}}\r\n loadingColumns={busy === 'columns'}\r\n onLoadColumns={loadColumns}\r\n onTry={onTry}\r\n usage={usage}\r\n />\r\n </Box>\r\n\r\n <Box\r\n sx={{\r\n borderTop: 1,\r\n borderColor: 'divider',\r\n p: 1,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 1,\r\n flexWrap: 'wrap'\r\n }}\r\n >\r\n {errors.length ? (\r\n <Tooltip title={<Box sx={{ whiteSpace: 'pre-line' }}>{errors.join('\\n')}</Box>}>\r\n <Chip color=\"error\" size=\"small\" label={`${errors.length} erro(s): ${errors[0]}`} />\r\n </Tooltip>\r\n ) : validation && !validationErrors.length ? (\r\n <Chip color=\"success\" size=\"small\" label=\"SQL validado no banco\" />\r\n ) : (\r\n <Chip color=\"success\" size=\"small\" variant=\"outlined\" label=\"modelo válido\" />\r\n )}\r\n {!!removed.length && (\r\n <Chip size=\"small\" color=\"warning\" label={`removidos: ${removed.join(', ')}`} />\r\n )}\r\n <Box sx={{ ml: 'auto', display: 'flex', gap: 1, flexWrap: 'wrap', alignItems: 'center' }}>\r\n <AutoApplySwitch applying={busy === 'apply'} />\r\n <Button\r\n size=\"small\"\r\n disabled={!!errors.length || !!busy}\r\n onClick={() =>\r\n act('validate', async () => {\r\n await validateSql()\r\n })\r\n }\r\n title=\"Executa cada pedaço do modelo no banco com poucas chaves\"\r\n >\r\n {busy === 'validate' ? 'Validando…' : 'Validar SQL'}\r\n </Button>\r\n {!autoApply && (\r\n <ConfirmButton\r\n size=\"small\"\r\n disabled={!dirty}\r\n onConfirm={() => setEditor(toEditor(reference))}\r\n title=\"Desfaz as edições ainda não aplicadas\"\r\n confirmTitle=\"Desfazer as edições?\"\r\n confirmText=\"As edições do modelo ainda não aplicadas na página serão perdidas; o editor volta ao modelo que a página usa.\"\r\n confirmLabel=\"Desfazer\"\r\n >\r\n Desfazer\r\n </ConfirmButton>\r\n )}\r\n <ConfirmButton\r\n size=\"small\"\r\n color=\"warning\"\r\n disabled={!draft}\r\n onConfirm={() => setDraft(null)}\r\n title=\"Volta a usar o modelo registrado no servidor\"\r\n confirmTitle=\"Descartar o rascunho?\"\r\n confirmText=\"A página volta a usar o modelo registrado no servidor; as edições do rascunho serão perdidas.\"\r\n confirmLabel=\"Descartar\"\r\n >\r\n Descartar rascunho\r\n </ConfirmButton>\r\n {capabilities?.saveModel && (\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n disabled={!differsFromOriginal || !!errors.length || !!busy}\r\n onClick={previewSave}\r\n title={`Reescreve src/dashboard/models/${original.name}.ts`}\r\n >\r\n {busy === 'save' ? 'Gerando…' : 'Salvar no arquivo'}\r\n </Button>\r\n )}\r\n {!autoApply && (\r\n <Button\r\n size=\"small\"\r\n variant=\"contained\"\r\n disabled={!dirty || !!errors.length || !!busy}\r\n onClick={apply}\r\n >\r\n {busy === 'apply' ? 'Validando…' : 'Aplicar na página'}\r\n </Button>\r\n )}\r\n </Box>\r\n </Box>\r\n </Box>\r\n\r\n <Dialog open={!!save} onClose={() => setSave(null)} maxWidth=\"lg\" fullWidth>\r\n <DialogTitle>Salvar no arquivo</DialogTitle>\r\n <DialogContent>\r\n <Typography sx={{ fontFamily: MONO, fontSize: 12, mb: 1 }}>{save?.path}</Typography>\r\n {save?.warnings.map((warning) => (\r\n <Alert key={warning} severity=\"warning\" sx={{ mb: 1 }}>\r\n {warning}\r\n </Alert>\r\n ))}\r\n {save && <FileDiff lines={lineDiff(save.previous, save.content)} />}\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary', mt: 1 }}>\r\n O Next recarrega o modelo sozinho; o rascunho é descartado. O lint-staged formata o\r\n arquivo no commit.\r\n </Typography>\r\n </DialogContent>\r\n <DialogActions>\r\n <Button onClick={() => setSave(null)}>Cancelar</Button>\r\n <Button\r\n variant=\"contained\"\r\n disabled={!save || save.previous === save.content || !!busy}\r\n onClick={writeSave}\r\n >\r\n Gravar\r\n </Button>\r\n </DialogActions>\r\n </Dialog>\r\n </SqlCompletionsContext.Provider>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Autocomplete,\r\n Box,\r\n Button,\r\n Checkbox,\r\n Chip,\r\n FormControlLabel,\r\n TextField\r\n} from '@mui/material'\r\nimport { useEffect, useState } from 'react'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport type { ModelDef } from '../model'\r\nimport type { DashboardQueryDebug, DashboardRow } from '../types'\r\nimport { errorMessage } from './store'\r\nimport { CodeBlock, Empty, inlineParams, MONO, ResultTable, Section } from './ui'\r\n\r\nexport type PlaygroundSelection = { dimensions: string[]; measures: string[] }\r\n\r\ntype Props = {\r\n /** Modelo em vigor na página (rascunho aplicado ou o registrado). */\r\n model: ModelDef\r\n selection: PlaygroundSelection\r\n onSelectionChange: (selection: PlaygroundSelection) => void\r\n}\r\n\r\ntype Outcome = { rows: DashboardRow[]; debug?: DashboardQueryDebug; ms: number } | { error: string }\r\n\r\n/** Consulta avulsa ao modelo: qualquer combinação de dimensões e medidas, com ou sem os filtros. */\r\nexport function PlaygroundPanel({ model, selection, onSelectionChange }: Props) {\r\n const { model: modelName, filters, fetcher } = useDashboard()\r\n const [useFilters, setUseFilters] = useState(true)\r\n const [running, setRunning] = useState(false)\r\n const [outcome, setOutcome] = useState<Outcome | null>(null)\r\n\r\n const run = async () => {\r\n setRunning(true)\r\n const startedAt = Date.now()\r\n try {\r\n const result = await fetcher({\r\n model: modelName,\r\n dimensions: selection.dimensions,\r\n measures: selection.measures,\r\n filters: useFilters ? filters : {}\r\n })\r\n setOutcome({ rows: result.rows, debug: result.devtools?.debug, ms: Date.now() - startedAt })\r\n } catch (error) {\r\n setOutcome({ error: errorMessage(error) })\r\n } finally {\r\n setRunning(false)\r\n }\r\n }\r\n\r\n // \"Testar\" no editor chega aqui com a seleção pronta: já executa\r\n const key = JSON.stringify(selection)\r\n useEffect(() => {\r\n if (selection.dimensions.length || selection.measures.length) run()\r\n }, [key])\r\n\r\n const empty = !selection.dimensions.length && !selection.measures.length\r\n\r\n return (\r\n <Box sx={{ p: 1.5, overflow: 'auto', height: '100%' }}>\r\n <Box sx={{ display: 'flex', gap: 1, alignItems: 'flex-start', flexWrap: 'wrap', mb: 2 }}>\r\n <Autocomplete\r\n multiple\r\n size=\"small\"\r\n options={Object.keys(model.dimensions)}\r\n value={selection.dimensions}\r\n onChange={(_, dimensions) => onSelectionChange({ ...selection, dimensions })}\r\n renderInput={(params) => <TextField {...params} label=\"Dimensões\" />}\r\n sx={{ minWidth: 280, flex: 1 }}\r\n />\r\n <Autocomplete\r\n multiple\r\n size=\"small\"\r\n options={Object.keys(model.measures)}\r\n value={selection.measures}\r\n onChange={(_, measures) => onSelectionChange({ ...selection, measures })}\r\n renderInput={(params) => <TextField {...params} label=\"Medidas\" />}\r\n sx={{ minWidth: 280, flex: 1 }}\r\n />\r\n <FormControlLabel\r\n control={\r\n <Checkbox checked={useFilters} onChange={(e) => setUseFilters(e.target.checked)} />\r\n }\r\n label=\"Usar filtros da página\"\r\n />\r\n <Button variant=\"contained\" disabled={empty || running} onClick={run}>\r\n {running ? 'Executando…' : 'Executar'}\r\n </Button>\r\n </Box>\r\n\r\n {!outcome ? (\r\n <Empty>Escolha dimensões e/ou medidas e execute.</Empty>\r\n ) : 'error' in outcome ? (\r\n <Alert severity=\"error\" sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {outcome.error}\r\n </Alert>\r\n ) : (\r\n <>\r\n <Box sx={{ display: 'flex', gap: 1, mb: 1.5 }}>\r\n <Chip size=\"small\" label={`${outcome.rows.length} linhas`} />\r\n <Chip size=\"small\" label={`total ${outcome.ms} ms`} />\r\n {outcome.debug && (\r\n <Chip\r\n size=\"small\"\r\n label={outcome.debug.cached ? 'cache' : `banco ${outcome.debug.durationMs} ms`}\r\n />\r\n )}\r\n {outcome.debug?.draft && <Chip size=\"small\" color=\"warning\" label=\"rascunho\" />}\r\n </Box>\r\n <Section title=\"Resultado\">\r\n <ResultTable rows={outcome.rows} maxHeight={420} />\r\n </Section>\r\n {outcome.debug && (\r\n <Section title=\"SQL gerado\">\r\n <CodeBlock sql code={inlineParams(outcome.debug.sql, outcome.debug.params)} />\r\n </Section>\r\n )}\r\n </>\r\n )}\r\n </Box>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Button,\r\n Checkbox,\r\n Chip,\r\n FormControlLabel,\r\n List,\r\n ListItemButton,\r\n MenuItem,\r\n TextField,\r\n ToggleButton,\r\n ToggleButtonGroup,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport { type ReactNode, useEffect, useState, useSyncExternalStore } from 'react'\r\nimport type { DashboardDevtoolsContext } from '../client/DashboardProvider'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport { diffRows, type RowDiff } from '../compare'\r\nimport type { DashboardQueryDebug, DashboardRow, DevtoolsCapabilities, ProfileStep } from '../types'\r\nimport { scrollToQuery } from './Inspector'\r\nimport { errorMessage, type QueryRun, type RunStatus } from './store'\r\nimport {\r\n CodeBlock,\r\n Empty,\r\n inlineParams,\r\n MONO,\r\n ResultTable,\r\n RowDiffTable,\r\n Section,\r\n STATUS_LABEL,\r\n StatusDot\r\n} from './ui'\r\n\r\nexport type QuerySelection = { instanceId: string; runId?: number }\r\n\r\ntype Props = {\r\n devtools: DashboardDevtoolsContext\r\n capabilities: DevtoolsCapabilities | null\r\n selected: QuerySelection | null\r\n onSelect: (selection: QuerySelection) => void\r\n /** Destaca o componente da consulta na página. */\r\n onHover: (instanceId: string | null) => void\r\n onClearServerCache: () => void\r\n}\r\n\r\nconst queryKey = (run: QueryRun) => JSON.stringify(run.query)\r\n\r\ntype SortKey = 'default' | 'label' | 'duration' | 'rows' | 'status'\r\n\r\nconst SORT_LABEL: Record<SortKey, string> = {\r\n default: 'ordem da página',\r\n label: 'nome',\r\n duration: 'mais lentas',\r\n rows: 'mais linhas',\r\n status: 'erros primeiro'\r\n}\r\n\r\nconst SORT_KEY = 'bm-dashboard-devtools:queries-sort'\r\n\r\n/** Problemas primeiro: erro, em andamento, cancelada, ok. */\r\nconst STATUS_ORDER: Record<RunStatus, number> = { error: 0, loading: 1, cancelled: 2, success: 3 }\r\n\r\nfunction loadSort(): SortKey {\r\n try {\r\n const saved = localStorage.getItem(SORT_KEY) as SortKey | null\r\n return saved && saved in SORT_LABEL ? saved : 'default'\r\n } catch {\r\n return 'default'\r\n }\r\n}\r\n\r\n/** Ordena a lista; empate mantém a ordem original (página ou mais recente primeiro). */\r\nfunction sortRuns(runs: QueryRun[], key: SortKey) {\r\n if (key === 'default') return runs\r\n const compare = (a: QueryRun, b: QueryRun) => {\r\n switch (key) {\r\n case 'label':\r\n return a.label.localeCompare(b.label, 'pt-BR', { numeric: true })\r\n case 'duration':\r\n // Em andamento conta o tempo até agora: consulta travada aparece no topo\r\n return (\r\n (b.durationMs ?? Date.now() - b.startedAt) - (a.durationMs ?? Date.now() - a.startedAt)\r\n )\r\n case 'rows':\r\n return (b.rows?.length ?? -1) - (a.rows?.length ?? -1)\r\n case 'status':\r\n return STATUS_ORDER[a.status] - STATUS_ORDER[b.status]\r\n }\r\n }\r\n return [...runs].sort(compare)\r\n}\r\n\r\n/** Consultas ativas na página (uma por componente) e o histórico de execuções. */\r\nexport function QueriesPanel({\r\n devtools,\r\n capabilities,\r\n selected,\r\n onSelect,\r\n onHover,\r\n onClearServerCache\r\n}: Props) {\r\n const { store, refresh } = devtools\r\n const snapshot = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot)\r\n const [view, setView] = useState<'active' | 'history'>('active')\r\n const [sort, setSort] = useState(loadSort)\r\n const changeSort = (next: SortKey) => {\r\n setSort(next)\r\n try {\r\n localStorage.setItem(SORT_KEY, next)\r\n } catch {}\r\n }\r\n\r\n const runs: QueryRun[] = sortRuns(\r\n view === 'active' ? snapshot.instances.map((instance) => instance.last) : snapshot.history,\r\n sort\r\n )\r\n const instanceById = new Map(snapshot.instances.map((item) => [item.instanceId, item]))\r\n\r\n // Mesma consulta pedida por mais de um componente: o cache do endpoint segura, mas vale saber\r\n const sameQuery = new Map<string, number>()\r\n for (const { last } of snapshot.instances)\r\n sameQuery.set(queryKey(last), (sameQuery.get(queryKey(last)) ?? 0) + 1)\r\n\r\n const storms = snapshot.instances.filter((item) => item.storm)\r\n\r\n // Na aba \"ativas\" a seleção acompanha a instância (cada nova execução substitui a anterior)\r\n const current =\r\n (view === 'history' && selected?.runId\r\n ? snapshot.history.find((run) => run.runId === selected.runId)\r\n : selected && instanceById.get(selected.instanceId)?.last) ?? runs[0]\r\n\r\n return (\r\n <Box sx={{ display: 'grid', gridTemplateColumns: '360px 1fr', height: '100%', minHeight: 0 }}>\r\n <Box\r\n sx={{\r\n borderRight: 1,\r\n borderColor: 'divider',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n minHeight: 0\r\n }}\r\n >\r\n <Box\r\n sx={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 1,\r\n p: 1,\r\n borderBottom: 1,\r\n borderColor: 'divider'\r\n }}\r\n >\r\n <ToggleButtonGroup\r\n size=\"small\"\r\n exclusive\r\n value={view}\r\n onChange={(_, value) => value && setView(value)}\r\n >\r\n <ToggleButton value=\"active\">Ativas ({snapshot.instances.length})</ToggleButton>\r\n <ToggleButton value=\"history\">Histórico ({snapshot.history.length})</ToggleButton>\r\n </ToggleButtonGroup>\r\n {view === 'history' && (\r\n <Button size=\"small\" onClick={store.clearHistory}>\r\n Limpar\r\n </Button>\r\n )}\r\n <TextField\r\n select\r\n size=\"small\"\r\n value={sort}\r\n onChange={(e) => changeSort(e.target.value as SortKey)}\r\n title=\"Ordenar a lista\"\r\n sx={{ ml: 'auto', minWidth: 0, '& .MuiSelect-select': { fontSize: 12, py: 0.5 } }}\r\n >\r\n {(Object.keys(SORT_LABEL) as SortKey[]).map((key) => (\r\n <MenuItem key={key} value={key} dense>\r\n {key === 'default' && view === 'history' ? 'mais recentes' : SORT_LABEL[key]}\r\n </MenuItem>\r\n ))}\r\n </TextField>\r\n </Box>\r\n <Box sx={{ display: 'flex', gap: 0.5, p: 1, borderBottom: 1, borderColor: 'divider' }}>\r\n <Button size=\"small\" variant=\"outlined\" onClick={refresh}>\r\n Re-executar tudo\r\n </Button>\r\n <Button\r\n size=\"small\"\r\n onClick={onClearServerCache}\r\n title=\"Esvazia o cache em memória do endpoint e refaz as consultas\"\r\n >\r\n Limpar cache\r\n </Button>\r\n </Box>\r\n {!!storms.length && (\r\n <Alert\r\n severity=\"warning\"\r\n sx={{ m: 1, py: 0 }}\r\n action={\r\n <Button size=\"small\" color=\"inherit\" onClick={store.resetStorms}>\r\n OK\r\n </Button>\r\n }\r\n >\r\n Consulta em loop: {storms.map((item) => item.label).join(', ')}. Algum componente está\r\n recriando dimensions/measures/filtros a cada render.\r\n </Alert>\r\n )}\r\n <List\r\n dense\r\n disablePadding\r\n sx={{ overflow: 'auto', flex: 1 }}\r\n onMouseLeave={() => onHover(null)}\r\n >\r\n {runs.map((run) => {\r\n const instance = instanceById.get(run.instanceId)\r\n const duplicated = view === 'active' && (sameQuery.get(queryKey(run)) ?? 0) > 1\r\n return (\r\n <ListItemButton\r\n key={run.runId}\r\n selected={current?.runId === run.runId}\r\n onClick={() => onSelect({ instanceId: run.instanceId, runId: run.runId })}\r\n onMouseEnter={() => onHover(instance ? run.instanceId : null)}\r\n sx={{ gap: 1, alignItems: 'center' }}\r\n >\r\n <StatusDot status={run.status} />\r\n <Box sx={{ minWidth: 0, flex: 1 }}>\r\n <Typography noWrap sx={{ fontSize: 12, fontFamily: MONO }}>\r\n {run.label}\r\n </Typography>\r\n <Typography noWrap sx={{ fontSize: 11, color: 'text.secondary' }}>\r\n {run.status === 'loading' ? 'carregando…' : `${run.durationMs} ms`}\r\n {run.rows && ` · ${run.rows.length} linhas`}\r\n {run.debug?.cached && ' · cache'}\r\n {run.batched && ` · lote de ${run.batched}`}\r\n {view === 'active' && ` · ${instance?.runs ?? 1}×`}\r\n </Typography>\r\n </Box>\r\n {instance?.storm && view === 'active' && (\r\n <Chip label=\"loop\" size=\"small\" color=\"error\" />\r\n )}\r\n {duplicated && (\r\n <Tooltip title=\"Outro componente faz exatamente a mesma consulta\">\r\n <Chip label=\"duplicada\" size=\"small\" variant=\"outlined\" />\r\n </Tooltip>\r\n )}\r\n {run.debug?.draft && <Chip label=\"rascunho\" size=\"small\" color=\"warning\" />}\r\n </ListItemButton>\r\n )\r\n })}\r\n {!runs.length && <Empty>Nenhuma consulta.</Empty>}\r\n </List>\r\n </Box>\r\n\r\n <Box sx={{ overflow: 'auto', p: 1.5, minWidth: 0 }}>\r\n {current ? (\r\n <RunDetail\r\n key={current.runId}\r\n run={current}\r\n devtools={devtools}\r\n capabilities={capabilities}\r\n mounted={instanceById.has(current.instanceId)}\r\n />\r\n ) : (\r\n <Empty>Selecione uma consulta.</Empty>\r\n )}\r\n </Box>\r\n </Box>\r\n )\r\n}\r\n\r\nfunction RunDetail({\r\n run,\r\n devtools,\r\n capabilities,\r\n mounted\r\n}: {\r\n run: QueryRun\r\n devtools: DashboardDevtoolsContext\r\n capabilities: DevtoolsCapabilities | null\r\n mounted: boolean\r\n}) {\r\n const { debug } = run\r\n const { devtools: _, ...query } = run.query\r\n return (\r\n <>\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, mb: 1.5, flexWrap: 'wrap' }}>\r\n <StatusDot status={run.status} />\r\n <Typography sx={{ fontFamily: MONO, fontWeight: 700 }}>{run.label}</Typography>\r\n <Chip size=\"small\" label={STATUS_LABEL[run.status]} />\r\n {run.durationMs !== undefined && (\r\n <Chip size=\"small\" label={`total ${run.durationMs} ms`} title=\"Ida e volta no browser\" />\r\n )}\r\n {debug && (\r\n <Chip\r\n size=\"small\"\r\n color={debug.cached ? 'info' : 'default'}\r\n label={\r\n debug.cached\r\n ? `cache (banco: ${debug.durationMs} ms)`\r\n : `banco ${debug.durationMs} ms`\r\n }\r\n />\r\n )}\r\n {debug?.draft && <Chip size=\"small\" color=\"warning\" label=\"rodou no rascunho\" />}\r\n {run.batched && (\r\n <Chip\r\n size=\"small\"\r\n label={`lote de ${run.batched}`}\r\n title=\"Saiu da mesma SQL que outras consultas (mesmas dimensões, filtros e fatos): o SQL e o tempo são os do conjunto\"\r\n />\r\n )}\r\n {mounted && (\r\n <Button size=\"small\" onClick={() => scrollToQuery(run.instanceId)}>\r\n Localizar na página\r\n </Button>\r\n )}\r\n <Typography sx={{ ml: 'auto', fontSize: 11, color: 'text.secondary' }}>\r\n {new Date(run.startedAt).toLocaleTimeString('pt-BR')}\r\n </Typography>\r\n </Box>\r\n\r\n {run.error && (\r\n <Alert severity=\"error\" sx={{ mb: 2, fontFamily: MONO, fontSize: 12 }}>\r\n {run.error}\r\n </Alert>\r\n )}\r\n {run.status === 'error' && !debug && <FailedSql run={run} />}\r\n\r\n <Section title=\"Consulta\">\r\n <CodeBlock code={JSON.stringify(query, null, 2)} maxHeight={180} />\r\n </Section>\r\n\r\n {debug && (\r\n <Section title=\"SQL gerado\">\r\n <CodeBlock sql code={inlineParams(debug.sql, debug.params)} />\r\n {!!debug.params.length && (\r\n <Typography sx={{ fontSize: 11, color: 'text.secondary', mt: 0.5, fontFamily: MONO }}>\r\n params: {JSON.stringify(debug.params)}\r\n </Typography>\r\n )}\r\n </Section>\r\n )}\r\n {!debug && run.status === 'success' && (\r\n <Alert severity=\"info\" sx={{ mb: 2 }}>\r\n O servidor não devolveu debug. Confira se o endpoint chama{' '}\r\n <code>runQuery(..., {'{ devtools: true }'})</code> em desenvolvimento.\r\n </Alert>\r\n )}\r\n\r\n {debug && <RunTools run={run} devtools={devtools} capabilities={capabilities} />}\r\n\r\n {run.rows && (\r\n <Section title={`Resultado (${run.rows.length} linhas)`}>\r\n <ResultTable rows={run.rows} />\r\n </Section>\r\n )}\r\n </>\r\n )\r\n}\r\n\r\n/**\r\n * SQL de uma consulta que deu erro: o servidor não devolve debug junto com o erro, então pede só a\r\n * compilação (`devtools.compile`), sem executar. Se nem compilar, mostra por quê.\r\n */\r\nfunction FailedSql({ run }: { run: QueryRun }) {\r\n const { fetcher } = useDashboard()\r\n const [state, setState] = useState<ToolState<DashboardQueryDebug> | null>(null)\r\n useEffect(() => {\r\n let active = true\r\n setState({ loading: true })\r\n fetcher({ ...run.query, devtools: { compile: true } })\r\n .then((result) => {\r\n const debug = result.devtools?.debug\r\n if (active)\r\n setState(\r\n debug\r\n ? { loading: false, data: debug }\r\n : {\r\n loading: false,\r\n error:\r\n 'O endpoint não devolveu o SQL (precisa de runQuery(..., { devtools: true }) numa versão que aceite devtools.compile).'\r\n }\r\n )\r\n })\r\n .catch((error) => active && setState({ loading: false, error: errorMessage(error) }))\r\n return () => {\r\n active = false\r\n }\r\n }, [fetcher, run.query])\r\n\r\n return (\r\n <Section title=\"SQL gerado (não executou)\">\r\n <ToolResult state={state}>\r\n {(debug) => (\r\n <>\r\n <CodeBlock sql code={inlineParams(debug.sql, debug.params)} />\r\n <Typography sx={{ fontSize: 11, color: 'text.secondary', mt: 0.5 }}>\r\n Compilado de novo agora{debug.draft ? ', com o rascunho atual' : ''}, para depurar o\r\n erro acima.\r\n {!!debug.params.length && (\r\n <Box component=\"span\" sx={{ fontFamily: MONO }}>\r\n {' '}\r\n params: {JSON.stringify(debug.params)}\r\n </Box>\r\n )}\r\n </Typography>\r\n </>\r\n )}\r\n </ToolResult>\r\n </Section>\r\n )\r\n}\r\n\r\ntype ToolState<T> = { loading: boolean; error?: string; data?: T }\r\n\r\nfunction useTool<T>() {\r\n const [state, setState] = useState<ToolState<T> | null>(null)\r\n const run = async (load: () => Promise<T>) => {\r\n setState({ loading: true })\r\n try {\r\n setState({ loading: false, data: await load() })\r\n } catch (error) {\r\n setState({ loading: false, error: errorMessage(error) })\r\n }\r\n }\r\n return [state, run] as const\r\n}\r\n\r\nfunction ToolResult<T>({\r\n state,\r\n children\r\n}: {\r\n state: ToolState<T> | null\r\n children: (data: T) => ReactNode\r\n}) {\r\n if (!state) return null\r\n if (state.loading) return <Typography sx={{ fontSize: 12 }}>Executando…</Typography>\r\n if (state.error)\r\n return (\r\n <Alert severity=\"error\" sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {state.error}\r\n </Alert>\r\n )\r\n return state.data === undefined ? null : children(state.data)\r\n}\r\n\r\n/** EXPLAIN, perfil por join, comparação com o modelo registrado e snapshot da consulta. */\r\nfunction RunTools({\r\n run,\r\n devtools,\r\n capabilities\r\n}: {\r\n run: QueryRun\r\n devtools: DashboardDevtoolsContext\r\n capabilities: DevtoolsCapabilities | null\r\n}) {\r\n const { fetcher } = useDashboard()\r\n const query = run.query\r\n const [explain, runExplain] = useTool<DashboardRow[]>()\r\n const [profile, runProfile] = useTool<ProfileStep[]>()\r\n const [compare, runCompare] = useTool<RowDiff[]>()\r\n const [snapshot, runSnapshot] = useTool<string>()\r\n const [snapshotName, setSnapshotName] = useState('')\r\n const [overwrite, setOverwrite] = useState(false)\r\n\r\n const explainQuery = () =>\r\n runExplain(async () => {\r\n const result = await fetcher({ ...query, devtools: { explain: true } })\r\n return result.devtools?.explain ?? []\r\n })\r\n const profileQuery = () =>\r\n runProfile(async () => {\r\n const result = await fetcher({ ...query, devtools: { profile: true } })\r\n return result.devtools?.profile ?? []\r\n })\r\n const compareQuery = () =>\r\n runCompare(async () => {\r\n const registered = await devtools.rawFetcher(query)\r\n return diffRows(registered.rows, run.rows ?? [], query)\r\n })\r\n const saveSnapshot = () =>\r\n runSnapshot(async () => {\r\n const result = await devtools.rawFetcher({\r\n ...query,\r\n devtools: { snapshot: { name: snapshotName, overwrite } }\r\n })\r\n return result.devtools?.snapshot?.path ?? ''\r\n })\r\n\r\n const maxProfile = Math.max(1, ...(profile?.data ?? []).map((step) => step.durationMs))\r\n\r\n return (\r\n <Section\r\n title=\"Ferramentas\"\r\n actions={\r\n <>\r\n <Button size=\"small\" variant=\"outlined\" onClick={explainQuery}>\r\n EXPLAIN\r\n </Button>\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n onClick={profileQuery}\r\n title=\"Mede a agregação de cada fato isoladamente (sem cache)\"\r\n >\r\n Perfil por join\r\n </Button>\r\n {devtools.draft && run.rows && (\r\n <Button size=\"small\" variant=\"outlined\" color=\"warning\" onClick={compareQuery}>\r\n Comparar com o registrado\r\n </Button>\r\n )}\r\n </>\r\n }\r\n >\r\n <Box sx={{ display: 'flex', flexDirection: 'column', gap: 1.5 }}>\r\n <ToolResult state={explain}>\r\n {(rows) => <ResultTable rows={rows} maxHeight={240} />}\r\n </ToolResult>\r\n\r\n <ToolResult state={profile}>\r\n {(steps) => (\r\n <Box sx={{ display: 'grid', gridTemplateColumns: '160px 1fr 90px 90px', gap: 0.5 }}>\r\n {steps.map((step) => (\r\n <Box key={step.name} sx={{ display: 'contents', fontFamily: MONO, fontSize: 12 }}>\r\n <Box sx={{ fontFamily: MONO }}>{step.name}</Box>\r\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\r\n <Box\r\n sx={{\r\n height: 10,\r\n borderRadius: 1,\r\n width: `${(step.durationMs / maxProfile) * 100}%`,\r\n minWidth: 2,\r\n bgcolor: step.name === 'consulta' ? 'primary.main' : 'info.main'\r\n }}\r\n />\r\n </Box>\r\n <Box sx={{ textAlign: 'right', fontFamily: MONO }}>{step.durationMs} ms</Box>\r\n <Box sx={{ textAlign: 'right', fontFamily: MONO, color: 'text.secondary' }}>\r\n {step.rows ?? ''} {step.name === 'consulta' ? 'linhas' : 'chaves'}\r\n </Box>\r\n </Box>\r\n ))}\r\n </Box>\r\n )}\r\n </ToolResult>\r\n\r\n <ToolResult state={compare}>\r\n {(diffs) => (\r\n <RowDiffTable diffs={diffs} expectedLabel=\"registrado\" actualLabel=\"rascunho\" />\r\n )}\r\n </ToolResult>\r\n\r\n {capabilities?.snapshots && (\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 1, flexWrap: 'wrap' }}>\r\n <TextField\r\n size=\"small\"\r\n label=\"Nome do snapshot\"\r\n placeholder=\"custo-mes-2024\"\r\n value={snapshotName}\r\n onChange={(e) => setSnapshotName(e.target.value)}\r\n sx={{ width: 240, '& input': { fontFamily: MONO, fontSize: 12 } }}\r\n />\r\n <FormControlLabel\r\n control={\r\n <Checkbox\r\n size=\"small\"\r\n checked={overwrite}\r\n onChange={(e) => setOverwrite(e.target.checked)}\r\n />\r\n }\r\n label=\"Sobrescrever\"\r\n />\r\n <Tooltip title=\"Grava o resultado do modelo REGISTRADO (não o rascunho) como referência para os testes de regressão. Prefira períodos fechados: dado que ainda muda quebra o teste.\">\r\n <span>\r\n <Button\r\n size=\"small\"\r\n variant=\"outlined\"\r\n disabled={!snapshotName}\r\n onClick={saveSnapshot}\r\n >\r\n Salvar snapshot\r\n </Button>\r\n </span>\r\n </Tooltip>\r\n <ToolResult state={snapshot}>\r\n {(path) => (\r\n <Typography sx={{ fontSize: 12, color: 'success.main', fontFamily: MONO }}>\r\n Salvo em {path}\r\n </Typography>\r\n )}\r\n </ToolResult>\r\n </Box>\r\n )}\r\n </Box>\r\n </Section>\r\n )\r\n}\r\n","import { Alert, Box, Button, Chip, Collapse, Typography } from '@mui/material'\r\nimport { useEffect, useState } from 'react'\r\nimport type { DashboardDevtoolsContext } from '../client/DashboardProvider'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport { diffRows, type RowDiff } from '../compare'\r\nimport type { DashboardQuery, DashboardSnapshot, DevtoolsCapabilities } from '../types'\r\nimport { errorMessage } from './store'\r\nimport { Empty, MONO, RowDiffTable, Section } from './ui'\r\n\r\ntype CheckItem = { id: string; label: string; query: DashboardQuery }\r\n\r\ntype Check = {\r\n id: string\r\n label: string\r\n query: DashboardQuery\r\n status: 'loading' | 'done' | 'error'\r\n diffs?: RowDiff[]\r\n rows?: number\r\n error?: string\r\n}\r\n\r\ntype Props = {\r\n devtools: DashboardDevtoolsContext\r\n capabilities: DevtoolsCapabilities | null\r\n}\r\n\r\nconst stripQuery = ({ model, dimensions, measures, filters }: DashboardQuery): DashboardQuery => ({\r\n model,\r\n dimensions,\r\n measures,\r\n filters\r\n})\r\n\r\n/** Executa as conferências uma a uma, atualizando a lista conforme terminam. */\r\nfunction useChecks() {\r\n const [checks, setChecks] = useState<Check[]>([])\r\n const run = async (\r\n items: CheckItem[],\r\n compare: (item: CheckItem) => Promise<{ diffs: RowDiff[]; rows: number }>\r\n ) => {\r\n setChecks(items.map((item) => ({ ...item, status: 'loading' })))\r\n for (const item of items) {\r\n let patch: Partial<Check>\r\n try {\r\n patch = { status: 'done', ...(await compare(item)) }\r\n } catch (error) {\r\n patch = { status: 'error', error: errorMessage(error) }\r\n }\r\n setChecks((current) =>\r\n current.map((check) => (check.id === item.id ? { ...check, ...patch } : check))\r\n )\r\n }\r\n }\r\n return [checks, run] as const\r\n}\r\n\r\n/**\r\n * Proteção dos números: (1) rascunho x modelo registrado em todas as consultas da página e\r\n * (2) snapshots salvos x modelo em vigor (o mesmo que o teste `tests/dashboard` faz no CI).\r\n */\r\nexport function RegressionPanel({ devtools, capabilities }: Props) {\r\n const { fetcher, model } = useDashboard()\r\n const [pageChecks, runPageChecks] = useChecks()\r\n const [snapshotChecks, runSnapshotChecks] = useChecks()\r\n const [snapshots, setSnapshots] = useState<DashboardSnapshot[] | null>(null)\r\n const [snapshotsError, setSnapshotsError] = useState<string | null>(null)\r\n\r\n const loadSnapshots = () =>\r\n devtools\r\n .rawFetcher({ model, devtools: { snapshots: true } })\r\n .then((result) => {\r\n setSnapshots(result.devtools?.snapshots ?? [])\r\n setSnapshotsError(null)\r\n })\r\n .catch((error) => setSnapshotsError(errorMessage(error)))\r\n\r\n useEffect(() => {\r\n if (capabilities?.snapshots) loadSnapshots()\r\n }, [capabilities?.snapshots])\r\n\r\n const comparePage = () => {\r\n // Uma conferência por consulta distinta (componentes com a mesma consulta contam uma vez)\r\n const unique = new Map<string, CheckItem>()\r\n for (const { last, label } of devtools.store.getSnapshot().instances) {\r\n const query = stripQuery(last.query)\r\n const id = JSON.stringify(query)\r\n if (!unique.has(id)) unique.set(id, { id, label, query })\r\n }\r\n runPageChecks([...unique.values()], async ({ query }) => {\r\n const [registered, draft] = await Promise.all([devtools.rawFetcher(query), fetcher(query)])\r\n return { diffs: diffRows(registered.rows, draft.rows, query), rows: draft.rows.length }\r\n })\r\n }\r\n\r\n const verifySnapshots = () => {\r\n const byName = new Map((snapshots ?? []).map((snapshot) => [snapshot.name, snapshot]))\r\n runSnapshotChecks(\r\n [...byName.values()].map((snapshot) => ({\r\n id: snapshot.name,\r\n label: snapshot.name,\r\n query: snapshot.query as DashboardQuery\r\n })),\r\n async ({ id, query }) => {\r\n const result = await fetcher(query)\r\n const expected = byName.get(id)?.rows ?? []\r\n return { diffs: diffRows(expected, result.rows, query), rows: result.rows.length }\r\n }\r\n )\r\n }\r\n\r\n return (\r\n <Box sx={{ p: 1.5, overflow: 'auto', height: '100%' }}>\r\n <Section\r\n title=\"Rascunho × modelo registrado\"\r\n actions={\r\n <Button size=\"small\" variant=\"contained\" disabled={!devtools.draft} onClick={comparePage}>\r\n Comparar consultas da página\r\n </Button>\r\n }\r\n >\r\n {!devtools.draft ? (\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary' }}>\r\n Aplique um rascunho na aba Modelo para comparar: cada consulta da página roda nos dois\r\n modelos e as linhas são casadas pelas dimensões.\r\n </Typography>\r\n ) : (\r\n <CheckList checks={pageChecks} expectedLabel=\"registrado\" actualLabel=\"rascunho\" />\r\n )}\r\n </Section>\r\n\r\n <Section\r\n title=\"Snapshots de regressão\"\r\n actions={\r\n capabilities?.snapshots && (\r\n <>\r\n <Button size=\"small\" onClick={loadSnapshots}>\r\n Recarregar\r\n </Button>\r\n <Button\r\n size=\"small\"\r\n variant=\"contained\"\r\n disabled={!snapshots?.length}\r\n onClick={verifySnapshots}\r\n >\r\n Verificar todos {devtools.draft ? '(no rascunho)' : ''}\r\n </Button>\r\n </>\r\n )\r\n }\r\n >\r\n {!capabilities?.snapshots ? (\r\n <Alert severity=\"info\">\r\n O endpoint não configurou <code>snapshotsDir</code> no <code>runQuery</code>.\r\n </Alert>\r\n ) : snapshotsError ? (\r\n <Alert severity=\"error\">{snapshotsError}</Alert>\r\n ) : !snapshots ? (\r\n <Typography sx={{ fontSize: 12 }}>Carregando…</Typography>\r\n ) : !snapshots.length ? (\r\n <Empty>\r\n Nenhum snapshot. Salve um pela aba Consultas → Ferramentas → \"Salvar snapshot\".\r\n </Empty>\r\n ) : (\r\n <>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary', mb: 1 }}>\r\n {snapshots.length} snapshot(s). Os mesmos rodam nos testes do app (\r\n <code>tests/dashboard</code>).\r\n </Typography>\r\n {snapshotChecks.length ? (\r\n <CheckList checks={snapshotChecks} expectedLabel=\"snapshot\" actualLabel=\"agora\" />\r\n ) : (\r\n <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap' }}>\r\n {snapshots.map((snapshot) => (\r\n <Chip\r\n key={snapshot.name}\r\n size=\"small\"\r\n label={`${snapshot.name} · ${snapshot.rows.length} linhas`}\r\n title={`${JSON.stringify(snapshot.query)}\\n${snapshot.createdAt}`}\r\n sx={{ fontFamily: MONO }}\r\n />\r\n ))}\r\n </Box>\r\n )}\r\n </>\r\n )}\r\n </Section>\r\n </Box>\r\n )\r\n}\r\n\r\nfunction CheckList({\r\n checks,\r\n expectedLabel,\r\n actualLabel\r\n}: {\r\n checks: Check[]\r\n expectedLabel: string\r\n actualLabel: string\r\n}) {\r\n const [open, setOpen] = useState<string | null>(null)\r\n if (!checks.length) return null\r\n const failed = checks.filter((check) => check.status === 'error' || check.diffs?.length).length\r\n const done = checks.every((check) => check.status !== 'loading')\r\n return (\r\n <Box>\r\n {done && (\r\n <Alert severity={failed ? 'warning' : 'success'} sx={{ mb: 1 }}>\r\n {failed ? `${failed} de ${checks.length} com diferença ou erro.` : 'Tudo igual.'}\r\n </Alert>\r\n )}\r\n {checks.map((check) => {\r\n const differs = !!check.diffs?.length\r\n return (\r\n <Box key={check.id} sx={{ borderBottom: 1, borderColor: 'divider', py: 0.5 }}>\r\n <Box\r\n sx={{ display: 'flex', alignItems: 'center', gap: 1, cursor: 'pointer' }}\r\n onClick={() => setOpen(open === check.id ? null : check.id)}\r\n >\r\n <Typography sx={{ fontFamily: MONO, fontSize: 12, flex: 1 }} noWrap>\r\n {check.label}\r\n </Typography>\r\n {check.status === 'loading' && <Chip size=\"small\" label=\"executando…\" />}\r\n {check.status === 'error' && <Chip size=\"small\" color=\"error\" label=\"erro\" />}\r\n {check.status === 'done' && (\r\n <Chip\r\n size=\"small\"\r\n color={differs ? 'warning' : 'success'}\r\n label={\r\n differs\r\n ? `${check.diffs?.length} linha(s) diferente(s)`\r\n : `igual · ${check.rows} linhas`\r\n }\r\n />\r\n )}\r\n </Box>\r\n <Collapse in={open === check.id}>\r\n <Box sx={{ pt: 1 }}>\r\n {check.error && (\r\n <Alert severity=\"error\" sx={{ fontFamily: MONO, fontSize: 12 }}>\r\n {check.error}\r\n </Alert>\r\n )}\r\n {check.diffs && (\r\n <RowDiffTable\r\n diffs={check.diffs}\r\n expectedLabel={expectedLabel}\r\n actualLabel={actualLabel}\r\n />\r\n )}\r\n </Box>\r\n </Collapse>\r\n </Box>\r\n )\r\n })}\r\n </Box>\r\n )\r\n}\r\n","import {\r\n Alert,\r\n Box,\r\n Chip,\r\n CircularProgress,\r\n createTheme,\r\n IconButton,\r\n Paper,\r\n Portal,\r\n Tab,\r\n Tabs,\r\n ThemeProvider,\r\n Tooltip,\r\n Typography\r\n} from '@mui/material'\r\nimport {\r\n type MouseEvent as ReactMouseEvent,\r\n type ReactNode,\r\n useCallback,\r\n useEffect,\r\n useRef,\r\n useState,\r\n useSyncExternalStore\r\n} from 'react'\r\nimport { useDashboard } from '../client/DashboardProvider'\r\nimport { ModelDictionary } from '../client/ModelDictionary'\r\nimport type { ModelDef } from '../model'\r\nimport type { DevtoolsCapabilities, SchemaTable } from '../types'\r\nimport { FiltersPanel } from './FiltersPanel'\r\nimport { DevtoolsWindow, openDevtoolsWindow } from './DevtoolsWindow'\r\nimport { DEVTOOLS_ATTRIBUTE, findQueryElement, HighlightOverlay, useInspectMode } from './Inspector'\r\nimport { LayoutPanel } from './LayoutPanel'\r\nimport { LAYOUT_ITEM_ATTRIBUTE } from './layoutStore'\r\nimport { ModelPanel } from './ModelPanel'\r\nimport { PlaygroundPanel, type PlaygroundSelection } from './PlaygroundPanel'\r\nimport { QueriesPanel, type QuerySelection } from './QueriesPanel'\r\nimport { RegressionPanel } from './RegressionPanel'\r\nimport { errorMessage } from './store'\r\nimport { MONO } from './ui'\r\n\r\n/**\r\n * Devtools do `@bluemarble/bi` (no estilo do TanStack Query Devtools): um botão flutuante que abre um\r\n * painel com as consultas da página, o modelo editável, um playground, regressão, dicionário e\r\n * filtros. Montado pelo próprio `DashboardProvider` em desenvolvimento.\r\n *\r\n * Modos: fixado (embaixo, à esquerda ou à direita), flutuante (janela que se arrasta pelo cabeçalho\r\n * e redimensiona pelo canto) ou numa janela separada do navegador (`DevtoolsWindow`). Fixado, o\r\n * painel ocupa espaço: a página encolhe para não ficar escondida atrás dele; só o modo flutuante\r\n * sobrepõe a página.\r\n * Atalhos: Alt+Shift+B abre/fecha o painel, Alt+Shift+F alterna entre fixado e flutuante,\r\n * Alt+Shift+I liga o inspetor, Esc sai do inspetor.\r\n */\r\n\r\n// Abaixo do Modal do MUI (1300) para os menus dos Selects do painel abrirem por cima dele\r\nconst Z_INDEX = 1250\r\nconst MIN_HEIGHT = 180\r\nconst MIN_SIDE_WIDTH = 360\r\nconst MIN_FLOAT_WIDTH = 420\r\nconst MIN_FLOAT_HEIGHT = 220\r\nconst FLOAT_MARGIN = 16\r\n\r\nconst theme = createTheme({\r\n palette: { mode: 'dark', primary: { main: '#F58220' }, background: { paper: '#1b1e23' } },\r\n typography: { fontSize: 12 },\r\n components: {\r\n MuiTableCell: { styleOverrides: { root: { fontSize: 12, padding: '4px 8px' } } },\r\n MuiButton: {\r\n defaultProps: { disableElevation: true },\r\n styleOverrides: { root: { textTransform: 'none' } }\r\n },\r\n MuiTab: { styleOverrides: { root: { textTransform: 'none', minHeight: 40 } } }\r\n }\r\n})\r\n\r\ntype TabKey =\r\n | 'queries'\r\n | 'model'\r\n | 'layout'\r\n | 'playground'\r\n | 'regression'\r\n | 'dictionary'\r\n | 'filters'\r\n\r\nconst STORAGE_KEY = 'bm-dashboard-devtools:ui'\r\n\r\ntype DockSide = 'bottom' | 'left' | 'right'\r\n\r\nconst DOCK_SIDES: { side: DockSide; icon: string; label: string }[] = [\r\n { side: 'left', icon: '◧', label: 'Fixar à esquerda' },\r\n { side: 'bottom', icon: '⬓', label: 'Fixar embaixo' },\r\n { side: 'right', icon: '◨', label: 'Fixar à direita' }\r\n]\r\n\r\ntype FloatRect = { x: number; y: number; width: number; height: number }\r\n\r\ntype UiState = {\r\n open: boolean\r\n /**\r\n * Fixado numa borda (ocupa espaço na página), `floating` (janela solta, por cima) ou `window`\r\n * (janela separada do navegador).\r\n */\r\n mode: DockSide | 'floating' | 'window'\r\n /** Última borda usada: para onde volta ao sair do flutuante. */\r\n dock: DockSide\r\n /** Altura fixado embaixo. */\r\n height: number\r\n /** Largura fixado na lateral. */\r\n width: number\r\n /** Posição e tamanho no modo flutuante. */\r\n float: FloatRect\r\n tab: TabKey\r\n}\r\n\r\n/** Mantém a janela flutuante inteira dentro da tela (encolhe se a tela ficou menor). */\r\nfunction clampFloat(rect: FloatRect): FloatRect {\r\n const maxWidth = Math.max(MIN_FLOAT_WIDTH, window.innerWidth - FLOAT_MARGIN * 2)\r\n const maxHeight = Math.max(MIN_FLOAT_HEIGHT, window.innerHeight - FLOAT_MARGIN * 2)\r\n const width = Math.min(Math.max(rect.width, MIN_FLOAT_WIDTH), maxWidth)\r\n const height = Math.min(Math.max(rect.height, MIN_FLOAT_HEIGHT), maxHeight)\r\n return {\r\n width,\r\n height,\r\n x: Math.min(Math.max(rect.x, 0), Math.max(0, window.innerWidth - width)),\r\n y: Math.min(Math.max(rect.y, 0), Math.max(0, window.innerHeight - height))\r\n }\r\n}\r\n\r\nfunction loadUi(): UiState {\r\n const width = Math.min(960, window.innerWidth - FLOAT_MARGIN * 2)\r\n const height = Math.min(560, window.innerHeight - FLOAT_MARGIN * 2)\r\n const fallback: UiState = {\r\n open: false,\r\n mode: 'bottom',\r\n dock: 'bottom',\r\n width: 520,\r\n height: 380,\r\n // Canto inferior direito, longe do botão (que fica à esquerda)\r\n float: {\r\n width,\r\n height,\r\n x: window.innerWidth - width - FLOAT_MARGIN,\r\n y: window.innerHeight - height - FLOAT_MARGIN\r\n },\r\n tab: 'queries'\r\n }\r\n try {\r\n const saved: UiState = {\r\n ...fallback,\r\n ...JSON.parse(localStorage.getItem(STORAGE_KEY) ?? '{}')\r\n }\r\n // Versão anterior gravava `docked` (só existia embaixo)\r\n if (!['bottom', 'left', 'right', 'floating', 'window'].includes(saved.mode))\r\n saved.mode = 'bottom'\r\n if (!['bottom', 'left', 'right'].includes(saved.dock)) saved.dock = 'bottom'\r\n // Popup só abre com um clique (o navegador bloqueia sem gesto): começa fechado\r\n if (saved.mode === 'window') saved.open = false\r\n return { ...saved, float: clampFloat({ ...fallback.float, ...saved.float }) }\r\n } catch {\r\n return fallback\r\n }\r\n}\r\n\r\n/**\r\n * Encolhe a página para o painel fixado caber ao lado dela. A raiz do Next (`#__next`) vira uma caixa\r\n * do tamanho da tela menos o painel, com rolagem própria; o `transform` faz os elementos `fixed` do\r\n * app (sidebar, appbar) ficarem dentro dessa caixa em vez de presos à janela — só um padding no\r\n * `body` deixaria eles atrás do painel. Sem `#__next` (App Router), cai no padding do `body`.\r\n */\r\nfunction reservePageSpace(side: DockSide, initialSize: number) {\r\n const root = document.getElementById('__next')\r\n if (!root) {\r\n const property = (\r\n { bottom: 'paddingBottom', left: 'paddingLeft', right: 'paddingRight' } as const\r\n )[side]\r\n const previous = document.body.style[property]\r\n const resize = (size: number) => {\r\n document.body.style[property] = `${size}px`\r\n }\r\n resize(initialSize)\r\n return {\r\n resize,\r\n release: () => {\r\n document.body.style[property] = previous\r\n }\r\n }\r\n }\r\n const previous = root.getAttribute('style')\r\n const scroll = { x: window.scrollX, y: window.scrollY }\r\n Object.assign(root.style, {\r\n position: 'fixed',\r\n inset: '0',\r\n overflow: 'auto',\r\n transform: 'translateZ(0)'\r\n })\r\n const resize = (size: number) => {\r\n root.style[side] = `${size}px`\r\n }\r\n resize(initialSize)\r\n // A rolagem passa da janela para a caixa: mantém onde a pessoa estava\r\n root.scrollTo(scroll.x, scroll.y)\r\n return {\r\n resize,\r\n release: () => {\r\n const inner = { x: root.scrollLeft, y: root.scrollTop }\r\n if (previous === null) root.removeAttribute('style')\r\n else root.setAttribute('style', previous)\r\n window.scrollTo(inner.x, inner.y)\r\n }\r\n }\r\n}\r\n\r\n/** Acompanha o mouse até soltar o botão, sem selecionar texto da página no caminho. */\r\nfunction trackMouse(event: ReactMouseEvent, onMove: (dx: number, dy: number) => void) {\r\n event.preventDefault()\r\n const startX = event.clientX\r\n const startY = event.clientY\r\n const previousSelect = document.body.style.userSelect\r\n document.body.style.userSelect = 'none'\r\n const move = (moveEvent: MouseEvent) =>\r\n onMove(moveEvent.clientX - startX, moveEvent.clientY - startY)\r\n const up = () => {\r\n document.body.style.userSelect = previousSelect\r\n window.removeEventListener('mousemove', move)\r\n window.removeEventListener('mouseup', up)\r\n }\r\n window.addEventListener('mousemove', move)\r\n window.addEventListener('mouseup', up)\r\n}\r\n\r\nconst devtoolsMarker = { [DEVTOOLS_ATTRIBUTE]: '' }\r\n\r\nexport default function DashboardDevtools() {\r\n const { model, fetcher, devtools } = useDashboard()\r\n const [ui, setUi] = useState(loadUi)\r\n const [original, setOriginal] = useState<ModelDef | null>(null)\r\n const [capabilities, setCapabilities] = useState<DevtoolsCapabilities | null>(null)\r\n const [describeError, setDescribeError] = useState<string | null>(null)\r\n const [tables, setTables] = useState<SchemaTable[] | null>(null)\r\n const [playground, setPlayground] = useState<PlaygroundSelection>({\r\n dimensions: [],\r\n measures: []\r\n })\r\n const [selected, setSelected] = useState<QuerySelection | null>(null)\r\n const [pickedItem, setPickedItem] = useState<{ item: string } | null>(null)\r\n const [hovered, setHovered] = useState<string | null>(null)\r\n const [inspecting, setInspecting] = useState(false)\r\n const [popup, setPopup] = useState<Window | null>(null)\r\n\r\n const store = devtools?.store\r\n const snapshot = useSyncExternalStore(\r\n store?.subscribe ?? (() => () => {}),\r\n () => store?.getSnapshot(),\r\n () => store?.getSnapshot()\r\n )\r\n const instances = snapshot?.instances ?? []\r\n\r\n useEffect(() => {\r\n try {\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(ui))\r\n } catch {}\r\n }, [ui])\r\n\r\n const loadModel = useCallback(\r\n (clearCache = false) =>\r\n fetcher({ model, devtools: { describe: true, clearCache } })\r\n .then((result) => {\r\n setOriginal(result.devtools?.model ?? null)\r\n setCapabilities(result.devtools?.capabilities ?? null)\r\n setDescribeError(result.devtools?.model ? null : 'O endpoint não devolveu o modelo.')\r\n })\r\n .catch((error) => setDescribeError(errorMessage(error))),\r\n [fetcher, model]\r\n )\r\n\r\n useEffect(() => {\r\n if (ui.open) loadModel()\r\n }, [ui.open, loadModel])\r\n\r\n // Schema do banco só quando alguém vai editar SQL\r\n useEffect(() => {\r\n if (!ui.open || ui.tab !== 'model' || tables) return\r\n fetcher({ model, devtools: { schema: true } })\r\n .then((result) => setTables(result.devtools?.schema ?? []))\r\n .catch(() => setTables([]))\r\n }, [ui.open, ui.tab, tables, fetcher, model])\r\n\r\n const setTab = (tab: TabKey) => setUi((current) => ({ ...current, open: true, tab }))\r\n\r\n // Na aba Layout, o inspetor escolhe o gráfico/filtro para editar; nas outras, a consulta\r\n const layoutTab = ui.tab === 'layout'\r\n const pick = useCallback(\r\n (instanceId: string) => {\r\n setInspecting(false)\r\n const item = findQueryElement(instanceId)\r\n ?.closest(`[${LAYOUT_ITEM_ATTRIBUTE}]`)\r\n ?.getAttribute(LAYOUT_ITEM_ATTRIBUTE)\r\n if (layoutTab && item) {\r\n setPickedItem({ item })\r\n return\r\n }\r\n setSelected({ instanceId })\r\n setUi((current) => ({ ...current, open: true, tab: 'queries' }))\r\n },\r\n [layoutTab]\r\n )\r\n useInspectMode({ active: inspecting, onHover: setHovered, onPick: pick })\r\n\r\n // Janela separada: abrir o popup precisa acontecer no clique/tecla (senão o navegador bloqueia)\r\n const closePopup = useCallback(() => {\r\n setPopup((current) => {\r\n if (current && !current.closed) current.close()\r\n return null\r\n })\r\n }, [])\r\n const openPanel = useCallback(() => {\r\n if (ui.mode !== 'window') {\r\n setUi((current) => ({ ...current, open: true }))\r\n return\r\n }\r\n const opened = popup && !popup.closed ? popup : openDevtoolsWindow()\r\n if (opened) {\r\n opened.focus()\r\n setPopup(opened)\r\n setUi((current) => ({ ...current, open: true }))\r\n } else {\r\n // Bloqueado: abre fixado na página\r\n setUi((current) => ({ ...current, open: true, mode: current.dock }))\r\n }\r\n }, [ui.mode, popup])\r\n const closePanel = useCallback(() => {\r\n closePopup()\r\n setUi((current) => ({ ...current, open: false }))\r\n }, [closePopup])\r\n const toWindow = () => {\r\n const opened = openDevtoolsWindow()\r\n if (!opened) return\r\n opened.focus()\r\n setPopup(opened)\r\n setUi((current) => ({ ...current, open: true, mode: 'window' }))\r\n }\r\n const onPopupClosed = useCallback(() => {\r\n setPopup(null)\r\n setUi((current) => ({ ...current, open: false }))\r\n }, [])\r\n\r\n const keyActions = useRef({ openPanel, closePanel, closePopup, open: ui.open, inspecting })\r\n keyActions.current = { openPanel, closePanel, closePopup, open: ui.open, inspecting }\r\n useEffect(() => {\r\n const onKey = (event: KeyboardEvent) => {\r\n const actions = keyActions.current\r\n if (event.key === 'Escape' && actions.inspecting) setInspecting(false)\r\n if (!event.altKey || !event.shiftKey) return\r\n if (event.code === 'KeyB') {\r\n event.preventDefault()\r\n if (actions.open) actions.closePanel()\r\n else actions.openPanel()\r\n } else if (event.code === 'KeyF') {\r\n event.preventDefault()\r\n actions.closePopup()\r\n setUi((current) => ({\r\n ...current,\r\n open: true,\r\n mode: current.mode === 'floating' ? current.dock : 'floating'\r\n }))\r\n } else if (event.code === 'KeyI') {\r\n event.preventDefault()\r\n setInspecting((value) => !value)\r\n }\r\n }\r\n // Com a janela separada em foco, os atalhos chegam nela\r\n const targets = popup && !popup.closed ? [window, popup] : [window]\r\n for (const target of targets) target.addEventListener('keydown', onKey)\r\n return () => {\r\n for (const target of targets) target.removeEventListener('keydown', onKey)\r\n }\r\n }, [popup])\r\n\r\n // Fixado, o painel ocupa espaço: a página encolhe em vez de ficar escondida atrás dele.\r\n // Flutuante, em janela separada ou fechado, a página volta ao normal.\r\n const reserved = ui.open && ui.mode !== 'floating' && ui.mode !== 'window' ? ui.mode : null\r\n const reservedSize = reserved === 'bottom' ? ui.height : ui.width\r\n const reservation = useRef<ReturnType<typeof reservePageSpace> | null>(null)\r\n const reservedSizeRef = useRef(reservedSize)\r\n reservedSizeRef.current = reservedSize\r\n useEffect(() => {\r\n if (!reserved) return\r\n const handle = reservePageSpace(reserved, reservedSizeRef.current)\r\n reservation.current = handle\r\n return () => {\r\n reservation.current = null\r\n handle.release()\r\n }\r\n }, [reserved])\r\n // Arrastar a borda só ajusta o tamanho, sem desfazer e refazer tudo\r\n useEffect(() => reservation.current?.resize(reservedSize), [reservedSize])\r\n\r\n // Tela redimensionada: a janela flutuante não pode ficar fora dela\r\n useEffect(() => {\r\n const onResize = () => setUi((current) => ({ ...current, float: clampFloat(current.float) }))\r\n window.addEventListener('resize', onResize)\r\n return () => window.removeEventListener('resize', onResize)\r\n }, [])\r\n\r\n if (!devtools || !store) return null\r\n\r\n const inWindow = ui.mode === 'window' && !!popup\r\n const floating = ui.mode === 'floating'\r\n const side = ui.mode === 'left' || ui.mode === 'right' ? ui.mode : null\r\n\r\n const startDockResize = (event: ReactMouseEvent) => {\r\n const { height, width } = ui\r\n trackMouse(event, (dx, dy) =>\r\n setUi((current) =>\r\n current.mode === 'bottom'\r\n ? {\r\n ...current,\r\n height: Math.min(Math.max(height - dy, MIN_HEIGHT), window.innerHeight - 40)\r\n }\r\n : {\r\n ...current,\r\n width: Math.min(\r\n Math.max(width + (current.mode === 'left' ? dx : -dx), MIN_SIDE_WIDTH),\r\n window.innerWidth - 80\r\n )\r\n }\r\n )\r\n )\r\n }\r\n\r\n const startFloatResize = (event: ReactMouseEvent) => {\r\n const start = ui.float\r\n trackMouse(event, (dx, dy) =>\r\n setUi((current) => ({\r\n ...current,\r\n float: clampFloat({ ...start, width: start.width + dx, height: start.height + dy })\r\n }))\r\n )\r\n }\r\n\r\n // Arrastar pelo cabeçalho; botões, abas e campos continuam clicáveis\r\n const startDrag = (event: ReactMouseEvent) => {\r\n if (!floating || event.button !== 0) return\r\n if ((event.target as Element).closest('button, [role=\"tab\"], input, a')) return\r\n const start = ui.float\r\n trackMouse(event, (dx, dy) =>\r\n setUi((current) => ({\r\n ...current,\r\n float: clampFloat({ ...start, x: start.x + dx, y: start.y + dy })\r\n }))\r\n )\r\n }\r\n\r\n const toggleMode = () => {\r\n closePopup()\r\n setUi((current) => ({\r\n ...current,\r\n mode: current.mode === 'floating' ? current.dock : 'floating'\r\n }))\r\n }\r\n const dockTo = (dock: DockSide) => {\r\n closePopup()\r\n setUi((current) => ({ ...current, mode: dock, dock }))\r\n }\r\n\r\n const clearServerCache = () => loadModel(true).then(devtools.refresh)\r\n\r\n const loading = instances.filter((item) => item.last.status === 'loading').length\r\n const errors = instances.filter((item) => item.last.status === 'error').length\r\n const storms = instances.filter((item) => item.storm).length\r\n const hoveredLabel = instances.find((item) => item.instanceId === hovered)?.label\r\n\r\n const needsModel = (content: (registered: ModelDef) => ReactNode) =>\r\n describeError ? (\r\n <Alert severity=\"error\" sx={{ m: 1.5 }}>\r\n Não foi possível carregar o modelo: {describeError}. O endpoint precisa chamar{' '}\r\n <code>runQuery(..., {'{ devtools: true }'})</code> em desenvolvimento.\r\n </Alert>\r\n ) : !original ? (\r\n <Box sx={{ p: 3, display: 'flex', justifyContent: 'center' }}>\r\n <CircularProgress size={20} />\r\n </Box>\r\n ) : (\r\n content(original)\r\n )\r\n\r\n const header = (\r\n <Box\r\n onMouseDown={startDrag}\r\n onDoubleClick={(event) => {\r\n if (floating && !(event.target as Element).closest('button, [role=\"tab\"]')) toggleMode()\r\n }}\r\n sx={{\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 1.5,\r\n px: 1.5,\r\n borderBottom: 1,\r\n borderColor: 'divider',\r\n cursor: floating ? 'move' : undefined,\r\n // Na lateral não cabe tudo numa linha: as abas descem para a linha de baixo\r\n ...(side && { flexWrap: 'wrap', columnGap: 1, pt: 0.5 })\r\n }}\r\n >\r\n <Typography sx={{ fontWeight: 800, color: 'primary.main', whiteSpace: 'nowrap' }}>\r\n ◆ BI Devtools\r\n </Typography>\r\n <Chip size=\"small\" label={model} sx={{ fontFamily: MONO }} />\r\n <Tabs\r\n value={ui.tab}\r\n onChange={(_, tab: TabKey) => setTab(tab)}\r\n variant=\"scrollable\"\r\n scrollButtons=\"auto\"\r\n sx={{ minHeight: 40, ...(side && { order: 1, width: '100%' }) }}\r\n >\r\n <Tab\r\n value=\"queries\"\r\n label={\r\n <Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>\r\n Consultas ({instances.length}){!!loading && <CircularProgress size={10} />}\r\n {!!(errors || storms) && (\r\n <Chip size=\"small\" color=\"error\" label={errors + storms} sx={{ height: 16 }} />\r\n )}\r\n </Box>\r\n }\r\n />\r\n <Tab value=\"model\" label=\"Modelo\" />\r\n <Tab value=\"layout\" label=\"Layout\" />\r\n <Tab value=\"playground\" label=\"Playground\" />\r\n <Tab value=\"regression\" label=\"Regressão\" />\r\n <Tab value=\"dictionary\" label=\"Dicionário\" />\r\n <Tab value=\"filters\" label=\"Filtros\" />\r\n </Tabs>\r\n {devtools.draft && <Chip size=\"small\" color=\"warning\" label=\"rascunho aplicado\" />}\r\n <Box sx={{ ml: 'auto', display: 'flex', alignItems: 'center', gap: 0.5 }}>\r\n <Tooltip title=\"Inspecionar componente (Alt+Shift+I)\">\r\n <IconButton\r\n size=\"small\"\r\n color={inspecting ? 'primary' : 'default'}\r\n onClick={() => setInspecting((value) => !value)}\r\n aria-label=\"Inspecionar componente\"\r\n >\r\n ⌖\r\n </IconButton>\r\n </Tooltip>\r\n {DOCK_SIDES.map(({ side: dock, icon, label }) => (\r\n <Tooltip key={dock} title={`${label} (ocupa espaço na página)`}>\r\n <IconButton\r\n size=\"small\"\r\n color={ui.mode === dock ? 'primary' : 'default'}\r\n onClick={() => dockTo(dock)}\r\n aria-label={label}\r\n >\r\n {icon}\r\n </IconButton>\r\n </Tooltip>\r\n ))}\r\n <Tooltip title=\"Janela flutuante, por cima da página (Alt+Shift+F) · arraste pelo cabeçalho\">\r\n <IconButton\r\n size=\"small\"\r\n color={floating ? 'primary' : 'default'}\r\n onClick={toggleMode}\r\n aria-label=\"Devtools flutuante\"\r\n >\r\n ⧉\r\n </IconButton>\r\n </Tooltip>\r\n <Tooltip title=\"Abrir numa janela separada do navegador (ex.: em outro monitor)\">\r\n <IconButton\r\n size=\"small\"\r\n color={inWindow ? 'primary' : 'default'}\r\n onClick={inWindow ? () => popup?.focus() : toWindow}\r\n aria-label=\"Devtools em janela separada\"\r\n >\r\n ↗\r\n </IconButton>\r\n </Tooltip>\r\n <Tooltip title=\"Fechar (Alt+Shift+B)\">\r\n <IconButton size=\"small\" onClick={closePanel} aria-label=\"Fechar devtools\">\r\n ✕\r\n </IconButton>\r\n </Tooltip>\r\n </Box>\r\n </Box>\r\n )\r\n\r\n const body = (\r\n <Box sx={{ flex: 1, minHeight: 0 }}>\r\n {ui.tab === 'queries' && (\r\n <QueriesPanel\r\n devtools={devtools}\r\n capabilities={capabilities}\r\n selected={selected}\r\n onSelect={setSelected}\r\n onHover={setHovered}\r\n onClearServerCache={clearServerCache}\r\n />\r\n )}\r\n {ui.tab === 'model' &&\r\n needsModel((registered) => (\r\n <ModelPanel\r\n devtools={devtools}\r\n original={registered}\r\n capabilities={capabilities}\r\n tables={tables ?? []}\r\n onTry={(selection) => {\r\n setPlayground(selection)\r\n setTab('playground')\r\n }}\r\n // O Next recompila a rota ao ver o arquivo novo; espera um pouco antes de reler\r\n onSaved={() => setTimeout(() => loadModel(), 1000)}\r\n />\r\n ))}\r\n {ui.tab === 'layout' &&\r\n needsModel((registered) => (\r\n <LayoutPanel\r\n devtools={devtools}\r\n model={devtools.draft ?? registered}\r\n capabilities={capabilities}\r\n picked={pickedItem}\r\n onHover={setHovered}\r\n />\r\n ))}\r\n {ui.tab === 'playground' &&\r\n needsModel((registered) => (\r\n <PlaygroundPanel\r\n model={devtools.draft ?? registered}\r\n selection={playground}\r\n onSelectionChange={setPlayground}\r\n />\r\n ))}\r\n {ui.tab === 'regression' && (\r\n <RegressionPanel devtools={devtools} capabilities={capabilities} />\r\n )}\r\n {ui.tab === 'dictionary' && (\r\n <Box sx={{ p: 1.5, overflow: 'auto', height: '100%' }}>\r\n <Typography sx={{ fontSize: 12, color: 'text.secondary', mb: 1.5 }}>\r\n O mesmo <code>{'<ModelDictionary />'}</code> pode ir numa página do dashboard como\r\n documentação para quem usa. Edite rótulos e descrições na aba Modelo.\r\n </Typography>\r\n <ModelDictionary />\r\n </Box>\r\n )}\r\n {ui.tab === 'filters' && <FiltersPanel devtools={devtools} />}\r\n </Box>\r\n )\r\n\r\n return (\r\n <Portal>\r\n <ThemeProvider theme={theme}>\r\n <HighlightOverlay instanceId={hovered} label={hoveredLabel} zIndex={Z_INDEX + 1} />\r\n\r\n {ui.open && inWindow && popup && (\r\n <DevtoolsWindow\r\n popup={popup}\r\n title={`BI Devtools · ${model}`}\r\n theme={theme}\r\n onClosed={onPopupClosed}\r\n >\r\n <Paper\r\n {...devtoolsMarker}\r\n square\r\n elevation={0}\r\n sx={{\r\n height: '100%',\r\n display: 'flex',\r\n flexDirection: 'column',\r\n color: 'text.primary',\r\n overflow: 'hidden'\r\n }}\r\n >\r\n {header}\r\n {body}\r\n </Paper>\r\n </DevtoolsWindow>\r\n )}\r\n\r\n {ui.open && !inWindow ? (\r\n <Paper\r\n {...devtoolsMarker}\r\n square={!floating}\r\n elevation={floating ? 16 : 12}\r\n sx={{\r\n position: 'fixed',\r\n zIndex: Z_INDEX,\r\n display: 'flex',\r\n flexDirection: 'column',\r\n color: 'text.primary',\r\n overflow: 'hidden',\r\n ...(floating\r\n ? {\r\n left: ui.float.x,\r\n top: ui.float.y,\r\n width: ui.float.width,\r\n height: ui.float.height,\r\n border: '1px solid #F58220',\r\n borderRadius: 1.5\r\n }\r\n : side\r\n ? {\r\n top: 0,\r\n bottom: 0,\r\n [side]: 0,\r\n width: ui.width,\r\n [side === 'left' ? 'borderRight' : 'borderLeft']: '2px solid #F58220'\r\n }\r\n : {\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n height: ui.height,\r\n borderTop: '2px solid #F58220'\r\n })\r\n }}\r\n >\r\n {floating ? (\r\n <Box\r\n onMouseDown={startFloatResize}\r\n title=\"Redimensionar\"\r\n sx={{\r\n position: 'absolute',\r\n right: 0,\r\n bottom: 0,\r\n width: 16,\r\n height: 16,\r\n zIndex: 1,\r\n cursor: 'nwse-resize',\r\n // Riscos diagonais no canto, como o \"grip\" de janela\r\n background:\r\n 'linear-gradient(135deg, transparent 0 55%, #F58220 55% 62%, transparent 62% 72%, #F58220 72% 79%, transparent 79%)'\r\n }}\r\n />\r\n ) : (\r\n <Box\r\n onMouseDown={startDockResize}\r\n sx={\r\n side\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n bottom: 0,\r\n [side === 'left' ? 'right' : 'left']: -3,\r\n width: 8,\r\n zIndex: 1,\r\n cursor: 'ew-resize'\r\n }\r\n : {\r\n position: 'absolute',\r\n top: -5,\r\n left: 0,\r\n right: 0,\r\n height: 8,\r\n cursor: 'ns-resize'\r\n }\r\n }\r\n />\r\n )}\r\n {header}\r\n {body}\r\n </Paper>\r\n ) : (\r\n <ToggleButton\r\n draft={!!devtools.draft}\r\n loading={loading}\r\n problems={errors + storms}\r\n inspecting={inspecting}\r\n onOpen={inWindow ? () => popup?.focus() : openPanel}\r\n />\r\n )}\r\n\r\n {inspecting && (\r\n <Box\r\n {...devtoolsMarker}\r\n sx={{\r\n position: 'fixed',\r\n top: 12,\r\n left: '50%',\r\n transform: 'translateX(-50%)',\r\n zIndex: Z_INDEX + 2,\r\n bgcolor: '#1b1e23',\r\n color: '#fff',\r\n border: '1px solid #F58220',\r\n borderRadius: 1,\r\n px: 1.5,\r\n py: 0.75,\r\n fontSize: 12,\r\n boxShadow: 6\r\n }}\r\n >\r\n {layoutTab\r\n ? 'Inspetor: clique num gráfico ou filtro para editá-lo · Esc para sair'\r\n : 'Inspetor: clique num gráfico ou filtro do dashboard · Esc para sair'}\r\n </Box>\r\n )}\r\n </ThemeProvider>\r\n </Portal>\r\n )\r\n}\r\n\r\nfunction ToggleButton({\r\n draft,\r\n loading,\r\n problems,\r\n inspecting,\r\n onOpen\r\n}: {\r\n draft: boolean\r\n loading: number\r\n problems: number\r\n inspecting: boolean\r\n onOpen: () => void\r\n}) {\r\n return (\r\n <Tooltip title=\"BI Devtools (Alt+Shift+B)\" placement=\"right\">\r\n <Box\r\n {...devtoolsMarker}\r\n component=\"button\"\r\n type=\"button\"\r\n onClick={onOpen}\r\n aria-label=\"Abrir BI Devtools\"\r\n sx={{\r\n position: 'fixed',\r\n left: 12,\r\n bottom: 12,\r\n zIndex: Z_INDEX,\r\n display: 'flex',\r\n alignItems: 'center',\r\n gap: 0.75,\r\n px: 1.25,\r\n height: 32,\r\n border: '1px solid',\r\n borderColor: draft || inspecting ? 'warning.main' : '#F58220',\r\n borderRadius: 16,\r\n bgcolor: '#1b1e23',\r\n color: '#fff',\r\n fontSize: 12,\r\n fontWeight: 800,\r\n cursor: 'pointer',\r\n boxShadow: 4,\r\n opacity: 0.85,\r\n '&:hover': { opacity: 1 }\r\n }}\r\n >\r\n <Box component=\"span\" sx={{ color: '#F58220' }}>\r\n ◆\r\n </Box>\r\n BI\r\n {!!loading && <CircularProgress size={10} sx={{ color: '#4dabf7' }} />}\r\n {!!problems && (\r\n <Box component=\"span\" sx={{ bgcolor: 'error.main', borderRadius: 8, px: 0.75 }}>\r\n {problems}\r\n </Box>\r\n )}\r\n {draft && (\r\n <Box component=\"span\" sx={{ color: 'warning.main' }}>\r\n rascunho\r\n </Box>\r\n )}\r\n </Box>\r\n </Tooltip>\r\n )\r\n}\r\n"],"mappings":"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"}
|