@wibi-global/sdk 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. package/dist/artifact-schema/src/biCatalog.d.ts +3 -0
  2. package/dist/artifact-schema/src/biCatalog.d.ts.map +1 -0
  3. package/dist/artifact-schema/src/biCatalog.js +36 -0
  4. package/dist/artifact-schema/src/biCatalog.js.map +1 -0
  5. package/dist/artifact-schema/src/hash.d.ts +3 -0
  6. package/dist/artifact-schema/src/hash.d.ts.map +1 -0
  7. package/dist/artifact-schema/src/hash.js +22 -0
  8. package/dist/artifact-schema/src/hash.js.map +1 -0
  9. package/dist/artifact-schema/src/index.d.ts +6 -0
  10. package/dist/artifact-schema/src/index.d.ts.map +1 -0
  11. package/dist/artifact-schema/src/index.js +6 -0
  12. package/dist/artifact-schema/src/index.js.map +1 -0
  13. package/dist/artifact-schema/src/schema.d.ts +274 -0
  14. package/dist/artifact-schema/src/schema.d.ts.map +1 -0
  15. package/dist/artifact-schema/src/schema.js +165 -0
  16. package/dist/artifact-schema/src/schema.js.map +1 -0
  17. package/dist/artifact-schema/src/types.d.ts +88 -0
  18. package/dist/artifact-schema/src/types.d.ts.map +1 -0
  19. package/dist/artifact-schema/src/types.js +2 -0
  20. package/dist/artifact-schema/src/types.js.map +1 -0
  21. package/dist/artifact-schema/src/validate.d.ts +4 -0
  22. package/dist/artifact-schema/src/validate.d.ts.map +1 -0
  23. package/dist/artifact-schema/src/validate.js +101 -0
  24. package/dist/artifact-schema/src/validate.js.map +1 -0
  25. package/dist/instructions/AGENTS.md +92 -0
  26. package/dist/instructions/AGENT_COMMON.md +78 -0
  27. package/dist/instructions/CLAUDE.md +54 -0
  28. package/dist/instructions/CODEX.md +38 -0
  29. package/dist/instructions/GEMINI.md +35 -0
  30. package/dist/prompts/authoring.wbp +61 -0
  31. package/dist/sdk/src/builder.d.ts.map +1 -0
  32. package/dist/sdk/src/builder.js.map +1 -0
  33. package/dist/sdk/src/context.d.ts.map +1 -0
  34. package/dist/sdk/src/context.js.map +1 -0
  35. package/dist/sdk/src/dashboard-context.d.ts.map +1 -0
  36. package/dist/sdk/src/dashboard-context.js.map +1 -0
  37. package/dist/sdk/src/dashboard-spec.d.ts.map +1 -0
  38. package/dist/{dashboard-spec.js → sdk/src/dashboard-spec.js} +4 -1
  39. package/dist/sdk/src/dashboard-spec.js.map +1 -0
  40. package/dist/sdk/src/data/ctx.wbx +114 -0
  41. package/dist/sdk/src/data/index.d.ts.map +1 -0
  42. package/dist/sdk/src/data/index.js +12 -0
  43. package/dist/sdk/src/data/index.js.map +1 -0
  44. package/dist/sdk/src/data/queries.wbx +330 -0
  45. package/dist/sdk/src/data/serialization/dashboard-serialization.types.d.ts.map +1 -0
  46. package/dist/sdk/src/data/serialization/dashboard-serialization.types.js.map +1 -0
  47. package/dist/sdk/src/data/serialization/dashboard-serialization.types.ts +430 -0
  48. package/dist/sdk/src/data/serialization/index.d.ts.map +1 -0
  49. package/dist/sdk/src/data/serialization/index.js.map +1 -0
  50. package/dist/sdk/src/data/syntax.wbx +155 -0
  51. package/dist/sdk/src/data/view-categories.wbx +88 -0
  52. package/dist/sdk/src/data/views.wbx +1118 -0
  53. package/dist/sdk/src/data/widgets.wbx +2477 -0
  54. package/dist/sdk/src/data.d.ts.map +1 -0
  55. package/dist/sdk/src/data.js.map +1 -0
  56. package/dist/sdk/src/index.d.ts.map +1 -0
  57. package/dist/sdk/src/index.js.map +1 -0
  58. package/package.json +2 -2
  59. package/dist/builder.d.ts.map +0 -1
  60. package/dist/builder.js.map +0 -1
  61. package/dist/context.d.ts.map +0 -1
  62. package/dist/context.js.map +0 -1
  63. package/dist/dashboard-context.d.ts.map +0 -1
  64. package/dist/dashboard-context.js.map +0 -1
  65. package/dist/dashboard-spec.d.ts.map +0 -1
  66. package/dist/dashboard-spec.js.map +0 -1
  67. package/dist/data/index.d.ts.map +0 -1
  68. package/dist/data/index.js +0 -12
  69. package/dist/data/index.js.map +0 -1
  70. package/dist/data/serialization/dashboard-serialization.types.d.ts.map +0 -1
  71. package/dist/data/serialization/dashboard-serialization.types.js.map +0 -1
  72. package/dist/data/serialization/index.d.ts.map +0 -1
  73. package/dist/data/serialization/index.js.map +0 -1
  74. package/dist/data.d.ts.map +0 -1
  75. package/dist/data.js.map +0 -1
  76. package/dist/index.d.ts.map +0 -1
  77. package/dist/index.js.map +0 -1
  78. /package/dist/{builder.d.ts → sdk/src/builder.d.ts} +0 -0
  79. /package/dist/{builder.js → sdk/src/builder.js} +0 -0
  80. /package/dist/{context.d.ts → sdk/src/context.d.ts} +0 -0
  81. /package/dist/{context.js → sdk/src/context.js} +0 -0
  82. /package/dist/{dashboard-context.d.ts → sdk/src/dashboard-context.d.ts} +0 -0
  83. /package/dist/{dashboard-context.js → sdk/src/dashboard-context.js} +0 -0
  84. /package/dist/{dashboard-spec.d.ts → sdk/src/dashboard-spec.d.ts} +0 -0
  85. /package/dist/{data → sdk/src/data}/index.d.ts +0 -0
  86. /package/dist/{data → sdk/src/data}/serialization/dashboard-serialization.types.d.ts +0 -0
  87. /package/dist/{data → sdk/src/data}/serialization/dashboard-serialization.types.js +0 -0
  88. /package/dist/{data → sdk/src/data}/serialization/index.d.ts +0 -0
  89. /package/dist/{data → sdk/src/data}/serialization/index.js +0 -0
  90. /package/dist/{data.d.ts → sdk/src/data.d.ts} +0 -0
  91. /package/dist/{data.js → sdk/src/data.js} +0 -0
  92. /package/dist/{index.d.ts → sdk/src/index.d.ts} +0 -0
  93. /package/dist/{index.js → sdk/src/index.js} +0 -0
@@ -0,0 +1,2477 @@
1
+ {
2
+ "__CONTEXT_BLOCK__": {
3
+ "block_name": "WIDGET_SCHEMA",
4
+ "block_role": "SOURCE_OF_TRUTH_FOR_WIDGETS_COMPONENTS_AND_PROPS",
5
+ "llm_instruction": "Este bloco define contratos válidos de widgets, componentes e props que o TSX pode usar. Para dashboard.serialized.json, cada widget (chart, grid, kpi, progress-list) é sempre um elemento INDEPENDENTE e DIRETO na section — NUNCA embrulhe dois ou mais widgets dentro de um group, container ou div com título. PROIBIDO criar seções aglutinadoras como 'Evolução Temporal' que contêm múltiplos charts. Cada chart tem sua própria entrada em widgets[] com seu próprio title em properties. SHOW_TITLE: sections SEMPRE com show_title: false — o title da section é ID interno, nunca visual. Um section com show_title: true renderiza um container com header que envolve todos os widgets dentro — isso é PROIBIDO.",
6
+ "last_synced_from": "wibi/src/pages/bi/designer/config/widgetSchemas.ts",
7
+ "last_synced_date": "2026-03-20"
8
+ },
9
+ "__SQL_TEMPLATE_RULES__": {
10
+ "block_name": "SQL_TEMPLATE_RULES",
11
+ "block_role": "REGRAS_CRITICAS_PARA_GERACAO_DE_SQL_NO_dashboard.serialized.json",
12
+ "llm_instruction": "LEIA ESTE BLOCO ANTES DE ESCREVER QUALQUER sql_template. Ele define as únicas variáveis aceitas pelo resolveSqlTemplate() do renderer.",
13
+
14
+ "variaveis_substituidas_pelo_renderer": {
15
+ "{{startDate}}": "Data de início do período selecionado pelo usuário. Formato: 'YYYY-MM-DD'. Aliases aceitos: {{start_date}}, ${startDate}.",
16
+ "{{endDate}}": "Data de fim do período selecionado pelo usuário. Formato: 'YYYY-MM-DD'. Aliases aceitos: {{end_date}}, ${endDate}.",
17
+ "{{year}}": "Ano de início extraído de startDate (4 dígitos). Ex: 2025.",
18
+ "{{dsoStartDate}}": "Data de início ampliada (2 anos atrás) para janelas DSO. Alias aceito: {{date_limit_2y}}.",
19
+ "${companyFilter:alias}": "Injeta 'AND alias.id_empresa = N' quando empresa está selecionada, ou string vazia. N = empresaId selecionado.",
20
+ "${empresaId}": "ID numérico da empresa selecionada (0 se nenhuma). Aliases: ${companyId}, ${companyIds}."
21
+ },
22
+
23
+ "filtros_de_dropdown_NAO_vao_no_SQL": {
24
+ "REGRA_ABSOLUTA": "O dropdown filtra os dados NO CLIENTE (browser) DEPOIS que a query retornou. A query SQL não sabe que existe um dropdown. NUNCA crie variáveis de dropdown no sql_template.",
25
+ "COMO_FUNCIONA": "1. A query executa no banco e retorna TODOS os registros do período. 2. O widget dropdown lê os valores únicos do campo filter_field desse resultado. 3. Quando o usuário seleciona um valor, o renderer filtra as linhas localmente. 4. Todos os widgets com a mesma query_id passam a ver apenas as linhas filtradas. Nenhuma nova query é disparada.",
26
+ "PROIBIDO_ABSOLUTAMENTE": [
27
+ "{{#estado}}...{{/estado}} — Mustache condicional — NÃO EXISTE no renderer — causa SYNTAX_ERROR no banco",
28
+ "{{estado}} como filtro — a variável {{estado}} NÃO É substituída pelo renderer — chega literal no banco — causa SYNTAX_ERROR",
29
+ "AND (estado IN ({{estado}}) OR {{estado}} IS NULL) — PROIBIDO — mesma razão",
30
+ "AND campo = '{{valorDropdown}}' — PROIBIDO — valores de dropdown nunca são injetados no SQL",
31
+ "{% if campo %}...{% endif %} — Jinja — NÃO É suportado",
32
+ "qualquer tentativa de tornar o SQL condicional baseado em seleção de dropdown"
33
+ ],
34
+ "CORRETO": "A query retorna TODOS os dados. O dropdown filtra localmente. Ponto final."
35
+ },
36
+
37
+ "padrao_correto_de_query_com_dropdown": {
38
+ "explicacao": "Dashboard com dropdown de 'estado' filtrando charts e grid. A query NÃO menciona estado em nenhuma variável — apenas usa {{startDate}} e {{endDate}}.",
39
+ "query_CORRETA": {
40
+ "id": "q-vendas",
41
+ "sql_template": "SELECT estado, produto, sum(valor) AS total FROM vw_vendas WHERE data >= '{{startDate}}' AND data <= '{{endDate}}' GROUP BY estado, produto ORDER BY total DESC"
42
+ },
43
+ "query_ERRADA_nao_fazer": {
44
+ "id": "q-vendas",
45
+ "sql_template": "SELECT estado, produto, sum(valor) AS total FROM vw_vendas WHERE data >= '{{startDate}}' AND data <= '{{endDate}}' AND (estado IN ({{estado}}) OR {{estado}} IS NULL) GROUP BY estado, produto ORDER BY total DESC",
46
+ "motivo_do_erro": "{{estado}} não é substituída pelo renderer. Chega literal no banco. ClickHouse retorna SYNTAX_ERROR."
47
+ },
48
+ "dropdown_widget": {
49
+ "id": "w-filtro-estado",
50
+ "widget_type": "dropdown",
51
+ "query_id": "q-vendas",
52
+ "properties": {
53
+ "filter_field": "estado",
54
+ "label": "Filtrar por Estado",
55
+ "allow_multiple": true
56
+ }
57
+ },
58
+ "chart_widget": {
59
+ "id": "w-chart-vendas",
60
+ "widget_type": "chart",
61
+ "query_id": "q-vendas",
62
+ "properties": { "chart_type": "bar", "x_field": "estado", "y_field": "total" }
63
+ },
64
+ "resultado": "Dropdown e chart compartilham query_id='q-vendas'. Ao selecionar 'SP' no dropdown, o chart exibe só SP — sem nova query SQL."
65
+ },
66
+
67
+ "variaveis_NAO_suportadas": [
68
+ "{{#campo}}...{{/campo}} — Mustache condicional — NÃO EXISTE",
69
+ "{{campo}} como valor de filtro de dropdown — NÃO É substituída",
70
+ "qualquer variável além das listadas em variaveis_substituidas_pelo_renderer"
71
+ ],
72
+
73
+ "como_filtrar_por_empresa_no_sql": {
74
+ "padrao": "Use ${companyFilter:alias} para injetar o filtro de empresa automaticamente.",
75
+ "exemplo": "SELECT * FROM vw_vendas v WHERE v.data >= '{{startDate}}' AND v.data <= '{{endDate}}' ${companyFilter:v}",
76
+ "resultado_com_empresa": "SELECT * FROM vw_vendas v WHERE v.data >= '2025-01-01' AND v.data <= '2025-03-31' AND v.id_empresa = 42",
77
+ "resultado_sem_empresa": "SELECT * FROM vw_vendas v WHERE v.data >= '2025-01-01' AND v.data <= '2025-03-31' "
78
+ },
79
+
80
+ "resumo_regras_de_ouro": [
81
+ "1. sql_template só aceita {{startDate}}, {{endDate}}, {{year}}, {{dsoStartDate}}, ${companyFilter:alias}, ${empresaId}.",
82
+ "2. Filtros de dropdown NÃO entram no SQL — são aplicados no cliente.",
83
+ "3. NUNCA use {{#campo}}...{{/campo}} — causa SYNTAX_ERROR no banco.",
84
+ "4. A query deve sempre retornar todos os dados do período; o dropdown filtra localmente.",
85
+ "5. Para filtrar por empresa no SQL, use ${companyFilter:alias} — nunca uma variável de dropdown."
86
+ ]
87
+ },
88
+ "__WIDGET_SELECTION_GUIDE__": {
89
+ "block_name": "WIDGET_SELECTION_GUIDE",
90
+ "block_role": "LLM_INTELLIGENCE — guia de escolha do widget_type certo para cada situação",
91
+ "llm_instruction": "Use esta tabela para decidir o widget_type mais adequado antes de criar qualquer widget no dashboard.serialized.json.",
92
+ "by_use_case": {
93
+ "indicador_unico": "widget_type='kpi' — para exibir UM número em destaque (faturamento total, qtd pedidos). Use múltiplos 'kpi' em seção multi-coluna para painel de indicadores.",
94
+ "indicador_com_tendencia": "widget_type='sparkline' — KPI com mini gráfico de tendência embutido.",
95
+ "varios_kpis_configurados": "widget_type='multi-card' — vários indicadores com ícone/cor em um único widget.",
96
+ "barras_verticais": "widget_type='chart' com chart_type='bar'",
97
+ "barras_horizontais": "widget_type='chart' com chart_type='horizontal_bar'",
98
+ "barras_empilhadas": "widget_type='chart' com chart_type='stacked_bar'",
99
+ "linha_de_tendencia": "widget_type='chart' com chart_type='line'",
100
+ "area_volume": "widget_type='chart' com chart_type='area'",
101
+ "pizza_proporcao": "widget_type='chart' com chart_type='pie'",
102
+ "donut_proporcao": "widget_type='chart' com chart_type='pie' e inner_radius > 0",
103
+ "ranking_com_barra": "widget_type='progress-list' — top N itens com barra proporcional",
104
+ "tabela_de_dados": "widget_type='grid' — tabela paginável com formatação por coluna",
105
+ "tabela_cruzada": "widget_type='pivot' — linhas × colunas com valor agregado",
106
+ "velocimetro_meta": "widget_type='gauge' — medidor circular com escala",
107
+ "funil_conversao": "widget_type='funnel' — etapas de pipeline decrescentes",
108
+ "cascata_contribuicao": "widget_type='waterfall' — parcelas positivas/negativas para um total",
109
+ "dispersao_correlacao": "widget_type='scatter' — dois campos numéricos X×Y",
110
+ "mapa_calor_matriz": "widget_type='heatmap' — grade colorida por intensidade",
111
+ "hierarquia_retangulos": "widget_type='treemap' — blocos proporcionais ao valor",
112
+ "hierarquia_aneis": "widget_type='sunburst' — anéis concêntricos hierárquicos",
113
+ "hierarquia_arvore": "widget_type='tree' — nós pai-filho com setas",
114
+ "fluxo_entre_nos": "widget_type='sankey' — diagrama de fluxo entre categorias",
115
+ "rede_relacionamentos": "widget_type='graph' — nós conectados por arestas",
116
+ "comparacao_multivariada": "widget_type='radar' — aranha com múltiplos eixos",
117
+ "velas_financeiras": "widget_type='candlestick' — OHLC financeiro",
118
+ "distribuicao_estatistica": "widget_type='boxplot' — mediana, quartis, outliers",
119
+ "fluxo_tematico_tempo": "widget_type='themeriver' — categorias evoluindo ao longo do tempo",
120
+ "eventos_cronologicos": "widget_type='timeline' — linha do tempo de eventos",
121
+ "pontos_no_mapa": "widget_type='map' — marcadores lat/lon no mapa",
122
+ "regioes_coloridas": "widget_type='filled-map' — coroplético por estado/país",
123
+ "rotas_geograficas": "widget_type='lines' — fluxo animado entre dois pontos geo",
124
+ "filtro_combobox": "widget_type='dropdown' — seleção de valor de um campo para filtrar",
125
+ "filtro_slicer": "widget_type='filter' — painel de filtro visual com botões",
126
+ "filtro_periodo": "widget_type='date' — seletor de período (Dia/Semana/Mês/Ano)",
127
+ "filtro_empresa": "widget_type='companies' — seletor de empresa",
128
+ "titulo_secao": "widget_type='heading' — H1/H2/H3/H4 decorativo",
129
+ "texto_livre": "widget_type='text' — bloco de texto/markdown",
130
+ "imagem_logo": "widget_type='image' — imagem estática",
131
+ "separador": "widget_type='divider' — linha separadora",
132
+ "espacamento": "widget_type='spacer' — espaço vertical"
133
+ },
134
+ "height_recommendations": {
135
+ "kpi": 120,
136
+ "sparkline": 150,
137
+ "multi-card": 160,
138
+ "chart": 400,
139
+ "grid": 350,
140
+ "pivot": 380,
141
+ "progress-list": 350,
142
+ "gauge": 320,
143
+ "funnel": 350,
144
+ "waterfall": 400,
145
+ "scatter": 380,
146
+ "heatmap": 380,
147
+ "treemap": 360,
148
+ "sunburst": 400,
149
+ "tree": 420,
150
+ "sankey": 400,
151
+ "graph": 420,
152
+ "radar": 380,
153
+ "candlestick": 380,
154
+ "boxplot": 360,
155
+ "parallel": 380,
156
+ "themeriver": 380,
157
+ "timeline": 400,
158
+ "map": 380,
159
+ "filled-map": 400,
160
+ "lines": 400
161
+ }
162
+ },
163
+ "dashboardStyling": {
164
+ "llm_instruction": "O dashboard.serialized.json suporta propriedades de estilização global (em metadata) e por seção (em layout.sections[]). A organização visual deve acontecer com sections, heading/text/divider e widgets diretos. NUNCA use group para agrupar charts. CADA chart é um widget independente em widgets[] com title em properties.title — não existe 'container de charts'. Dois charts side-by-side = dois widgets na mesma section com col_span adequado. Um chart por linha = um widget com col_span igual ao número de colunas da section. CRÍTICO: show_title nas sections é SEMPRE false — o title da section é um identificador interno, NUNCA um cabeçalho visual. O título visível de um chart vai SOMENTE em properties.title do widget.",
165
+ "metadata_styling_properties": {
166
+ "background_color": {
167
+ "type": "string",
168
+ "description": "Cor de fundo global do dashboard. Aceita hex (#f0f4f8), rgb(240,244,248), ou CSS gradient (linear-gradient(135deg, #667eea, #764ba2)).",
169
+ "example": "#f8fafc"
170
+ },
171
+ "text_color": {
172
+ "type": "string",
173
+ "description": "Cor do texto padrão do dashboard.",
174
+ "example": "#1e293b"
175
+ },
176
+ "font_family": {
177
+ "type": "string",
178
+ "description": "Fonte customizada. Ex: 'Inter, sans-serif'"
179
+ },
180
+ "section_gap": {
181
+ "type": "number",
182
+ "description": "Espaçamento vertical entre seções em px. Padrão: 26.",
183
+ "example": 32
184
+ },
185
+ "padding": {
186
+ "type": "number",
187
+ "description": "Padding geral do canvas em px. Padrão: 24.",
188
+ "example": 16
189
+ }
190
+ },
191
+ "section_styling_properties": {
192
+ "background_color": { "type": "string", "description": "Cor de fundo da seção." },
193
+ "text_color": { "type": "string", "description": "Cor do texto da seção." },
194
+ "border_radius": { "type": "number", "description": "Raio de borda em px." },
195
+ "padding": { "type": "number", "description": "Padding interno em px." },
196
+ "show_title": { "type": "boolean", "default": false, "description": "SEMPRE false — oculta o título da seção. O título de cada chart/widget vai em properties.title do próprio widget, NUNCA no title da section. REGRA: show_title deve ser false em TODAS as sections do dashboard.serialized.json." }
197
+ },
198
+ "section_llm_rules": {
199
+ "llm_instruction": "REGRA CRÍTICA DE SECTIONS: show_title DEVE ser sempre false. O 'title' do SerializedSection é apenas um identificador interno — NUNCA é renderizado visualmente. Título visível de um chart/grid/kpi vai EXCLUSIVAMENTE em properties.title do widget. Uma section com title='Evolução Temporal' e show_title=true renderiza como um CONTAINER VISUAL com header 'Evolução Temporal' envolvendo todos os widgets — isso é PROIBIDO. Padrão correto: { id: 'sec-charts', title: 'charts', show_title: false, columns: 2, items: ['w-chart-1', 'w-chart-2'] } — cada widget declara seu próprio title em properties."
200
+ },
201
+ "widget_styling_properties": {
202
+ "llm_instruction": "Todo widget (data ou decorativo) pode ter estas propriedades opcionais de estilização:",
203
+ "background_color": { "type": "string", "description": "Cor de fundo do widget." },
204
+ "text_color": { "type": "string", "description": "Cor do texto do widget." },
205
+ "border_radius": { "type": "number", "description": "Raio de borda em px." },
206
+ "borderless": { "type": "boolean", "default": false, "description": "Se true, remove borda e sombra do widget." }
207
+ }
208
+ },
209
+ "implicitDataProperties": {
210
+ "description": "Propriedades injetadas automaticamente por getDefaultProperties() em TODO widget que NÃO está na lista NO_DATA_WIDGETS. Fonte: widgetSchemas.ts → getDefaultProperties()",
211
+ "NO_DATA_WIDGETS": ["text", "image", "group", "date", "companies"],
212
+ "injectedProps": {
213
+ "sql": {
214
+ "type": "string",
215
+ "defaultValue": "",
216
+ "description": "Query SQL que alimenta o widget. Pode ser definida pelo designer ou pela LLM via customSQL."
217
+ },
218
+ "connectionConfig": {
219
+ "type": "object | null",
220
+ "defaultValue": null,
221
+ "description": "Configuração de conexão BI (connectionId, host, etc). Geralmente vem do DataSource vinculado."
222
+ },
223
+ "biConnectionId": {
224
+ "type": "number",
225
+ "defaultValue": 0,
226
+ "description": "ID da conexão BI usada para executar a query SQL. 0 = não configurado."
227
+ }
228
+ },
229
+ "llm_instruction": "Todo widget que carrega dados possui implicitamente sql, connectionConfig e biConnectionId em properties. Widgets com noData:true NÃO possuem essas props."
230
+ },
231
+ "tsxContracts": {
232
+ "EChartsChart": {
233
+ "import": "@/pages/bi/designer/components/items/EChartsChart",
234
+ "component": "EChartsChart",
235
+ "requiredProps": [
236
+ "item",
237
+ "data"
238
+ ],
239
+ "optionalProps": [
240
+ "theme",
241
+ "onUpdate",
242
+ "isDesignMode",
243
+ "enableTypeSwitcher",
244
+ "showZoomButton",
245
+ "onCrossFilterTrigger"
246
+ ],
247
+ "forbiddenProps": [
248
+ "widget"
249
+ ],
250
+ "itemShape": {
251
+ "type": "DashboardItem",
252
+ "required": [
253
+ "id",
254
+ "type",
255
+ "position",
256
+ "size",
257
+ "properties"
258
+ ],
259
+ "optional": [
260
+ "title",
261
+ "dataSource",
262
+ "zIndex",
263
+ "locked",
264
+ "children",
265
+ "category",
266
+ "widgetFields",
267
+ "customSQL"
268
+ ],
269
+ "properties": {
270
+ "type": "chart",
271
+ "properties": [
272
+ "option",
273
+ "theme",
274
+ "xField",
275
+ "yFields",
276
+ "chartType",
277
+ "aggregation"
278
+ ]
279
+ }
280
+ },
281
+ "notes": [
282
+ "usar item, nunca widget",
283
+ "preferir properties.option para dashboards gerados",
284
+ "data deve ser array",
285
+ "xField, yFields e aggregation são gerenciados pelo WidgetFieldDropZone no designer"
286
+ ]
287
+ },
288
+ "GridComponent": {
289
+ "import": "@/pages/bi/designer/components/items/GridComponent",
290
+ "component": "GridComponent",
291
+ "requiredProps": [
292
+ "item"
293
+ ],
294
+ "optionalProps": [
295
+ "data",
296
+ "theme",
297
+ "onUpdate",
298
+ "isDesignMode"
299
+ ],
300
+ "forbiddenProps": [
301
+ "widget"
302
+ ],
303
+ "notes": [
304
+ "widget de tabela dentro do Designer",
305
+ "usar item.properties.selectedColumns para definir colunas visíveis"
306
+ ]
307
+ },
308
+ "KpiComponent": {
309
+ "import": "@/pages/bi/designer/components/items/KpiComponent",
310
+ "component": "KpiComponent",
311
+ "requiredProps": [
312
+ "item"
313
+ ],
314
+ "optionalProps": [
315
+ "data",
316
+ "isDesignMode",
317
+ "theme"
318
+ ],
319
+ "forbiddenProps": [
320
+ "widget"
321
+ ]
322
+ },
323
+ "CardComponent": {
324
+ "import": "@/pages/bi/designer/components/items/CardComponent",
325
+ "component": "CardComponent",
326
+ "requiredProps": [
327
+ "item"
328
+ ],
329
+ "optionalProps": [
330
+ "data",
331
+ "isDesignMode",
332
+ "theme"
333
+ ],
334
+ "forbiddenProps": [
335
+ "widget"
336
+ ]
337
+ },
338
+ "MultiCardComponent": {
339
+ "import": "@/pages/bi/designer/components/items/MultiCardComponent",
340
+ "component": "MultiCardComponent",
341
+ "requiredProps": [
342
+ "item"
343
+ ],
344
+ "optionalProps": [
345
+ "data",
346
+ "isDesignMode",
347
+ "theme"
348
+ ],
349
+ "forbiddenProps": [
350
+ "widget"
351
+ ]
352
+ },
353
+ "SparklineComponent": {
354
+ "import": "@/pages/bi/designer/components/items/SparklineComponent",
355
+ "component": "SparklineComponent",
356
+ "requiredProps": [
357
+ "item"
358
+ ],
359
+ "optionalProps": [
360
+ "data",
361
+ "isDesignMode",
362
+ "theme"
363
+ ],
364
+ "forbiddenProps": [
365
+ "widget"
366
+ ]
367
+ },
368
+ "FunnelComponent": {
369
+ "import": "@/pages/bi/designer/components/items/FunnelComponent",
370
+ "component": "FunnelComponent",
371
+ "requiredProps": [
372
+ "item"
373
+ ],
374
+ "optionalProps": [
375
+ "data",
376
+ "theme",
377
+ "onUpdate",
378
+ "isDesignMode"
379
+ ],
380
+ "forbiddenProps": [
381
+ "widget"
382
+ ]
383
+ },
384
+ "GaugeComponent": {
385
+ "import": "@/pages/bi/designer/components/items/GaugeComponent",
386
+ "component": "GaugeComponent",
387
+ "requiredProps": [
388
+ "item"
389
+ ],
390
+ "optionalProps": [
391
+ "data",
392
+ "theme"
393
+ ],
394
+ "forbiddenProps": [
395
+ "widget"
396
+ ]
397
+ },
398
+ "EChartsGauge": {
399
+ "import": "@/pages/bi/designer/components/items/EChartsGauge",
400
+ "component": "EChartsGauge",
401
+ "requiredProps": [
402
+ "item"
403
+ ],
404
+ "optionalProps": [
405
+ "data",
406
+ "theme",
407
+ "onUpdate",
408
+ "isDesignMode"
409
+ ],
410
+ "forbiddenProps": [
411
+ "widget"
412
+ ],
413
+ "notes": [
414
+ "versão ECharts do velocímetro, alternativa ao GaugeComponent"
415
+ ]
416
+ },
417
+ "WaterfallComponent": {
418
+ "import": "@/pages/bi/designer/components/items/WaterfallComponent",
419
+ "component": "WaterfallComponent",
420
+ "requiredProps": [
421
+ "item"
422
+ ],
423
+ "optionalProps": [
424
+ "data",
425
+ "theme",
426
+ "onUpdate",
427
+ "isDesignMode"
428
+ ],
429
+ "forbiddenProps": [
430
+ "widget"
431
+ ]
432
+ },
433
+ "PivotComponent": {
434
+ "import": "@/pages/bi/designer/components/items/PivotComponent",
435
+ "component": "PivotComponent",
436
+ "requiredProps": [
437
+ "item"
438
+ ],
439
+ "optionalProps": [
440
+ "data",
441
+ "theme"
442
+ ],
443
+ "forbiddenProps": [
444
+ "widget"
445
+ ],
446
+ "notes": [
447
+ "tabela pivot para análise cruzada de dados"
448
+ ]
449
+ },
450
+ "ScatterComponent": {
451
+ "import": "@/pages/bi/designer/components/items/ScatterComponent",
452
+ "component": "ScatterComponent",
453
+ "requiredProps": [
454
+ "item"
455
+ ],
456
+ "optionalProps": [
457
+ "data",
458
+ "theme",
459
+ "onUpdate",
460
+ "isDesignMode",
461
+ "onCrossFilterTrigger"
462
+ ],
463
+ "forbiddenProps": [
464
+ "widget"
465
+ ]
466
+ },
467
+ "HeatmapComponent": {
468
+ "import": "@/pages/bi/designer/components/items/HeatmapComponent",
469
+ "component": "HeatmapComponent",
470
+ "requiredProps": [
471
+ "item"
472
+ ],
473
+ "optionalProps": [
474
+ "data",
475
+ "isDesignMode",
476
+ "theme"
477
+ ],
478
+ "forbiddenProps": [
479
+ "widget"
480
+ ]
481
+ },
482
+ "RadarComponent": {
483
+ "import": "@/pages/bi/designer/components/items/RadarComponent",
484
+ "component": "RadarComponent",
485
+ "requiredProps": [
486
+ "item"
487
+ ],
488
+ "optionalProps": [
489
+ "data",
490
+ "isDesignMode",
491
+ "theme"
492
+ ],
493
+ "forbiddenProps": [
494
+ "widget"
495
+ ]
496
+ },
497
+ "TreemapComponent": {
498
+ "import": "@/pages/bi/designer/components/items/TreemapComponent",
499
+ "component": "TreemapComponent",
500
+ "requiredProps": [
501
+ "item"
502
+ ],
503
+ "optionalProps": [
504
+ "data",
505
+ "isDesignMode",
506
+ "theme"
507
+ ],
508
+ "forbiddenProps": [
509
+ "widget"
510
+ ]
511
+ },
512
+ "BoxplotComponent": {
513
+ "import": "@/pages/bi/designer/components/items/BoxplotComponent",
514
+ "component": "BoxplotComponent",
515
+ "requiredProps": [
516
+ "item"
517
+ ],
518
+ "optionalProps": [
519
+ "data",
520
+ "isDesignMode",
521
+ "theme"
522
+ ],
523
+ "forbiddenProps": [
524
+ "widget"
525
+ ]
526
+ },
527
+ "CandlestickComponent": {
528
+ "import": "@/pages/bi/designer/components/items/CandlestickComponent",
529
+ "component": "CandlestickComponent",
530
+ "requiredProps": [
531
+ "item"
532
+ ],
533
+ "optionalProps": [
534
+ "data",
535
+ "isDesignMode",
536
+ "theme"
537
+ ],
538
+ "forbiddenProps": [
539
+ "widget"
540
+ ]
541
+ },
542
+ "SankeyComponent": {
543
+ "import": "@/pages/bi/designer/components/items/SankeyComponent",
544
+ "component": "SankeyComponent",
545
+ "requiredProps": [
546
+ "item"
547
+ ],
548
+ "optionalProps": [
549
+ "data",
550
+ "isDesignMode",
551
+ "theme"
552
+ ],
553
+ "forbiddenProps": [
554
+ "widget"
555
+ ]
556
+ },
557
+ "GraphComponent": {
558
+ "import": "@/pages/bi/designer/components/items/GraphComponent",
559
+ "component": "GraphComponent",
560
+ "requiredProps": [
561
+ "item"
562
+ ],
563
+ "optionalProps": [
564
+ "data",
565
+ "isDesignMode",
566
+ "theme"
567
+ ],
568
+ "forbiddenProps": [
569
+ "widget"
570
+ ]
571
+ },
572
+ "SunburstComponent": {
573
+ "import": "@/pages/bi/designer/components/items/SunburstComponent",
574
+ "component": "SunburstComponent",
575
+ "requiredProps": [
576
+ "item"
577
+ ],
578
+ "optionalProps": [
579
+ "data",
580
+ "isDesignMode",
581
+ "theme"
582
+ ],
583
+ "forbiddenProps": [
584
+ "widget"
585
+ ]
586
+ },
587
+ "TreeChartComponent": {
588
+ "import": "@/pages/bi/designer/components/items/TreeChartComponent",
589
+ "component": "TreeChartComponent",
590
+ "requiredProps": [
591
+ "item"
592
+ ],
593
+ "optionalProps": [
594
+ "data",
595
+ "isDesignMode",
596
+ "theme"
597
+ ],
598
+ "forbiddenProps": [
599
+ "widget"
600
+ ]
601
+ },
602
+ "ParallelComponent": {
603
+ "import": "@/pages/bi/designer/components/items/ParallelComponent",
604
+ "component": "ParallelComponent",
605
+ "requiredProps": [
606
+ "item"
607
+ ],
608
+ "optionalProps": [
609
+ "data",
610
+ "isDesignMode",
611
+ "theme"
612
+ ],
613
+ "forbiddenProps": [
614
+ "widget"
615
+ ]
616
+ },
617
+ "ThemeRiverComponent": {
618
+ "import": "@/pages/bi/designer/components/items/ThemeRiverComponent",
619
+ "component": "ThemeRiverComponent",
620
+ "requiredProps": [
621
+ "item"
622
+ ],
623
+ "optionalProps": [
624
+ "data",
625
+ "isDesignMode",
626
+ "theme"
627
+ ],
628
+ "forbiddenProps": [
629
+ "widget"
630
+ ]
631
+ },
632
+ "EffectScatterComponent": {
633
+ "import": "@/pages/bi/designer/components/items/EffectScatterComponent",
634
+ "component": "EffectScatterComponent",
635
+ "requiredProps": [
636
+ "item"
637
+ ],
638
+ "optionalProps": [
639
+ "data",
640
+ "isDesignMode",
641
+ "theme"
642
+ ],
643
+ "forbiddenProps": [
644
+ "widget"
645
+ ]
646
+ },
647
+ "PictorialBarComponent": {
648
+ "import": "@/pages/bi/designer/components/items/PictorialBarComponent",
649
+ "component": "PictorialBarComponent",
650
+ "requiredProps": [
651
+ "item"
652
+ ],
653
+ "optionalProps": [
654
+ "data",
655
+ "isDesignMode",
656
+ "theme"
657
+ ],
658
+ "forbiddenProps": [
659
+ "widget"
660
+ ]
661
+ },
662
+ "MapComponent": {
663
+ "import": "@/pages/bi/designer/components/items/MapComponent",
664
+ "component": "MapComponent",
665
+ "requiredProps": [
666
+ "item"
667
+ ],
668
+ "optionalProps": [
669
+ "data",
670
+ "isDesignMode",
671
+ "theme"
672
+ ],
673
+ "forbiddenProps": [
674
+ "widget"
675
+ ]
676
+ },
677
+ "FilledMapComponent": {
678
+ "import": "@/pages/bi/designer/components/items/FilledMapComponent",
679
+ "component": "FilledMapComponent",
680
+ "requiredProps": [
681
+ "item"
682
+ ],
683
+ "optionalProps": [
684
+ "data",
685
+ "isDesignMode",
686
+ "theme"
687
+ ],
688
+ "forbiddenProps": [
689
+ "widget"
690
+ ]
691
+ },
692
+ "LinesComponent": {
693
+ "import": "@/pages/bi/designer/components/items/LinesComponent",
694
+ "component": "LinesComponent",
695
+ "requiredProps": [
696
+ "item"
697
+ ],
698
+ "optionalProps": [
699
+ "data",
700
+ "isDesignMode",
701
+ "theme"
702
+ ],
703
+ "forbiddenProps": [
704
+ "widget"
705
+ ]
706
+ },
707
+ "TextComponent": {
708
+ "import": "@/pages/bi/designer/components/items/TextComponent",
709
+ "component": "TextComponent",
710
+ "requiredProps": [
711
+ "item"
712
+ ],
713
+ "optionalProps": [
714
+ "data",
715
+ "theme",
716
+ "isDesignMode"
717
+ ],
718
+ "forbiddenProps": [
719
+ "widget"
720
+ ]
721
+ },
722
+ "ImageComponent": {
723
+ "import": "@/pages/bi/designer/components/items/ImageComponent",
724
+ "component": "ImageComponent",
725
+ "requiredProps": [
726
+ "item"
727
+ ],
728
+ "optionalProps": [
729
+ "theme"
730
+ ],
731
+ "forbiddenProps": [
732
+ "widget"
733
+ ],
734
+ "notes": [
735
+ "não recebe data — é widget estático"
736
+ ]
737
+ },
738
+ "FilterComponent": {
739
+ "import": "@/pages/bi/designer/components/items/FilterComponent",
740
+ "component": "FilterComponent",
741
+ "requiredProps": [
742
+ "item"
743
+ ],
744
+ "optionalProps": [
745
+ "data",
746
+ "theme"
747
+ ],
748
+ "forbiddenProps": [
749
+ "widget"
750
+ ]
751
+ },
752
+ "DropdownComponent": {
753
+ "import": "@/pages/bi/designer/components/items/DropdownComponent",
754
+ "component": "DropdownComponent",
755
+ "requiredProps": [
756
+ "item"
757
+ ],
758
+ "optionalProps": [
759
+ "data",
760
+ "isDesignMode",
761
+ "onFilterChange",
762
+ "theme"
763
+ ],
764
+ "forbiddenProps": [
765
+ "widget"
766
+ ]
767
+ },
768
+ "TimelineComponent": {
769
+ "import": "@/pages/bi/designer/components/items/TimelineComponent",
770
+ "component": "TimelineComponent",
771
+ "requiredProps": [
772
+ "item"
773
+ ],
774
+ "optionalProps": [
775
+ "data",
776
+ "isDesignMode",
777
+ "theme"
778
+ ],
779
+ "forbiddenProps": [
780
+ "widget"
781
+ ]
782
+ },
783
+ "ProgressListComponent": {
784
+ "import": "@/pages/bi/designer/components/items/ProgressListComponent",
785
+ "component": "ProgressListComponent",
786
+ "requiredProps": [
787
+ "item"
788
+ ],
789
+ "optionalProps": [
790
+ "data",
791
+ "isDesignMode",
792
+ "theme"
793
+ ],
794
+ "forbiddenProps": [
795
+ "widget"
796
+ ]
797
+ },
798
+ "GroupComponent": {
799
+ "import": "@/pages/bi/designer/components/items/GroupComponent",
800
+ "component": "GroupComponent",
801
+ "requiredProps": [
802
+ "item"
803
+ ],
804
+ "optionalProps": [
805
+ "data",
806
+ "onUpdate",
807
+ "isDesignMode",
808
+ "dataSources",
809
+ "allItems",
810
+ "onItemUpdate",
811
+ "onItemDelete",
812
+ "onItemSelect",
813
+ "selectedItem",
814
+ "viewMode",
815
+ "getAggregatedData",
816
+ "theme"
817
+ ],
818
+ "forbiddenProps": [
819
+ "widget"
820
+ ],
821
+ "notes": [
822
+ "container que agrupa widgets filhos",
823
+ "viewMode aceita 'design' | 'preview'"
824
+ ]
825
+ },
826
+ "DataGrid": {
827
+ "import": "@/components/DataGrid",
828
+ "component": "DataGrid",
829
+ "requiredProps": [
830
+ "data"
831
+ ],
832
+ "recommendedProps": [
833
+ "title",
834
+ "loading",
835
+ "error",
836
+ "pageSize",
837
+ "enableSearch",
838
+ "enableFilters",
839
+ "enableExport",
840
+ "enablePagination",
841
+ "enableSort",
842
+ "customColumns",
843
+ "columnLabels",
844
+ "defaultVisibleColumns",
845
+ "defaultSortColumn",
846
+ "defaultSortDirection",
847
+ "rowIdField"
848
+ ],
849
+ "llmContract": {
850
+ "requiredProps": [
851
+ "columns",
852
+ "data"
853
+ ],
854
+ "columnShape": [
855
+ "field",
856
+ "header",
857
+ "width"
858
+ ],
859
+ "forbiddenProps": [
860
+ "widget"
861
+ ]
862
+ },
863
+ "sourceProps": [
864
+ "data",
865
+ "loading",
866
+ "error",
867
+ "title",
868
+ "subtitle",
869
+ "onRefresh",
870
+ "enableFilters",
871
+ "enableSearch",
872
+ "searchPlaceholder",
873
+ "enableExport",
874
+ "enablePagination",
875
+ "enableSort",
876
+ "enableColumnResize",
877
+ "enableColumnReorder",
878
+ "enableAggregation",
879
+ "enableFullscreen",
880
+ "enableColumnSettings",
881
+ "theme",
882
+ "enableHeader",
883
+ "fullWidthColumns",
884
+ "pageSize",
885
+ "totalRows",
886
+ "currentPage",
887
+ "onPageChange",
888
+ "onPageSizeChange",
889
+ "customColumns",
890
+ "columnLabels",
891
+ "columnAliases",
892
+ "defaultVisibleColumns",
893
+ "defaultSortColumn",
894
+ "defaultSortDirection",
895
+ "canNextPage",
896
+ "canPreviousPage",
897
+ "enableAdd",
898
+ "onAdd",
899
+ "addButtonText",
900
+ "onRowClick",
901
+ "enableEditing",
902
+ "rowIdField",
903
+ "onEditsChange",
904
+ "columnIcons",
905
+ "columnAggregationDefaults",
906
+ "defaultColumnWidths"
907
+ ],
908
+ "notes": [
909
+ "o system prompt exige columns+data para geração TSX",
910
+ "o componente fonte atual expõe data e props de configuração de colunas",
911
+ "nunca usar widget"
912
+ ]
913
+ },
914
+ "DataGridV2": {
915
+ "import": "@/components/DataGridV2",
916
+ "component": "DataGridV2",
917
+ "requiredProps": [
918
+ "data",
919
+ "columns",
920
+ "rowKey"
921
+ ],
922
+ "optionalProps": [
923
+ "loading",
924
+ "loadingMessage",
925
+ "emptyMessage",
926
+ "onRowClick",
927
+ "rowClassName",
928
+ "footer",
929
+ "pagination",
930
+ "sortDescriptor",
931
+ "onSortChange",
932
+ "initialSort"
933
+ ],
934
+ "columnShape": {
935
+ "type": "DataGridV2Column<T>",
936
+ "required": [
937
+ "id",
938
+ "header"
939
+ ],
940
+ "optional": [
941
+ "render",
942
+ "accessor",
943
+ "transform",
944
+ "formatOptions",
945
+ "inferFormat",
946
+ "headerClassName",
947
+ "cellClassName",
948
+ "sortable",
949
+ "width",
950
+ "minWidth"
951
+ ]
952
+ },
953
+ "paginationShape": {
954
+ "type": "DataGridV2Pagination",
955
+ "fields": [
956
+ "currentPage",
957
+ "totalPages",
958
+ "totalRecords",
959
+ "pageSize",
960
+ "onPageChange"
961
+ ]
962
+ },
963
+ "notes": [
964
+ "grid v2 com tipagem genérica <T>",
965
+ "rowKey é função (row, index) => string",
966
+ "columns usa accessor + formatOptions ou render customizado",
967
+ "preferir DataGrid (v1) para uso genérico; DataGridV2 para grids fortemente tipados"
968
+ ]
969
+ },
970
+ "WidgetDate": {
971
+ "import": "@/components/widgets/WidgetDate",
972
+ "typeImport": "@/components/widgets/WidgetDate#DatePeriod",
973
+ "component": "WidgetDate",
974
+ "canonical": true,
975
+ "preferredImportPattern": "import WidgetDate, { type DatePeriod } from '@/components/widgets/WidgetDate'",
976
+ "llmDirective": "Sempre use este WidgetDate como seletor de período padrão do WiBi quando a página precisar de filtro temporal.",
977
+ "requiredProps": [],
978
+ "recommendedProps": [
979
+ "value",
980
+ "onChange",
981
+ "className"
982
+ ],
983
+ "valueShape": {
984
+ "type": "DatePeriod",
985
+ "fields": [
986
+ "type",
987
+ "startDate",
988
+ "endDate"
989
+ ],
990
+ "periodTypes": [
991
+ "SP",
992
+ "D",
993
+ "S",
994
+ "M",
995
+ "T",
996
+ "SE",
997
+ "A",
998
+ "CUSTOM"
999
+ ]
1000
+ },
1001
+ "notes": [
1002
+ "este é o WidgetDate canônico do projeto WiBi",
1003
+ "usado para filtro de período",
1004
+ "onChange retorna DatePeriod",
1005
+ "preferir exatamente o import '@/components/widgets/WidgetDate'",
1006
+ "seguir o padrão usado em HomeFinanceiro.tsx e DashboardVendas01.tsx"
1007
+ ]
1008
+ },
1009
+ "WidgetEmpresas": {
1010
+ "import": "@/components/widgets/WidgetEmpresas",
1011
+ "component": "WidgetEmpresas",
1012
+ "requiredProps": [
1013
+ "onChange"
1014
+ ],
1015
+ "recommendedProps": [
1016
+ "value",
1017
+ "placeholder",
1018
+ "showIcon",
1019
+ "className",
1020
+ "disabled",
1021
+ "autoSelectFirst"
1022
+ ],
1023
+ "valueShape": {
1024
+ "type": "number|string|array|null"
1025
+ },
1026
+ "notes": [
1027
+ "usado para filtro de empresa",
1028
+ "onChange recebe empresaId:number"
1029
+ ]
1030
+ },
1031
+ "WidgetTipos": {
1032
+ "import": "@/components/widgets/WidgetTipos",
1033
+ "component": "WidgetTipos",
1034
+ "requiredProps": [
1035
+ "tgId",
1036
+ "onChange"
1037
+ ],
1038
+ "optionalProps": [
1039
+ "value",
1040
+ "placeholder",
1041
+ "showIcon",
1042
+ "className",
1043
+ "disabled",
1044
+ "autoSelectFirst",
1045
+ "reloadKey"
1046
+ ],
1047
+ "notes": [
1048
+ "seletor de tipos genérico (ex: tipo de pagamento, tipo de documento)",
1049
+ "tgId identifica o grupo de tipos no banco",
1050
+ "onChange recebe tipoId:number"
1051
+ ]
1052
+ },
1053
+ "WidgetCaixas": {
1054
+ "import": "@/components/widgets/WidgetCaixas",
1055
+ "component": "WidgetCaixas",
1056
+ "requiredProps": [
1057
+ "emCodigo",
1058
+ "onChange"
1059
+ ],
1060
+ "optionalProps": [
1061
+ "value",
1062
+ "placeholder",
1063
+ "showIcon",
1064
+ "className",
1065
+ "disabled",
1066
+ "autoSelectFirst",
1067
+ "onSelect"
1068
+ ],
1069
+ "valueShape": {
1070
+ "type": "number",
1071
+ "description": "cxId do caixa selecionado"
1072
+ },
1073
+ "onSelectShape": {
1074
+ "type": "Caixa | null",
1075
+ "fields": [
1076
+ "cxId",
1077
+ "cxData",
1078
+ "cxHora",
1079
+ "usCodigo",
1080
+ "cxFechado",
1081
+ "cxDataFinal",
1082
+ "emCodigo",
1083
+ "cxCaixaConf",
1084
+ "cxBancoConf",
1085
+ "cxHoraFinal",
1086
+ "dataHora"
1087
+ ]
1088
+ },
1089
+ "notes": [
1090
+ "seletor de caixas financeiros por empresa",
1091
+ "emCodigo filtra caixas da empresa selecionada",
1092
+ "onChange recebe caixaId:number",
1093
+ "onSelect recebe o objeto Caixa completo ou null"
1094
+ ]
1095
+ }
1096
+ },
1097
+ "dashboardItemType": {
1098
+ "description": "Tipo universal usado por todos os componentes de widget no Designer",
1099
+ "type": "DashboardItem",
1100
+ "import": "@/pages/bi/designer/types",
1101
+ "fields": {
1102
+ "id": { "type": "string", "required": true },
1103
+ "type": { "type": "string", "required": true, "values": [
1104
+ "chart", "grid", "table", "card", "filter", "text", "image", "line", "pie", "gauge", "pivot", "map",
1105
+ "area", "scatter", "treemap", "multi-card", "kpi", "sparkline", "funnel", "waterfall",
1106
+ "filled-map", "dropdown", "timeline", "group",
1107
+ "radar", "heatmap", "candlestick", "boxplot", "sankey", "graph", "sunburst", "tree",
1108
+ "parallel", "themeriver", "effectScatter", "pictorialBar", "lines", "progress-list",
1109
+ "date", "companies"
1110
+ ]},
1111
+ "position": { "type": "{ x: number; y: number }", "required": true },
1112
+ "size": { "type": "{ width: number; height: number }", "required": true },
1113
+ "title": { "type": "string", "required": false },
1114
+ "dataSource": { "type": "string | null", "required": false },
1115
+ "properties": { "type": "Record<string, any>", "required": false },
1116
+ "zIndex": { "type": "number", "required": false },
1117
+ "locked": { "type": "boolean", "required": false },
1118
+ "children": { "type": "DashboardItem[]", "required": false, "description": "Para widget Group — widgets filhos" },
1119
+ "category": { "type": "'basic' | 'advanced' | 'hierarchical' | 'data' | 'specialized'", "required": false },
1120
+ "widgetFields": { "type": "any[]", "required": false, "description": "Campos configurados do widget (para WidgetFactoryService)" },
1121
+ "customSQL": { "type": "string", "required": false, "description": "SQL customizado da LLM (substitui WidgetSQLBuilder)" }
1122
+ }
1123
+ },
1124
+ "designSystemPatterns": {
1125
+ "canonicalWidgets": {
1126
+ "periodFilter": {
1127
+ "component": "WidgetDate",
1128
+ "import": "@/components/widgets/WidgetDate",
1129
+ "directive": "Quando houver filtro temporal, use WidgetDate como componente padrão."
1130
+ },
1131
+ "empresaFilter": {
1132
+ "component": "WidgetEmpresas",
1133
+ "import": "@/components/widgets/WidgetEmpresas",
1134
+ "directive": "Quando houver filtro de empresa, use WidgetEmpresas como componente padrão."
1135
+ },
1136
+ "tiposFilter": {
1137
+ "component": "WidgetTipos",
1138
+ "import": "@/components/widgets/WidgetTipos",
1139
+ "directive": "Quando houver filtro de tipo genérico (pagamento, documento, etc), use WidgetTipos."
1140
+ },
1141
+ "caixasFilter": {
1142
+ "component": "WidgetCaixas",
1143
+ "import": "@/components/widgets/WidgetCaixas",
1144
+ "directive": "Quando houver filtro de caixa financeiro, use WidgetCaixas."
1145
+ }
1146
+ },
1147
+ "pageLayout": {
1148
+ "sources": [
1149
+ "wibi/src/pages/home/HomeFinanceiro.tsx",
1150
+ "wibi/src/pages/bi/comercial/DashboardVendas01.tsx",
1151
+ "wibi/src/pages/bi/EChartsPlayground.tsx"
1152
+ ],
1153
+ "rules": [
1154
+ "usar container raiz com w-full h-full flex flex-col",
1155
+ "usar header fixo com bg-bg-primary border-b border-border px-4 py-3",
1156
+ "usar área de conteúdo com overflow-auto e espaçamento p-3 ou p-4",
1157
+ "organizar blocos em cards com bg-bg-primary ou bg-bg-secondary border border-border rounded-lg",
1158
+ "usar títulos com text-sm ou text-base font-semibold text-text-primary",
1159
+ "usar textos de apoio com text-xs ou text-[10px] text-text-secondary/text-text-muted",
1160
+ "usar grids responsivos com gap-2, gap-3 ou gap-4",
1161
+ "usar ícones lucide com cores semânticas como text-accent-primary, text-accent-success, text-accent-warning e text-accent-danger"
1162
+ ]
1163
+ },
1164
+ "kpiCards": {
1165
+ "rules": [
1166
+ "usar cards compactos com rounded-lg border border-border p-3",
1167
+ "mostrar título pequeno, valor em destaque e texto auxiliar curto",
1168
+ "usar realce semântico de cor somente quando houver contexto de alerta ou destaque"
1169
+ ]
1170
+ },
1171
+ "chartsAndTables": {
1172
+ "rules": [
1173
+ "combinar DataGrid e EChartsChart em grids de 1 ou 2 colunas",
1174
+ "usar alturas definidas como h-[240px], h-[280px], h-[320px], h-[430px], h-[450px] ou h-[500px] conforme a densidade",
1175
+ "REGRA ABSOLUTA: cada chart ou grid é um widget INDEPENDENTE na section — NUNCA embrulhar dois ou mais charts em um group/container/div com título",
1176
+ "PROIBIDO: criar uma section ou group chamado 'Evolução Temporal', 'Análise', 'Gráficos' etc. para conter múltiplos charts — cada chart tem sua própria section ou aparece diretamente como widget isolado",
1177
+ "quando precisar de título para um chart, use a propriedade title dentro de properties do próprio widget chart, ou um widget heading/text separado na mesma section ANTES do chart",
1178
+ "NUNCA usar group como container de charts — group só existe para composição explicitamente solicitada pelo usuário"
1179
+ ]
1180
+ },
1181
+ "sectionGroupTitles": {
1182
+ "source": "wibi/src/pages/home/HomeComercial.tsx",
1183
+ "description": "Padrão canônico de bloco composto — APENAS para combinar ProgressList + Chart ou Grid + Chart lado a lado dentro de um mesmo card visual. NUNCA usar para embrulhar charts individuais.",
1184
+ "llm_instruction": "ATENÇÃO: este padrão é EXCLUSIVO para blocos compostos que combinam ProgressList + Chart ou Grid + Chart lado a lado (ex: Top Fornecedores lista + pizza). Para charts individuais (bar, line, area, pie sozinhos) NÃO use este padrão — declare o widget diretamente em widgets[] com title em properties.title. No dashboard.serialized.json, um chart por si só NUNCA vai dentro de um container com título. Dois charts side-by-side = dois widgets separados na mesma section, cada um com seu col_span.",
1185
+ "cardContainer": {
1186
+ "className": "bg-bg-primary border border-border rounded-lg p-3",
1187
+ "description": "Card visual opcional para bloco composto. Nao usar como wrapper generico por widget isolado."
1188
+ },
1189
+ "groupHeader": {
1190
+ "className": "flex items-center justify-between mb-3",
1191
+ "title": {
1192
+ "tag": "h2",
1193
+ "className": "text-xs font-semibold text-text-primary flex items-center gap-1.5",
1194
+ "icon": {
1195
+ "className": "w-3.5 h-3.5 text-accent-primary",
1196
+ "source": "lucide-react",
1197
+ "examples": ["BarChart3", "Users", "Package", "Target", "TrendingUp", "ShoppingCart", "DollarSign", "Activity"]
1198
+ }
1199
+ }
1200
+ },
1201
+ "contentGrid": {
1202
+ "description": "Grid interno para combinar ProgressList + Chart ou Grid + Chart lado a lado",
1203
+ "className": "grid grid-cols-1 lg:grid-cols-2 gap-4 h-[260px]",
1204
+ "variants": {
1205
+ "tall": "h-[320px]",
1206
+ "medium": "h-[260px]",
1207
+ "short": "h-[200px]"
1208
+ },
1209
+ "innerList": "overflow-auto",
1210
+ "innerChart": "h-full"
1211
+ },
1212
+ "realExamples": [
1213
+ {
1214
+ "title": "Faturamento {ano} — Mês a Mês",
1215
+ "icon": "BarChart3",
1216
+ "layout": "lg:col-span-2 (2/3 width) + col simples (1/3 width) para Top 8 Clientes",
1217
+ "outerGrid": "grid grid-cols-1 lg:grid-cols-3 gap-4",
1218
+ "content": "EChartsChart (bar) + ProgressListComponent"
1219
+ },
1220
+ {
1221
+ "title": "Performance de Vendedores",
1222
+ "icon": "Users",
1223
+ "layout": "2 colunas iguais dentro do card: ProgressList à esquerda, pie chart à direita",
1224
+ "innerGrid": "grid grid-cols-1 lg:grid-cols-2 gap-4 h-[260px]",
1225
+ "content": "ProgressListComponent + EChartsChart (pie)"
1226
+ },
1227
+ {
1228
+ "title": "Top 10 Produtos",
1229
+ "icon": "Package",
1230
+ "layout": "2 colunas iguais: ProgressList à esquerda, barras horizontais à direita",
1231
+ "innerGrid": "grid grid-cols-1 lg:grid-cols-2 gap-4 h-[260px]",
1232
+ "content": "ProgressListComponent + EChartsChart (horizontal_bar)"
1233
+ },
1234
+ {
1235
+ "title": "Indicadores de Saúde Comercial",
1236
+ "icon": "Target",
1237
+ "layout": "grid de 5 cards compactos (2 cols mobile, 3 cols tablet, 5 cols desktop)",
1238
+ "innerGrid": "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-2",
1239
+ "content": "CardComponent (compact=true) com cores semânticas por threshold"
1240
+ }
1241
+ ],
1242
+ "codePattern": {
1243
+ "description": "Template de JSX para um bloco composto com titulo + chart/list combo. Nao aplicar este padrao a widget unico.",
1244
+ "jsx": "<div className=\"bg-bg-primary border border-border rounded-lg p-3\"><div className=\"flex items-center justify-between mb-3\"><h2 className=\"text-xs font-semibold text-text-primary flex items-center gap-1.5\"><{Icon} className=\"w-3.5 h-3.5 text-accent-primary\" />{Título do Grupo}</h2></div><div className=\"grid grid-cols-1 lg:grid-cols-2 gap-4 h-[260px]\"><div className=\"overflow-auto\">{/* ProgressListComponent ou GridComponent */}</div><div className=\"h-full\">{/* EChartsChart */}</div></div></div>"
1245
+ },
1246
+ "kpiRowPattern": {
1247
+ "description": "Linha de KPIs compactos — padrão da faixa superior e dos indicadores de saúde",
1248
+ "kpiRow": "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-2",
1249
+ "kpiItem": "bg-bg-secondary border border-border rounded-lg p-1.5",
1250
+ "saúdeRow": "grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-5 gap-2",
1251
+ "jsx": "<div className=\"grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-2\"><div className=\"bg-bg-secondary border border-border rounded-lg p-1.5\"><CardComponent item={cardItem} data={[{...}]} theme={theme} /></div></div>"
1252
+ }
1253
+ }
1254
+ },
1255
+ "widgets": {
1256
+ "chart": {
1257
+ "name": "Gráfico (ECharts)",
1258
+ "category": "basic",
1259
+ "description": "Componente unificado de gráficos ECharts. Use chart_type para definir o tipo visual: bar, line, area, pie, donut, horizontal_bar, stacked_bar. Todas as propriedades são passadas via properties{} no JSON serializado usando snake_case.",
1260
+ "icon": "📊",
1261
+ "render": "EChartsChart",
1262
+ "defaultSize": { "width": 720, "height": 480 },
1263
+ "default_widget_height": 400,
1264
+ "llm_instruction": "No dashboard.serialized.json, use widget_type='chart' e defina chart_type dentro de properties. SEMPRE defina height no widget chart — o valor padrão recomendado é 400 (ex: { \"height\": 400 }). Para charts que precisam de mais espaço (muitos dados, labels longos, horizontal_bar) use height: 450 ou 500. NUNCA omita height num widget chart — sem ele o gráfico fica pequeno. As cores do gráfico vêm automaticamente da paleta do tema (azul, verde, laranja, vermelho, roxo, ciano, rosa, índigo). Para barras com COR DIFERENTE POR BARRA, use alternate_colors=true. NÃO invente propriedades como color_palette, colors, color_list — elas NÃO existem. A paleta de cores é fixa e gerenciada pelo tema. NUNCA gere enable_zoom: true salvo pedido EXPLÍCITO do usuário. Para rotacionar labels do eixo X use x_axis_label_rotate (número de graus, ex: 45 ou 90) em vez de rotate_labels. Para formatar datas no eixo X use x_axis_date_format com tokens: dd=dia, MM=mês numérico, yyyy/yy=ano, MMMM=mês por extenso, MMM=mês abreviado (ex: 'MMMM/yy' → Março/25, 'MMM/yy' → Mar/25, 'dd/MM/yyyy' → 01/03/2025).",
1265
+ "propertiesDetailed": {
1266
+ "chart_type": {
1267
+ "type": "string",
1268
+ "required": true,
1269
+ "values": ["bar", "line", "area", "pie", "donut", "horizontal_bar", "stacked_bar"],
1270
+ "default": "bar",
1271
+ "description": "Tipo visual do gráfico. 'bar'=barras verticais, 'line'=linhas, 'area'=área preenchida, 'pie'=pizza, 'donut'=rosca (pie com innerRadius), 'horizontal_bar'=barras horizontais, 'stacked_bar'=barras empilhadas."
1272
+ },
1273
+ "x_field": {
1274
+ "type": "string",
1275
+ "required": true,
1276
+ "description": "Nome do campo nos dados que será usado como eixo X (categorias). Ex: 'mes', 'nomeVendedor'."
1277
+ },
1278
+ "y_field": {
1279
+ "type": "string",
1280
+ "required": false,
1281
+ "description": "Campo de valor do eixo Y (quando há apenas uma série). Alternativa a y_fields."
1282
+ },
1283
+ "y_fields": {
1284
+ "type": "string[]",
1285
+ "required": false,
1286
+ "description": "Array de campos de valor para o eixo Y. Usar quando há múltiplas séries. Ex: ['faturamento', 'custos']."
1287
+ },
1288
+ "group_by_field": {
1289
+ "type": "string",
1290
+ "required": false,
1291
+ "description": "Campo para agrupar os dados em séries automáticas. Ex: group_by_field='regiao' cria uma série para cada região."
1292
+ },
1293
+ "aggregation": {
1294
+ "type": "string",
1295
+ "required": false,
1296
+ "values": ["sum", "avg", "count", "min", "max", "first", "last"],
1297
+ "default": "sum",
1298
+ "description": "Tipo de agregação quando há duplicatas no x_field."
1299
+ },
1300
+ "top_n": {
1301
+ "type": "number",
1302
+ "required": false,
1303
+ "description": "Limitar aos top N registros. Os demais são descartados."
1304
+ },
1305
+ "sort_order": {
1306
+ "type": "string",
1307
+ "required": false,
1308
+ "values": ["asc", "desc"],
1309
+ "default": "desc",
1310
+ "description": "Ordenação dos dados: ascendente ou descendente."
1311
+ },
1312
+ "alternate_colors": {
1313
+ "type": "boolean",
1314
+ "required": false,
1315
+ "default": false,
1316
+ "description": "IMPORTANTE: Quando true, cada barra/fatia recebe uma cor diferente da paleta do tema (azul, verde, laranja, vermelho, roxo...). Quando false (padrão), todas as barras de uma mesma série têm a mesma cor. Use true para rankings, top N, comparações entre categorias."
1317
+ },
1318
+ "orientation": {
1319
+ "type": "string",
1320
+ "required": false,
1321
+ "values": ["vertical", "horizontal"],
1322
+ "default": "vertical",
1323
+ "description": "Orientação do gráfico de barras. 'horizontal' inverte os eixos. Alternativa a usar chart_type='horizontal_bar'."
1324
+ },
1325
+ "bar_width": {
1326
+ "type": "number",
1327
+ "required": false,
1328
+ "default": 60,
1329
+ "description": "Largura máxima das barras em porcentagem (1-100). Ex: 60 = barras ocupam 60% do espaço."
1330
+ },
1331
+ "show_data_labels": {
1332
+ "type": "boolean",
1333
+ "required": false,
1334
+ "default": false,
1335
+ "description": "Exibir rótulos com valores em cima de cada barra/ponto/fatia."
1336
+ },
1337
+ "show_legend": {
1338
+ "type": "boolean",
1339
+ "required": false,
1340
+ "default": true,
1341
+ "description": "Exibir legenda do gráfico. Útil desabilitar quando há apenas uma série."
1342
+ },
1343
+ "enable_zoom": {
1344
+ "type": "boolean",
1345
+ "required": false,
1346
+ "default": false,
1347
+ "llm_rule": "NUNCA gere enable_zoom: true salvo quando o usuário pedir EXPLICITAMENTE zoom ou rolagem no gráfico.",
1348
+ "description": "Habilitar zoom interativo (dataZoom) no gráfico. Padrão: false. Só usar se o usuário pedir explicitamente."
1349
+ },
1350
+ "rotate_labels": {
1351
+ "type": "boolean",
1352
+ "required": false,
1353
+ "default": false,
1354
+ "deprecated": "Use x_axis_label_rotate com valor numérico de graus.",
1355
+ "description": "Rotacionar labels do eixo X em 45 graus. Deprecated — prefira x_axis_label_rotate."
1356
+ },
1357
+ "x_axis_label_rotate": {
1358
+ "type": "number",
1359
+ "required": false,
1360
+ "default": 0,
1361
+ "description": "Ângulo de rotação dos labels do eixo X em graus (ex: 45, 90, -45). Use quando o usuário pedir labels inclinados ou verticais."
1362
+ },
1363
+ "x_axis_date_format": {
1364
+ "type": "string",
1365
+ "required": false,
1366
+ "values": ["dd/MM/yyyy", "dd/MM/yy", "MM/yyyy", "MM/yy", "MMMM/yy", "MMM/yy", "yyyy-MM-dd"],
1367
+ "description": "Formato de exibição das datas no eixo X. Tokens: dd=dia, MM=mês numérico, yyyy=ano 4 dígitos, yy=ano 2 dígitos, MMMM=mês por extenso (ex: Março), MMM=mês abreviado (ex: Mar). Exemplos: 'dd/MM/yyyy' → 01/03/2025 | 'MMMM/yy' → Março/25 | 'MMM/yy' → Mar/25 | 'MM/yyyy' → 03/2025."
1368
+ },
1369
+ "smooth": {
1370
+ "type": "boolean",
1371
+ "required": false,
1372
+ "default": false,
1373
+ "description": "Suavizar linhas (para chart_type='line' ou 'area'). Curvas ao invés de retas."
1374
+ },
1375
+ "show_symbol": {
1376
+ "type": "boolean",
1377
+ "required": false,
1378
+ "default": true,
1379
+ "description": "Mostrar pontos/símbolos nos vértices das linhas."
1380
+ },
1381
+ "symbol_size": {
1382
+ "type": "number",
1383
+ "required": false,
1384
+ "default": 6,
1385
+ "description": "Tamanho dos símbolos/pontos nas linhas."
1386
+ },
1387
+ "line_style": {
1388
+ "type": "string",
1389
+ "required": false,
1390
+ "values": ["solid", "dashed", "dotted"],
1391
+ "default": "solid",
1392
+ "description": "Estilo da linha (para chart_type='line')."
1393
+ },
1394
+ "area_opacity": {
1395
+ "type": "number",
1396
+ "required": false,
1397
+ "default": 0.5,
1398
+ "description": "Opacidade do preenchimento da área (0 a 1). Para chart_type='area'."
1399
+ },
1400
+ "gradient": {
1401
+ "type": "boolean",
1402
+ "required": false,
1403
+ "default": true,
1404
+ "description": "Usar gradiente no preenchimento da área. Para chart_type='area'."
1405
+ },
1406
+ "radius": {
1407
+ "type": "number",
1408
+ "required": false,
1409
+ "default": 75,
1410
+ "description": "Raio externo da pizza/donut em porcentagem. Para chart_type='pie' ou 'donut'."
1411
+ },
1412
+ "inner_radius": {
1413
+ "type": "number",
1414
+ "required": false,
1415
+ "default": 0,
1416
+ "description": "Raio interno (furo) da rosca em porcentagem. Usar > 0 para criar donut. Ex: 40."
1417
+ },
1418
+ "rose_type": {
1419
+ "type": "string|boolean",
1420
+ "required": false,
1421
+ "values": ["radius", "area", "none", false],
1422
+ "default": false,
1423
+ "description": "Tipo rose (raios diferentes por valor). 'radius'=raio proporcional, 'area'=área proporcional, false=pizza normal."
1424
+ },
1425
+ "start_angle": {
1426
+ "type": "number",
1427
+ "required": false,
1428
+ "default": 90,
1429
+ "description": "Ângulo inicial da pizza em graus."
1430
+ },
1431
+ "min_angle": {
1432
+ "type": "number",
1433
+ "required": false,
1434
+ "default": 0,
1435
+ "description": "Ângulo mínimo de cada fatia (evita fatias invisíveis)."
1436
+ },
1437
+ "show_percentage": {
1438
+ "type": "boolean",
1439
+ "required": false,
1440
+ "default": true,
1441
+ "description": "Exibir porcentagem nos labels da pizza."
1442
+ },
1443
+ "label_position": {
1444
+ "type": "string",
1445
+ "required": false,
1446
+ "values": ["outside", "inside", "center"],
1447
+ "default": "outside",
1448
+ "description": "Posição dos labels na pizza."
1449
+ },
1450
+ "max_categories": {
1451
+ "type": "number",
1452
+ "required": false,
1453
+ "default": 10,
1454
+ "description": "Máximo de categorias na pizza. Excedentes são agrupados."
1455
+ },
1456
+ "sort_by": {
1457
+ "type": "string",
1458
+ "required": false,
1459
+ "values": ["value", "name"],
1460
+ "default": "value",
1461
+ "description": "Critério de ordenação para pizza."
1462
+ },
1463
+ "title": {
1464
+ "type": "string",
1465
+ "required": false,
1466
+ "description": "Título exibido no widget."
1467
+ },
1468
+ "description": {
1469
+ "type": "string",
1470
+ "required": false,
1471
+ "description": "Descrição curta abaixo do título."
1472
+ },
1473
+ "empty_state": {
1474
+ "type": "string",
1475
+ "required": false,
1476
+ "default": "Sem dados",
1477
+ "description": "Texto quando não há dados para exibir."
1478
+ }
1479
+ },
1480
+ "forbiddenProperties": [
1481
+ "color_palette",
1482
+ "colors",
1483
+ "color_list",
1484
+ "custom_colors",
1485
+ "series_colors",
1486
+ "bar_colors"
1487
+ ],
1488
+ "dataFields": ["xField", "yFields", "aggregation"],
1489
+ "notes": [
1490
+ "As cores são gerenciadas automaticamente pelo tema. A paleta padrão é: #3b82f6 (azul), #10b981 (verde), #f59e0b (laranja), #ef4444 (vermelho), #8b5cf6 (roxo), #06b6d4 (ciano), #ec4899 (rosa), #6366f1 (índigo).",
1491
+ "Para barras com cores alternadas (cada barra uma cor), use alternate_colors: true.",
1492
+ "NÃO existe propriedade color_palette, colors, ou similar. Não inventar propriedades de cores.",
1493
+ "No JSON serializado, usar snake_case: chart_type, x_field, y_fields, show_data_labels, alternate_colors, etc.",
1494
+ "O renderer converte snake_case para camelCase internamente."
1495
+ ]
1496
+ },
1497
+ "line": {
1498
+ "name": "Gráfico de Linhas",
1499
+ "category": "basic",
1500
+ "description": "Gráfico de linhas para tendências. Usa o mesmo componente EChartsChart com chart_type='line'.",
1501
+ "icon": "📈",
1502
+ "render": "EChartsChart",
1503
+ "defaultSize": { "width": 720, "height": 480 },
1504
+ "llm_instruction": "Para gráfico de linhas, use widget_type='chart' com chart_type='line' dentro de properties. NÃO use widget_type='line'.",
1505
+ "propertiesDetailed": "Mesmas propriedades de 'chart'. Propriedades específicas de linhas: smooth, show_symbol, symbol_size, line_style.",
1506
+ "dataFields": ["xField", "yFields", "aggregation"]
1507
+ },
1508
+ "area": {
1509
+ "name": "Gráfico de Área",
1510
+ "category": "basic",
1511
+ "description": "Gráfico de área para visualizar volume/magnitude. Usa o mesmo componente EChartsChart com chart_type='area'.",
1512
+ "icon": "📉",
1513
+ "render": "EChartsChart",
1514
+ "defaultSize": { "width": 720, "height": 480 },
1515
+ "llm_instruction": "Para gráfico de área, use widget_type='chart' com chart_type='area' dentro de properties. NÃO use widget_type='area'.",
1516
+ "propertiesDetailed": "Mesmas propriedades de 'chart'. Propriedades específicas de área: area_opacity, smooth, gradient.",
1517
+ "dataFields": ["xField", "yFields", "aggregation"]
1518
+ },
1519
+ "pie": {
1520
+ "name": "Gráfico de Pizza",
1521
+ "category": "basic",
1522
+ "description": "Gráfico de pizza ou rosca para visualizar proporções. Usa o mesmo componente EChartsChart com chart_type='pie'.",
1523
+ "icon": "🥧",
1524
+ "render": "EChartsChart",
1525
+ "defaultSize": { "width": 720, "height": 480 },
1526
+ "llm_instruction": "Para pizza, use widget_type='chart' com chart_type='pie'. Para donut, use chart_type='pie' com inner_radius > 0 (ex: 40). NÃO use widget_type='pie'.",
1527
+ "propertiesDetailed": "Mesmas propriedades de 'chart'. Propriedades específicas de pizza: radius, inner_radius, rose_type, start_angle, min_angle, show_percentage, label_position, max_categories, sort_by, sort_order.",
1528
+ "dataFields": ["categoryField", "valueField", "aggregation"]
1529
+ },
1530
+ "scatter": {
1531
+ "name": "Dispersão",
1532
+ "category": "advanced",
1533
+ "description": "Gráfico de dispersão para correlação entre dois campos numéricos.",
1534
+ "icon": "⚫",
1535
+ "render": "ScatterComponent",
1536
+ "defaultSize": { "width": 720, "height": 480 },
1537
+ "llm_instruction": "Use widget_type='scatter' para mostrar correlação entre dois campos numéricos. Defina x_field e y_field. Opcional: size_field para bolhas, color_field para colorir por categoria.",
1538
+ "propertiesDetailed": {
1539
+ "x_field": { "type": "string", "required": true, "description": "Campo do eixo X (numérico)." },
1540
+ "y_field": { "type": "string", "required": true, "description": "Campo do eixo Y (numérico)." },
1541
+ "size_field": { "type": "string", "required": false, "description": "Campo para variar o tamanho dos pontos (bubble chart)." },
1542
+ "color_field": { "type": "string", "required": false, "description": "Campo para colorir por categoria." },
1543
+ "symbol_size": { "type": "number", "required": false, "default": 10 },
1544
+ "show_regression": { "type": "boolean", "required": false, "default": false, "description": "Mostrar linha de tendência." },
1545
+ "enable_zoom": { "type": "boolean", "required": false, "default": false }
1546
+ },
1547
+ "dataFields": ["xField", "yField"]
1548
+ },
1549
+ "effect-scatter": {
1550
+ "name": "Dispersão com Efeito",
1551
+ "category": "advanced",
1552
+ "description": "Scatter com efeito ripple animado nos pontos. Ideal para destacar localizações geográficas ou pontos de atenção.",
1553
+ "icon": "✨",
1554
+ "render": "EffectScatterComponent",
1555
+ "defaultSize": { "width": 450, "height": 380 },
1556
+ "llm_instruction": "Use widget_type='effect-scatter' para dispersão com efeito de onda animado. Bom para mapas com pontos destacados.",
1557
+ "propertiesDetailed": {
1558
+ "x_field": { "type": "string", "required": true },
1559
+ "y_field": { "type": "string", "required": true },
1560
+ "symbol_size": { "type": "number", "required": false, "default": 10 },
1561
+ "ripple_effect": { "type": "boolean", "required": false, "default": true }
1562
+ }
1563
+ },
1564
+ "gauge": {
1565
+ "name": "Velocímetro",
1566
+ "category": "advanced",
1567
+ "description": "Velocímetro/medidor para exibir um valor único em uma escala. Ex: percentual de meta atingida, temperatura, score.",
1568
+ "icon": "⏱️",
1569
+ "render": "GaugeComponent",
1570
+ "defaultSize": { "width": 350, "height": 350 },
1571
+ "llm_instruction": "Use widget_type='gauge' para exibir um valor único em escala de velocímetro. OBRIGATÓRIO: value_field (campo numérico). Opcionais: min, max, target_value, unit.",
1572
+ "propertiesDetailed": {
1573
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico do valor a exibir." },
1574
+ "min": { "type": "number", "required": false, "default": 0, "description": "Valor mínimo da escala." },
1575
+ "max": { "type": "number", "required": false, "default": 100, "description": "Valor máximo da escala." },
1576
+ "target_value": { "type": "number", "required": false, "description": "Valor alvo/meta (mostrado como ponteiro secundário)." },
1577
+ "unit": { "type": "string", "required": false, "description": "Unidade do valor. Ex: '%', 'pts', 'R$'." },
1578
+ "format": { "type": "string", "required": false, "values": ["number", "currency", "percent"], "default": "number" },
1579
+ "aggregation": { "type": "string", "required": false, "default": "sum", "values": ["sum", "avg", "count", "min", "max", "first", "last"] }
1580
+ },
1581
+ "dataFields": ["valueField", "aggregation"]
1582
+ },
1583
+ "funnel": {
1584
+ "name": "Funil",
1585
+ "category": "advanced",
1586
+ "description": "Funil de conversão para visualizar etapas de um processo com redução progressiva de volume.",
1587
+ "icon": "🔻",
1588
+ "render": "FunnelComponent",
1589
+ "defaultSize": { "width": 400, "height": 350 },
1590
+ "llm_instruction": "Use widget_type='funnel' para pipeline/funil de conversão (ex: leads → qualificados → oportunidades → clientes). OBRIGATÓRIO: category_field (nome da etapa) e value_field (volume).",
1591
+ "propertiesDetailed": {
1592
+ "category_field": { "type": "string", "required": true, "description": "Campo com o nome de cada etapa do funil." },
1593
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico com o volume de cada etapa." },
1594
+ "sort": { "type": "string", "required": false, "values": ["descending", "ascending", "none"], "default": "descending" },
1595
+ "show_percentage": { "type": "boolean", "required": false, "default": true },
1596
+ "show_labels": { "type": "boolean", "required": false, "default": true },
1597
+ "gap": { "type": "number", "required": false, "default": 2 }
1598
+ },
1599
+ "dataFields": ["categoryField", "valueField"]
1600
+ },
1601
+ "waterfall": {
1602
+ "name": "Cascata",
1603
+ "category": "advanced",
1604
+ "description": "Gráfico de cascata (waterfall) para mostrar contribuição de parcelas a um total. Ex: receitas, despesas e lucro.",
1605
+ "icon": "💧",
1606
+ "render": "WaterfallComponent",
1607
+ "defaultSize": { "width": 720, "height": 480 },
1608
+ "llm_instruction": "Use widget_type='waterfall' para mostrar como valores positivos e negativos somados chegam a um total. OBRIGATÓRIO: category_field e value_field. Valores positivos sobem, negativos descem.",
1609
+ "propertiesDetailed": {
1610
+ "category_field": { "type": "string", "required": true, "description": "Campo com o nome de cada item/etapa." },
1611
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico (positivo=incremento, negativo=decremento)." },
1612
+ "show_total": { "type": "boolean", "required": false, "default": true, "description": "Exibir barra de total ao final." },
1613
+ "show_labels": { "type": "boolean", "required": false, "default": true },
1614
+ "positive_color": { "type": "string", "required": false, "default": "#10b981" },
1615
+ "negative_color": { "type": "string", "required": false, "default": "#ef4444" },
1616
+ "total_color": { "type": "string", "required": false, "default": "#3b82f6" }
1617
+ },
1618
+ "dataFields": ["categoryField", "valueField"]
1619
+ },
1620
+ "kpi": {
1621
+ "name": "KPI",
1622
+ "category": "data",
1623
+ "description": "Cartão de indicador chave (KPI) com valor principal, comparação e sparkline opcional.",
1624
+ "icon": "💰",
1625
+ "render": "KpiComponent",
1626
+ "defaultSize": { "width": 350, "height": 180 },
1627
+ "llm_instruction": "Use widget_type='kpi' para exibir um único indicador numérico em destaque (faturamento, total de pedidos, ticket médio, etc.). OBRIGATÓRIO: value_field. Opcional: comparison_type para comparar com meta ou período anterior, sparkline_field para mini-gráfico de tendência.",
1628
+ "propertiesDetailed": {
1629
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico a exibir como KPI principal." },
1630
+ "aggregation": { "type": "string", "required": false, "default": "sum", "values": ["sum", "avg", "count", "min", "max", "first", "last"] },
1631
+ "format": { "type": "string", "required": false, "values": ["number", "currency", "percent", "decimal"], "default": "number", "description": "Formato do valor." },
1632
+ "prefix": { "type": "string", "required": false, "description": "Prefixo do valor. Ex: 'R$'." },
1633
+ "suffix": { "type": "string", "required": false, "description": "Sufixo do valor. Ex: '%', 'un'." },
1634
+ "label": { "type": "string", "required": false, "description": "Rótulo/legenda do indicador." },
1635
+ "comparison_type": { "type": "string", "required": false, "values": ["none", "target", "previous"], "default": "none", "description": "Tipo de comparação: 'target'=vs meta, 'previous'=vs período anterior." },
1636
+ "target_field": { "type": "string", "required": false, "description": "Campo com o valor alvo/meta (para comparison_type='target')." },
1637
+ "previous_field": { "type": "string", "required": false, "description": "Campo com o valor do período anterior (para comparison_type='previous')." },
1638
+ "sparkline_field": { "type": "string", "required": false, "description": "Campo numérico para o mini-gráfico de tendência no card." },
1639
+ "icon": { "type": "string", "required": false, "description": "Nome do ícone Lucide. Ex: 'DollarSign', 'TrendingUp'." },
1640
+ "color": { "type": "string", "required": false, "description": "Cor de destaque (hex)." }
1641
+ },
1642
+ "dataFields": ["valueField", "aggregation"]
1643
+ },
1644
+ "grid": {
1645
+ "name": "Tabela",
1646
+ "category": "data",
1647
+ "description": "Tabela de dados. Suporta dois modos: legado (DataGrid com columns + column_labels) e v2 (DataGridV2 com column_defs tipadas). Para ativar o DataGridV2, use use_grid_v2: true e forneça column_defs.",
1648
+ "icon": "📊",
1649
+ "render": "GridComponent",
1650
+ "defaultSize": { "width": 980, "height": 400 },
1651
+ "properties": [
1652
+ "selectedColumns",
1653
+ "enableSorting",
1654
+ "enableFiltering",
1655
+ "enablePagination",
1656
+ "pageSize",
1657
+ "striped",
1658
+ "rowHeight"
1659
+ ],
1660
+ "serialized_properties": {
1661
+ "title": { "type": "string", "required": true },
1662
+ "page_size": { "type": "number", "required": true, "default": 20 },
1663
+ "columns": { "type": "string[]", "required": false, "description": "Lista de campos a exibir (modo legado). Opcional se column_defs estiver presente." },
1664
+ "column_labels": { "type": "Record<string, string>", "required": false, "description": "Labels das colunas (modo legado)." },
1665
+ "enable_filters": { "type": "boolean", "default": false },
1666
+ "enable_export": { "type": "boolean", "default": false },
1667
+ "enable_pagination": { "type": "boolean", "default": true },
1668
+ "enable_column_settings": { "type": "boolean", "default": false },
1669
+ "enable_fullscreen": { "type": "boolean", "default": false },
1670
+ "enable_aggregation": { "type": "boolean", "default": false },
1671
+ "use_grid_v2": {
1672
+ "type": "boolean",
1673
+ "default": false,
1674
+ "description": "Se true, usa DataGridV2 (mais leve, tipado, com resize e reorder de colunas). Requer column_defs."
1675
+ },
1676
+ "column_defs": {
1677
+ "type": "SerializedGridColumnDef[]",
1678
+ "required": false,
1679
+ "description": "Definições avançadas por coluna para DataGridV2. Cada item define id, header, width, min_width, sortable, format (type, decimals, currency, locale, notation).",
1680
+ "example": [
1681
+ { "id": "nome", "header": "Nome", "width": 200, "sortable": true },
1682
+ { "id": "valor", "header": "Valor", "width": 150, "format": { "type": "currency", "decimals": 2, "currency": "BRL" } },
1683
+ { "id": "percentual", "header": "%", "width": 100, "format": { "type": "percentage", "decimals": 1 } },
1684
+ { "id": "data", "header": "Data", "width": 120, "format": { "type": "date" } }
1685
+ ]
1686
+ },
1687
+ "default_sort": {
1688
+ "type": "{ column_id: string, direction: 'asc' | 'desc' }",
1689
+ "required": false,
1690
+ "description": "Ordenação inicial. Ex: { column_id: 'valor', direction: 'desc' }"
1691
+ },
1692
+ "empty_message": { "type": "string", "required": false, "default": "Nenhum registro encontrado." },
1693
+ "loading_message": { "type": "string", "required": false, "default": "Carregando..." }
1694
+ },
1695
+ "llm_instruction": "Para grids no dashboard.serialized.json, SEMPRE prefira use_grid_v2: true com column_defs quando souber os campos antecipadamente. O DataGridV2 é mais leve, suporta formatação por coluna (currency, percentage, date, etc.), resize e reorder de colunas nativo. Se não souber os campos, use o modo legado (columns + column_labels) que auto-detecta."
1696
+ },
1697
+ "pivot": {
1698
+ "name": "Pivot",
1699
+ "category": "data",
1700
+ "description": "Tabela pivot (dinâmica) para análise cruzada — linhas × colunas com valores agregados.",
1701
+ "icon": "📋",
1702
+ "render": "PivotComponent",
1703
+ "defaultSize": { "width": 980, "height": 400 },
1704
+ "llm_instruction": "Use widget_type='pivot' para tabela cruzada (ex: vendas por vendedor × mês). OBRIGATÓRIO: row_field (dimensão das linhas), col_field (dimensão das colunas), value_field (métrica). Aggregation padrão: sum.",
1705
+ "propertiesDetailed": {
1706
+ "row_field": { "type": "string", "required": true, "description": "Campo das linhas da tabela pivot. Ex: 'vendedor', 'produto'." },
1707
+ "col_field": { "type": "string", "required": true, "description": "Campo das colunas da tabela pivot. Ex: 'mes', 'ano', 'categoria'." },
1708
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico com o valor a agregar." },
1709
+ "aggregation": { "type": "string", "required": false, "default": "sum", "values": ["sum", "avg", "count", "min", "max"] },
1710
+ "show_totals": { "type": "boolean", "required": false, "default": true, "description": "Mostrar linha/coluna de totais." },
1711
+ "format": { "type": "string", "required": false, "values": ["number", "currency", "percent"], "default": "number" }
1712
+ }
1713
+ },
1714
+ "sparkline": {
1715
+ "name": "Sparkline",
1716
+ "category": "data",
1717
+ "description": "KPI compacto com mini gráfico de tendência embutido. Combina valor principal + variação + sparkline em um só card.",
1718
+ "icon": "⚡",
1719
+ "render": "SparklineComponent",
1720
+ "defaultSize": { "width": 350, "height": 180 },
1721
+ "llm_instruction": "Use widget_type='sparkline' para card KPI com mini gráfico de tendência. Ideal para métricas com histórico temporal (ex: faturamento mês a mês). OBRIGATÓRIO: value_field (métrica principal) e x_field (eixo de tempo para o sparkline).",
1722
+ "propertiesDetailed": {
1723
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico do valor principal do KPI." },
1724
+ "x_field": { "type": "string", "required": true, "description": "Campo de data/período para o eixo do sparkline." },
1725
+ "chart_type": { "type": "string", "required": false, "values": ["line", "area", "bar"], "default": "area" },
1726
+ "label": { "type": "string", "required": false, "description": "Rótulo/título do card." },
1727
+ "format": { "type": "string", "required": false, "values": ["number", "currency", "percent"], "default": "number" },
1728
+ "show_area": { "type": "boolean", "required": false, "default": true },
1729
+ "show_stats": { "type": "boolean", "required": false, "default": true, "description": "Mostrar min/max/avg abaixo do sparkline." },
1730
+ "color": { "type": "string", "required": false, "description": "Cor da linha/área (hex)." }
1731
+ },
1732
+ "dataFields": ["valueField", "xField"]
1733
+ },
1734
+ "card": {
1735
+ "name": "Cartão",
1736
+ "category": "data",
1737
+ "description": "Cartão customizável com ícone",
1738
+ "icon": "🎯",
1739
+ "render": "CardComponent",
1740
+ "defaultSize": { "width": 350, "height": 180 },
1741
+ "properties": [
1742
+ "format",
1743
+ "subtitle",
1744
+ "icon",
1745
+ "color",
1746
+ "sparkline",
1747
+ "solidBackground"
1748
+ ],
1749
+ "dataFields": ["valueField", "aggregation"]
1750
+ },
1751
+ "multi-card": {
1752
+ "name": "Multi-Cards",
1753
+ "category": "data",
1754
+ "description": "Múltiplos cartões KPI em grade, cada um exibindo uma métrica diferente da mesma query. Ideal para painel de indicadores.",
1755
+ "icon": "📋",
1756
+ "render": "MultiCardComponent",
1757
+ "defaultSize": { "width": 700, "height": 400 },
1758
+ "llm_instruction": "Use widget_type='multi-card' para exibir vários KPIs em grade (ex: Faturamento, Pedidos, Ticket Médio, Margem). Defina cards[] com cada indicador. Alternativa: usar múltiplos widget_type='kpi' em seção com várias colunas.",
1759
+ "propertiesDetailed": {
1760
+ "cards": {
1761
+ "type": "array",
1762
+ "required": true,
1763
+ "description": "Lista de cards, cada um com: { label, value_field, format, aggregation, icon, color }",
1764
+ "itemShape": {
1765
+ "label": "string — rótulo do card",
1766
+ "value_field": "string — campo numérico",
1767
+ "format": "number | currency | percent",
1768
+ "aggregation": "sum | avg | count | min | max | first | last",
1769
+ "icon": "string — nome ícone Lucide",
1770
+ "color": "string — cor hex"
1771
+ }
1772
+ },
1773
+ "layout": { "type": "string", "required": false, "values": ["grid", "horizontal"], "default": "grid" },
1774
+ "show_trend": { "type": "boolean", "required": false, "default": false }
1775
+ },
1776
+ "dataFields": ["valueFields", "aggregation"]
1777
+ },
1778
+ "text": {
1779
+ "name": "Texto",
1780
+ "category": "data",
1781
+ "description": "Widget de texto/markdown",
1782
+ "icon": "📝",
1783
+ "render": "TextComponent",
1784
+ "defaultSize": { "width": 480, "height": 200 },
1785
+ "properties": [
1786
+ "content",
1787
+ "fontSize",
1788
+ "textAlign",
1789
+ "fontWeight"
1790
+ ],
1791
+ "noData": true
1792
+ },
1793
+ "image": {
1794
+ "name": "Imagem",
1795
+ "category": "data",
1796
+ "description": "Widget de imagem estática",
1797
+ "icon": "🖼️",
1798
+ "render": "ImageComponent",
1799
+ "defaultSize": { "width": 480, "height": 300 },
1800
+ "properties": [
1801
+ "src",
1802
+ "alt",
1803
+ "objectFit"
1804
+ ],
1805
+ "noData": true
1806
+ },
1807
+ "timeline": {
1808
+ "name": "Linha do Tempo",
1809
+ "category": "data",
1810
+ "description": "Linha do tempo vertical para eventos históricos ou atividades. Cada linha da query vira um evento na timeline.",
1811
+ "icon": "📅",
1812
+ "render": "TimelineComponent",
1813
+ "defaultSize": { "width": 980, "height": 400 },
1814
+ "llm_instruction": "Use widget_type='timeline' para mostrar eventos em ordem cronológica (ex: histórico de pedidos, atividades, entregas). OBRIGATÓRIO: date_field (data do evento) e title_field (título/descrição).",
1815
+ "propertiesDetailed": {
1816
+ "date_field": { "type": "string", "required": true, "description": "Campo de data do evento." },
1817
+ "title_field": { "type": "string", "required": true, "description": "Campo com o título/nome do evento." },
1818
+ "description_field": { "type": "string", "required": false, "description": "Campo com descrição detalhada do evento." },
1819
+ "color_field": { "type": "string", "required": false, "description": "Campo para colorir eventos por categoria." },
1820
+ "format": { "type": "string", "required": false, "values": ["dd/MM/yyyy", "dd/MM/yyyy HH:mm", "MM/yyyy"], "default": "dd/MM/yyyy" },
1821
+ "show_quick_filters": { "type": "boolean", "required": false, "default": true }
1822
+ },
1823
+ "dataFields": ["dateField", "titleField"]
1824
+ },
1825
+ "progress-list": {
1826
+ "name": "Lista de Progresso",
1827
+ "category": "data",
1828
+ "description": "Lista com barras de progresso, valores e percentuais. Exibe rankings de itens (top clientes, produtos, fornecedores, etc.) com barra proporcional ao valor.",
1829
+ "icon": "📊",
1830
+ "render": "ProgressListComponent",
1831
+ "defaultSize": { "width": 480, "height": 400 },
1832
+ "llm_instruction": "Use widget_type='progress-list' para rankings com barra de progresso (ex: top clientes, top produtos, top cidades). OBRIGATÓRIO definir labelField (nome da categoria) e valueField (campo numérico). Os dados vêm da query SQL via query_id. NÃO use widget_type='kpi' ou 'panel' para este caso. Exemplo: { \"widget_type\": \"progress-list\", \"properties\": { \"labelField\": \"nomeFornecedor\", \"valueField\": \"valorTotal\", \"maxItems\": 10, \"valueFormat\": \"currency\", \"colorScheme\": \"gradient\" } }. IMPORTANTE: labelField e valueField devem corresponder EXATAMENTE aos aliases camelCase da query SQL.",
1833
+ "properties": [
1834
+ "labelField",
1835
+ "valueField",
1836
+ "aggregation",
1837
+ "maxItems",
1838
+ "showValues",
1839
+ "showPercentage",
1840
+ "valueFormat",
1841
+ "barHeight",
1842
+ "colorScheme",
1843
+ "primaryColor",
1844
+ "sortBy",
1845
+ "sortOrder"
1846
+ ]
1847
+ },
1848
+ "treemap": {
1849
+ "name": "Treemap",
1850
+ "category": "hierarchical",
1851
+ "description": "Mapa de árvore hierárquico — retângulos proporcionais ao valor. Ideal para mostrar participação de itens em um total (ex: produtos por categoria).",
1852
+ "icon": "🗺️",
1853
+ "render": "TreemapComponent",
1854
+ "defaultSize": { "width": 480, "height": 350 },
1855
+ "llm_instruction": "Use widget_type='treemap' para visualizar hierarquia com área proporcional ao valor. OBRIGATÓRIO: name_field (rótulo do item) e value_field (tamanho do bloco). Opcional: group_field para agrupamento de nível superior.",
1856
+ "propertiesDetailed": {
1857
+ "name_field": { "type": "string", "required": true, "description": "Campo com o nome/rótulo de cada item." },
1858
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico (define o tamanho do bloco)." },
1859
+ "group_field": { "type": "string", "required": false, "description": "Campo de agrupamento de nível superior (cria hierarquia de 2 níveis)." },
1860
+ "show_labels": { "type": "boolean", "required": false, "default": true },
1861
+ "color_scheme": { "type": "string", "required": false, "values": ["theme", "random", "gradient"], "default": "theme" },
1862
+ "roam": { "type": "boolean", "required": false, "default": false, "description": "Permitir zoom/pan." }
1863
+ }
1864
+ },
1865
+ "sankey": {
1866
+ "name": "Sankey",
1867
+ "category": "hierarchical",
1868
+ "description": "Diagrama de fluxo Sankey para visualizar transferência de volume entre nós. Ex: origem → canal → conversão.",
1869
+ "icon": "🌊",
1870
+ "render": "SankeyComponent",
1871
+ "defaultSize": { "width": 580, "height": 400 },
1872
+ "llm_instruction": "Use widget_type='sankey' para fluxos entre categorias (ex: origem de tráfego → produto → conversão). Requer dados no formato { source, target, value }. Defina source_field, target_field, value_field.",
1873
+ "propertiesDetailed": {
1874
+ "source_field": { "type": "string", "required": true, "description": "Campo com o nó de origem do fluxo." },
1875
+ "target_field": { "type": "string", "required": true, "description": "Campo com o nó de destino do fluxo." },
1876
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico com o volume do fluxo." },
1877
+ "orient": { "type": "string", "required": false, "values": ["horizontal", "vertical"], "default": "horizontal" },
1878
+ "node_width": { "type": "number", "required": false, "default": 20 },
1879
+ "node_gap": { "type": "number", "required": false, "default": 8 }
1880
+ }
1881
+ },
1882
+ "graph": {
1883
+ "name": "Grafo de Rede",
1884
+ "category": "hierarchical",
1885
+ "description": "Grafo de nós e arestas para representar redes, relacionamentos e dependências.",
1886
+ "icon": "🕸️",
1887
+ "render": "GraphComponent",
1888
+ "defaultSize": { "width": 480, "height": 400 },
1889
+ "llm_instruction": "Use widget_type='graph' para redes de relacionamento (ex: fornecedores ↔ produtos, clientes ↔ vendedores). Requer dados com nós (node_id_field, node_name_field) e arestas (source_field, target_field).",
1890
+ "propertiesDetailed": {
1891
+ "node_id_field": { "type": "string", "required": true, "description": "Campo com ID único do nó." },
1892
+ "node_name_field": { "type": "string", "required": true, "description": "Campo com o nome/rótulo do nó." },
1893
+ "source_field": { "type": "string", "required": true, "description": "Campo com o ID do nó de origem da aresta." },
1894
+ "target_field": { "type": "string", "required": true, "description": "Campo com o ID do nó de destino da aresta." },
1895
+ "layout": { "type": "string", "required": false, "values": ["force", "circular", "none"], "default": "force" },
1896
+ "repulsion": { "type": "number", "required": false, "default": 100 }
1897
+ }
1898
+ },
1899
+ "sunburst": {
1900
+ "name": "Sunburst",
1901
+ "category": "hierarchical",
1902
+ "description": "Gráfico sunburst hierárquico em anéis concêntricos. Ideal para hierarquias com 2-3 níveis (ex: país → estado → cidade).",
1903
+ "icon": "☀️",
1904
+ "render": "SunburstComponent",
1905
+ "defaultSize": { "width": 420, "height": 400 },
1906
+ "llm_instruction": "Use widget_type='sunburst' para hierarquias multi-nível em anéis (ex: categoria → subcategoria → produto). Defina: level1_field (nível externo), level2_field (nível interno), value_field.",
1907
+ "propertiesDetailed": {
1908
+ "level1_field": { "type": "string", "required": true, "description": "Campo de nível 1 (anel externo)." },
1909
+ "level2_field": { "type": "string", "required": false, "description": "Campo de nível 2 (anel do meio)." },
1910
+ "level3_field": { "type": "string", "required": false, "description": "Campo de nível 3 (anel central)." },
1911
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico com o valor de cada folha." },
1912
+ "radius": { "type": "number", "required": false, "default": 75 }
1913
+ }
1914
+ },
1915
+ "tree": {
1916
+ "name": "Árvore",
1917
+ "category": "hierarchical",
1918
+ "description": "Gráfico de árvore hierárquica com nós e conexões. Ideal para organogramas, categorias de produtos, estruturas hierárquicas.",
1919
+ "icon": "🌳",
1920
+ "render": "TreeChartComponent",
1921
+ "defaultSize": { "width": 440, "height": 400 },
1922
+ "llm_instruction": "Use widget_type='tree' para estruturas pai-filho (ex: organograma, categorias). Requer dados com id_field e parent_field para construir a hierarquia.",
1923
+ "propertiesDetailed": {
1924
+ "id_field": { "type": "string", "required": true, "description": "Campo com o ID único do nó." },
1925
+ "parent_field": { "type": "string", "required": true, "description": "Campo com o ID do nó pai (null/vazio = raiz)." },
1926
+ "name_field": { "type": "string", "required": true, "description": "Campo com o nome/rótulo do nó." },
1927
+ "orient": { "type": "string", "required": false, "values": ["LR", "RL", "TB", "BT"], "default": "LR", "description": "Orientação: LR=esquerda-direita, TB=cima-baixo." },
1928
+ "expand_and_collapse": { "type": "boolean", "required": false, "default": true },
1929
+ "symbol_size": { "type": "number", "required": false, "default": 7 }
1930
+ }
1931
+ },
1932
+ "radar": {
1933
+ "name": "Radar",
1934
+ "category": "specialized",
1935
+ "description": "Gráfico radar/aranha para comparar múltiplas dimensões simultaneamente. Ex: comparar desempenho de equipes em várias métricas.",
1936
+ "icon": "🕸️",
1937
+ "render": "RadarComponent",
1938
+ "defaultSize": { "width": 450, "height": 380 },
1939
+ "llm_instruction": "Use widget_type='radar' para comparar entidades em múltiplas dimensões (ex: vendedor A vs B em: volume, ticket médio, conversão, atendimentos). Defina indicators[] com as dimensões e series[] com os valores.",
1940
+ "propertiesDetailed": {
1941
+ "indicators": {
1942
+ "type": "array",
1943
+ "required": true,
1944
+ "description": "Lista de { name, max } com cada dimensão do radar.",
1945
+ "example": [{"name": "Volume", "max": 100}, {"name": "Margem", "max": 50}]
1946
+ },
1947
+ "name_field": { "type": "string", "required": true, "description": "Campo com o nome de cada série (ex: nome do vendedor)." },
1948
+ "value_fields": { "type": "string[]", "required": true, "description": "Campos dos valores de cada dimensão, na mesma ordem dos indicators." },
1949
+ "shape": { "type": "string", "required": false, "values": ["polygon", "circle"], "default": "polygon" },
1950
+ "split_number": { "type": "number", "required": false, "default": 5 }
1951
+ }
1952
+ },
1953
+ "heatmap": {
1954
+ "name": "Mapa de Calor",
1955
+ "category": "specialized",
1956
+ "description": "Mapa de calor (grade X×Y colorida por intensidade). Ex: volume de vendas por dia da semana × hora, temperatura por mês × ano.",
1957
+ "icon": "🔥",
1958
+ "render": "HeatmapComponent",
1959
+ "defaultSize": { "width": 520, "height": 380 },
1960
+ "llm_instruction": "Use widget_type='heatmap' para matrizes de calor. OBRIGATÓRIO: x_field (eixo horizontal), y_field (eixo vertical), value_field (intensidade da cor).",
1961
+ "propertiesDetailed": {
1962
+ "x_field": { "type": "string", "required": true, "description": "Campo do eixo X (ex: dia da semana, mês)." },
1963
+ "y_field": { "type": "string", "required": true, "description": "Campo do eixo Y (ex: hora, ano)." },
1964
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico que define a intensidade da cor." },
1965
+ "min": { "type": "number", "required": false, "description": "Valor mínimo para a escala de cores." },
1966
+ "max": { "type": "number", "required": false, "description": "Valor máximo para a escala de cores." },
1967
+ "color_range": { "type": "string[]", "required": false, "description": "Array de cores [mín, máx]. Ex: ['#f0f9ff', '#0369a1']." }
1968
+ }
1969
+ },
1970
+ "candlestick": {
1971
+ "name": "Candlestick",
1972
+ "category": "specialized",
1973
+ "description": "Gráfico de velas (OHLC) para análise financeira de ativos — abertura, máxima, mínima, fechamento.",
1974
+ "icon": "📈",
1975
+ "render": "CandlestickComponent",
1976
+ "defaultSize": { "width": 480, "height": 380 },
1977
+ "llm_instruction": "Use widget_type='candlestick' para análise financeira de ativos (ações, câmbio). OBRIGATÓRIO: date_field, open_field, close_field, low_field, high_field.",
1978
+ "propertiesDetailed": {
1979
+ "date_field": { "type": "string", "required": true, "description": "Campo de data/período." },
1980
+ "open_field": { "type": "string", "required": true, "description": "Campo de preço de abertura." },
1981
+ "close_field": { "type": "string", "required": true, "description": "Campo de preço de fechamento." },
1982
+ "low_field": { "type": "string", "required": true, "description": "Campo de mínima." },
1983
+ "high_field": { "type": "string", "required": true, "description": "Campo de máxima." },
1984
+ "up_color": { "type": "string", "required": false, "default": "#10b981" },
1985
+ "down_color": { "type": "string", "required": false, "default": "#ef4444" }
1986
+ }
1987
+ },
1988
+ "boxplot": {
1989
+ "name": "Box Plot",
1990
+ "category": "specialized",
1991
+ "description": "Gráfico de caixa para distribuição estatística — mediana, quartis e outliers. Ex: distribuição de ticket por categoria.",
1992
+ "icon": "📦",
1993
+ "render": "BoxplotComponent",
1994
+ "defaultSize": { "width": 450, "height": 380 },
1995
+ "llm_instruction": "Use widget_type='boxplot' para visualizar distribuição estatística de valores por grupo. OBRIGATÓRIO: group_field (categoria) e value_field (valor numérico a distribuir).",
1996
+ "propertiesDetailed": {
1997
+ "group_field": { "type": "string", "required": true, "description": "Campo de agrupamento (eixo X)." },
1998
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico para calcular a distribuição." },
1999
+ "box_width": { "type": "number", "required": false, "default": 30 }
2000
+ }
2001
+ },
2002
+ "parallel": {
2003
+ "name": "Coordenadas Paralelas",
2004
+ "category": "specialized",
2005
+ "description": "Coordenadas paralelas para análise multivariada — cada linha representa um registro cruzando múltiplos eixos.",
2006
+ "icon": "📊",
2007
+ "render": "ParallelComponent",
2008
+ "defaultSize": { "width": 650, "height": 380 },
2009
+ "llm_instruction": "Use widget_type='parallel' para análise de padrões em dados multivariados. Cada registro é uma linha que atravessa os eixos. Defina axis_fields[] com os campos a incluir.",
2010
+ "propertiesDetailed": {
2011
+ "axis_fields": { "type": "string[]", "required": true, "description": "Lista de campos numéricos a usar como eixos paralelos." },
2012
+ "name_field": { "type": "string", "required": false, "description": "Campo para identificar/colorir cada linha." },
2013
+ "line_opacity": { "type": "number", "required": false, "default": 0.5 }
2014
+ }
2015
+ },
2016
+ "themeriver": {
2017
+ "name": "Theme River",
2018
+ "category": "specialized",
2019
+ "description": "Rio temático — evolução do volume de múltiplos temas/categorias ao longo do tempo. Ex: evolução de vendas por linha de produto mês a mês.",
2020
+ "icon": "🌊",
2021
+ "render": "ThemeRiverComponent",
2022
+ "defaultSize": { "width": 650, "height": 380 },
2023
+ "llm_instruction": "Use widget_type='themeriver' para mostrar como múltiplas categorias evoluem no tempo (similar a stacked area). OBRIGATÓRIO: date_field, theme_field (categoria) e value_field.",
2024
+ "propertiesDetailed": {
2025
+ "date_field": { "type": "string", "required": true, "description": "Campo de data (eixo do tempo)." },
2026
+ "theme_field": { "type": "string", "required": true, "description": "Campo de categoria/tema (cada um vira uma faixa)." },
2027
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico com o volume." }
2028
+ }
2029
+ },
2030
+ "pictorial-bar": {
2031
+ "name": "Barra Pictórica",
2032
+ "category": "specialized",
2033
+ "description": "Barras com ícones/símbolos repetidos proporcionalmente ao valor. Mais visual e ilustrativo que barras convencionais.",
2034
+ "icon": "🎨",
2035
+ "render": "PictorialBarComponent",
2036
+ "defaultSize": { "width": 480, "height": 350 },
2037
+ "llm_instruction": "Use widget_type='pictorial-bar' para barras decorativas com ícones. OBRIGATÓRIO: category_field e value_field. O símbolo padrão é uma pessoa/círculo.",
2038
+ "propertiesDetailed": {
2039
+ "category_field": { "type": "string", "required": true, "description": "Campo de categorias (eixo X)." },
2040
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico (quantidade de símbolos)." },
2041
+ "symbol": { "type": "string", "required": false, "default": "circle", "description": "Símbolo: 'circle', 'rect', 'roundRect', 'triangle', 'diamond' ou SVG path." },
2042
+ "symbol_repeat": { "type": "boolean", "required": false, "default": true },
2043
+ "symbol_size": { "type": "number[]", "required": false, "description": "[largura, altura] do símbolo. Ex: [18, 28]." }
2044
+ }
2045
+ },
2046
+ "map": {
2047
+ "name": "Mapa com Pontos",
2048
+ "category": "geo",
2049
+ "description": "Mapa geográfico com pontos/marcadores em coordenadas lat/lon. Ideal para distribuição geográfica de clientes, lojas, entregas.",
2050
+ "icon": "🗺️",
2051
+ "render": "MapComponent",
2052
+ "defaultSize": { "width": 520, "height": 350 },
2053
+ "llm_instruction": "Use widget_type='map' para plotar pontos em mapa (requer lat/lon). OBRIGATÓRIO: lat_field e lon_field. Opcional: label_field (tooltip) e value_field (tamanho do ponto).",
2054
+ "propertiesDetailed": {
2055
+ "lat_field": { "type": "string", "required": true, "description": "Campo de latitude." },
2056
+ "lon_field": { "type": "string", "required": true, "description": "Campo de longitude." },
2057
+ "label_field": { "type": "string", "required": false, "description": "Campo para o rótulo/tooltip do ponto." },
2058
+ "value_field": { "type": "string", "required": false, "description": "Campo numérico para variar o tamanho do ponto." },
2059
+ "show_connections": { "type": "boolean", "required": false, "default": false, "description": "Desenhar linhas de conexão entre os pontos." }
2060
+ }
2061
+ },
2062
+ "filled-map": {
2063
+ "name": "Mapa Coroplético",
2064
+ "category": "geo",
2065
+ "description": "Mapa com regiões preenchidas por intensidade de cor (coroplético). Ex: vendas por estado, usuários por país.",
2066
+ "icon": "🗺️",
2067
+ "render": "FilledMapComponent",
2068
+ "defaultSize": { "width": 520, "height": 350 },
2069
+ "llm_instruction": "Use widget_type='filled-map' para colorir regiões geográficas por valor. OBRIGATÓRIO: region_field (nome do estado/país) e value_field (intensidade da cor).",
2070
+ "propertiesDetailed": {
2071
+ "region_field": { "type": "string", "required": true, "description": "Campo com o nome da região (estado, país). Deve corresponder ao GeoJSON." },
2072
+ "value_field": { "type": "string", "required": true, "description": "Campo numérico para a intensidade da cor." },
2073
+ "color_range": { "type": "string[]", "required": false, "description": "Cores [mínimo, máximo]. Ex: ['#dbeafe', '#1d4ed8']." },
2074
+ "map_type": { "type": "string", "required": false, "values": ["brazil", "world"], "default": "brazil" }
2075
+ }
2076
+ },
2077
+ "lines": {
2078
+ "name": "Linhas de Fluxo Geo",
2079
+ "category": "geo",
2080
+ "description": "Linhas animadas sobre mapa para mostrar fluxos geográficos (ex: rotas de entrega, origem-destino).",
2081
+ "icon": "➡️",
2082
+ "render": "LinesComponent",
2083
+ "defaultSize": { "width": 520, "height": 350 },
2084
+ "llm_instruction": "Use widget_type='lines' para rotas/fluxos entre dois pontos geográficos. OBRIGATÓRIO: from_lat, from_lon, to_lat, to_lon. Opcional: value_field para variar a espessura.",
2085
+ "propertiesDetailed": {
2086
+ "from_lat_field": { "type": "string", "required": true, "description": "Latitude do ponto de origem." },
2087
+ "from_lon_field": { "type": "string", "required": true, "description": "Longitude do ponto de origem." },
2088
+ "to_lat_field": { "type": "string", "required": true, "description": "Latitude do ponto de destino." },
2089
+ "to_lon_field": { "type": "string", "required": true, "description": "Longitude do ponto de destino." },
2090
+ "value_field": { "type": "string", "required": false, "description": "Campo numérico (espessura da linha)." },
2091
+ "effect": { "type": "boolean", "required": false, "default": true, "description": "Animação de fluxo na linha." }
2092
+ }
2093
+ },
2094
+ "filter": {
2095
+ "name": "Filtro / Slicer",
2096
+ "category": "filter",
2097
+ "description": "Painel de filtro interativo (Slicer) com lista de valores selecionáveis — similar a um slicer do Excel/Power BI. Mais visual que dropdown para poucos valores.",
2098
+ "icon": "🎚️",
2099
+ "render": "FilterComponent",
2100
+ "defaultSize": { "width": 240, "height": 320 },
2101
+ "llm_instruction": "Use widget_type='filter' para slicer visual com botões clicáveis (máx ~10 valores). Para listas longas (>10 valores) prefira widget_type='dropdown'. OBRIGATÓRIO: filter_field e query_id.",
2102
+ "propertiesDetailed": {
2103
+ "filter_field": { "type": "string", "required": true, "description": "Campo cujos valores únicos serão listados como opções." },
2104
+ "filter_type": { "type": "string", "required": false, "values": ["dropdown", "buttons", "checkbox"], "default": "dropdown" },
2105
+ "multi_select": { "type": "boolean", "required": false, "default": false },
2106
+ "show_search": { "type": "boolean", "required": false, "default": false }
2107
+ }
2108
+ },
2109
+ "dropdown": {
2110
+ "name": "Dropdown / Combobox",
2111
+ "category": "filter",
2112
+ "description": "Filtro interativo tipo combobox — exibe uma lista de valores únicos extraídos de uma query para o usuário selecionar. Filtra os demais widgets que compartilham a mesma query_id. Suporta seleção simples ou múltipla. O estado do filtro é preservado ao recarregar a página.",
2113
+ "icon": "🔽",
2114
+ "render": "DropdownComponent",
2115
+ "defaultSize": { "width": 250, "height": 60 },
2116
+ "llm_instruction": "Use widget_type='dropdown' para criar filtros interativos de seleção. O widget carrega os valores únicos do campo 'filter_field' via query_id e filtra os outros widgets. OBRIGATÓRIO: definir filter_field (nome do campo) e query_id (mesma query dos widgets que serão filtrados). O label é o rótulo exibido acima do dropdown. Use allow_multiple=true para seleção múltipla. Exemplo: um dropdown de 'categoria' filtrando um chart e um grid que usam a mesma query de produtos.",
2117
+ "propertiesDetailed": {
2118
+ "filter_field": {
2119
+ "type": "string",
2120
+ "required": true,
2121
+ "description": "Nome do campo cujos valores únicos serão listados no dropdown. Ex: 'categoria', 'vendedor', 'regiao'."
2122
+ },
2123
+ "label": {
2124
+ "type": "string",
2125
+ "required": false,
2126
+ "description": "Rótulo exibido acima do dropdown. Ex: 'Filtrar por Categoria'."
2127
+ },
2128
+ "allow_multiple": {
2129
+ "type": "boolean",
2130
+ "required": false,
2131
+ "default": false,
2132
+ "description": "Permitir seleção de múltiplos valores. false=seleção única, true=multi-seleção com badges."
2133
+ },
2134
+ "placeholder": {
2135
+ "type": "string",
2136
+ "required": false,
2137
+ "default": "Selecione...",
2138
+ "description": "Texto exibido quando nenhum valor está selecionado."
2139
+ }
2140
+ },
2141
+ "notes": [
2142
+ "O filtro é aplicado localmente nos dados já carregados — não refaz a query SQL.",
2143
+ "Para filtrar múltiplos widgets, todos devem usar a mesma query_id que o dropdown.",
2144
+ "O valor selecionado é preservado no sessionStorage (persiste no refresh da página).",
2145
+ "Coloque o dropdown na mesma section ou em section separada no topo, com col_span adequado."
2146
+ ]
2147
+ },
2148
+ "group": {
2149
+ "name": "Grupo",
2150
+ "category": "data",
2151
+ "description": "Container que agrupa widgets filhos",
2152
+ "icon": "📦",
2153
+ "render": "GroupComponent",
2154
+ "defaultSize": { "width": 980, "height": 600 },
2155
+ "properties": [
2156
+ "backgroundColor",
2157
+ "padding",
2158
+ "borderRadius"
2159
+ ],
2160
+ "noData": true,
2161
+ "llm_instruction": "NUNCA usar group para agrupar charts, grids ou KPIs no dashboard.serialized.json. É estritamente proibido criar um group com título ('Evolução Temporal', 'Análise Mensal', 'Gráficos', etc.) e colocar widgets dentro. Cada widget deve ser declarado diretamente em widgets[] com sua própria section_id. O title do chart vai em properties.title do próprio widget. Group só existe para casos explicitamente solicitados pelo usuário com filhos declarados."
2162
+ },
2163
+ "date": {
2164
+ "name": "Período",
2165
+ "category": "data",
2166
+ "description": "Seletor de período de datas (Dia, Semana, Mês, Ano)",
2167
+ "icon": "📅",
2168
+ "render": "WidgetDate",
2169
+ "defaultSize": { "width": 720, "height": 60 },
2170
+ "properties": [
2171
+ "field",
2172
+ "defaultPeriod"
2173
+ ],
2174
+ "noData": true
2175
+ },
2176
+ "companies": {
2177
+ "name": "Empresas",
2178
+ "category": "data",
2179
+ "description": "Seletor de empresas (multi-empresa)",
2180
+ "icon": "🏢",
2181
+ "render": "WidgetEmpresas",
2182
+ "defaultSize": { "width": 250, "height": 60 },
2183
+ "properties": [
2184
+ "field",
2185
+ "placeholder",
2186
+ "showIcon",
2187
+ "autoSelectFirst"
2188
+ ],
2189
+ "noData": true
2190
+ },
2191
+ "dataGrid": {
2192
+ "name": "DataGrid",
2193
+ "category": "data",
2194
+ "description": "Tabela de dados completa (standalone, fora do Designer)",
2195
+ "icon": "📊",
2196
+ "render": "DataGrid",
2197
+ "properties": [
2198
+ "data",
2199
+ "loading",
2200
+ "error",
2201
+ "title",
2202
+ "subtitle",
2203
+ "onRefresh",
2204
+ "enableFilters",
2205
+ "enableSearch",
2206
+ "searchPlaceholder",
2207
+ "enableExport",
2208
+ "enablePagination",
2209
+ "enableSort",
2210
+ "enableColumnResize",
2211
+ "enableColumnReorder",
2212
+ "enableAggregation",
2213
+ "enableFullscreen",
2214
+ "enableColumnSettings",
2215
+ "theme",
2216
+ "enableHeader",
2217
+ "fullWidthColumns",
2218
+ "pageSize",
2219
+ "totalRows",
2220
+ "currentPage",
2221
+ "onPageChange",
2222
+ "onPageSizeChange",
2223
+ "customColumns",
2224
+ "columnLabels",
2225
+ "columnAliases",
2226
+ "defaultVisibleColumns",
2227
+ "defaultSortColumn",
2228
+ "defaultSortDirection",
2229
+ "canNextPage",
2230
+ "canPreviousPage",
2231
+ "enableAdd",
2232
+ "onAdd",
2233
+ "addButtonText",
2234
+ "onRowClick",
2235
+ "enableEditing",
2236
+ "rowIdField",
2237
+ "onEditsChange",
2238
+ "columnIcons",
2239
+ "columnAggregationDefaults",
2240
+ "defaultColumnWidths"
2241
+ ]
2242
+ },
2243
+ "dataGridV2": {
2244
+ "name": "DataGridV2",
2245
+ "category": "data",
2246
+ "description": "Tabela de dados v2 com tipagem genérica (standalone)",
2247
+ "icon": "📊",
2248
+ "render": "DataGridV2",
2249
+ "properties": [
2250
+ "data",
2251
+ "columns",
2252
+ "rowKey",
2253
+ "loading",
2254
+ "loadingMessage",
2255
+ "emptyMessage",
2256
+ "onRowClick",
2257
+ "rowClassName",
2258
+ "footer",
2259
+ "pagination",
2260
+ "sortDescriptor",
2261
+ "onSortChange",
2262
+ "initialSort"
2263
+ ]
2264
+ },
2265
+ "widgetEmpresas": {
2266
+ "name": "WidgetEmpresas",
2267
+ "category": "data",
2268
+ "description": "Seletor de empresa standalone",
2269
+ "render": "WidgetEmpresas",
2270
+ "llm_instruction": "No dashboard.serialized.json, use widget_type='companies' para declarar este controle no layout. Nao depender de barra fixa no renderer.",
2271
+ "properties": [
2272
+ "value",
2273
+ "onChange",
2274
+ "placeholder",
2275
+ "showIcon",
2276
+ "className",
2277
+ "disabled",
2278
+ "autoSelectFirst"
2279
+ ],
2280
+ "noData": true
2281
+ },
2282
+ "widgetDate": {
2283
+ "name": "WidgetDate",
2284
+ "category": "data",
2285
+ "description": "Seletor de período standalone",
2286
+ "render": "WidgetDate",
2287
+ "llm_instruction": "No dashboard.serialized.json, use widget_type='date' para declarar este controle no layout. Nao depender de barra fixa no renderer.",
2288
+ "properties": [
2289
+ "value",
2290
+ "onChange",
2291
+ "className"
2292
+ ],
2293
+ "noData": true
2294
+ },
2295
+ "widgetTipos": {
2296
+ "name": "WidgetTipos",
2297
+ "category": "data",
2298
+ "description": "Seletor de tipos genérico standalone",
2299
+ "render": "WidgetTipos",
2300
+ "properties": [
2301
+ "tgId",
2302
+ "value",
2303
+ "onChange",
2304
+ "placeholder",
2305
+ "showIcon",
2306
+ "className",
2307
+ "disabled",
2308
+ "autoSelectFirst",
2309
+ "reloadKey"
2310
+ ],
2311
+ "noData": true
2312
+ },
2313
+ "__SERIALIZED_DECORATIVE_WIDGETS__": {
2314
+ "llm_instruction": "Os widgets abaixo são elementos DECORATIVOS disponíveis apenas no dashboard.serialized.json. Eles NÃO precisam de query_id (devem usar query_id: null). Permitem criar dashboards mais livres com títulos, textos explicativos, imagens, separadores e espaçamentos."
2315
+ },
2316
+ "heading": {
2317
+ "name": "Título / Heading",
2318
+ "category": "decorative",
2319
+ "description": "Elemento de título (H1, H2, H3, H4) para organizar visualmente o dashboard. Suporta subtítulo, cor customizada e alinhamento.",
2320
+ "icon": "📝",
2321
+ "render": "TextComponent",
2322
+ "defaultSize": { "width": 980, "height": 80 },
2323
+ "noData": true,
2324
+ "serialized_only": true,
2325
+ "propertiesDetailed": {
2326
+ "level": {
2327
+ "type": "string",
2328
+ "required": true,
2329
+ "values": ["h1", "h2", "h3", "h4"],
2330
+ "default": "h1",
2331
+ "description": "Nível do heading. h1=título principal, h2=subtítulo de seção, h3=grupo, h4=rótulo menor."
2332
+ },
2333
+ "content": {
2334
+ "type": "string",
2335
+ "required": true,
2336
+ "description": "Texto do heading. Ex: 'Visão Geral de Vendas'"
2337
+ },
2338
+ "align": {
2339
+ "type": "string",
2340
+ "required": false,
2341
+ "values": ["left", "center", "right"],
2342
+ "default": "left",
2343
+ "description": "Alinhamento horizontal do texto."
2344
+ },
2345
+ "color": {
2346
+ "type": "string",
2347
+ "required": false,
2348
+ "description": "Cor do texto (hex, rgb, nome CSS). Ex: '#1e293b'"
2349
+ },
2350
+ "subtitle": {
2351
+ "type": "string",
2352
+ "required": false,
2353
+ "description": "Texto secundário menor abaixo do heading."
2354
+ },
2355
+ "subtitle_color": {
2356
+ "type": "string",
2357
+ "required": false,
2358
+ "description": "Cor do subtítulo. Ex: '#64748b'"
2359
+ },
2360
+ "icon": {
2361
+ "type": "string",
2362
+ "required": false,
2363
+ "description": "Nome de ícone Lucide para exibir ao lado do heading."
2364
+ }
2365
+ }
2366
+ },
2367
+ "sdk-text": {
2368
+ "name": "Bloco de Texto",
2369
+ "category": "decorative",
2370
+ "description": "Bloco de texto livre para descrições, notas, instruções ou contexto no dashboard. Suporta markdown básico (**bold**, *italic*, [links]). Pode ter fundo colorido, borda e padding.",
2371
+ "icon": "📄",
2372
+ "render": "TextComponent",
2373
+ "defaultSize": { "width": 980, "height": 120 },
2374
+ "noData": true,
2375
+ "serialized_only": true,
2376
+ "llm_instruction": "No dashboard.serialized.json, use widget_type='text'. NÃO confundir com o widget 'text' do Designer (que é TextComponent interno). Este é o tipo serializado para blocos de texto decorativos.",
2377
+ "propertiesDetailed": {
2378
+ "content": {
2379
+ "type": "string",
2380
+ "required": true,
2381
+ "description": "Conteúdo do texto. Suporta markdown básico: **negrito**, *itálico*, [link](url)."
2382
+ },
2383
+ "align": {
2384
+ "type": "string",
2385
+ "required": false,
2386
+ "values": ["left", "center", "right", "justify"],
2387
+ "default": "left"
2388
+ },
2389
+ "font_size": {
2390
+ "type": "string",
2391
+ "required": false,
2392
+ "values": ["xs", "sm", "base", "lg", "xl"],
2393
+ "default": "base",
2394
+ "description": "Tamanho da fonte: xs=11px, sm=13px, base=15px, lg=18px, xl=22px."
2395
+ },
2396
+ "color": { "type": "string", "required": false },
2397
+ "background_color": { "type": "string", "required": false },
2398
+ "padding": { "type": "number", "required": false, "description": "Padding interno em px." },
2399
+ "border_radius": { "type": "number", "required": false },
2400
+ "border_color": { "type": "string", "required": false, "description": "Se definido, aplica borda de 1px solid." }
2401
+ }
2402
+ },
2403
+ "sdk-image": {
2404
+ "name": "Imagem Decorativa",
2405
+ "category": "decorative",
2406
+ "description": "Imagem decorativa para logos, banners, ilustrações. Suporta link clicável e legenda.",
2407
+ "icon": "🖼️",
2408
+ "render": "ImageComponent",
2409
+ "defaultSize": { "width": 480, "height": 300 },
2410
+ "noData": true,
2411
+ "serialized_only": true,
2412
+ "llm_instruction": "No dashboard.serialized.json, use widget_type='image'. Sempre forneça src e alt.",
2413
+ "propertiesDetailed": {
2414
+ "src": { "type": "string", "required": true, "description": "URL da imagem." },
2415
+ "alt": { "type": "string", "required": true, "description": "Texto alternativo para acessibilidade." },
2416
+ "object_fit": {
2417
+ "type": "string",
2418
+ "required": false,
2419
+ "values": ["cover", "contain", "fill", "none"],
2420
+ "default": "cover"
2421
+ },
2422
+ "height": { "type": "number", "required": false, "description": "Altura fixa em px." },
2423
+ "border_radius": { "type": "number", "required": false },
2424
+ "href": { "type": "string", "required": false, "description": "Link ao clicar na imagem." },
2425
+ "caption": { "type": "string", "required": false, "description": "Legenda abaixo da imagem." }
2426
+ }
2427
+ },
2428
+ "divider": {
2429
+ "name": "Separador / Divider",
2430
+ "category": "decorative",
2431
+ "description": "Linha separadora horizontal para dividir visualmente seções do dashboard. Pode ter label opcional no centro.",
2432
+ "icon": "➖",
2433
+ "render": "TextComponent",
2434
+ "defaultSize": { "width": 980, "height": 40 },
2435
+ "noData": true,
2436
+ "serialized_only": true,
2437
+ "propertiesDetailed": {
2438
+ "style": { "type": "string", "values": ["solid", "dashed", "dotted"], "default": "solid" },
2439
+ "color": { "type": "string", "required": false, "description": "Cor da linha." },
2440
+ "thickness": { "type": "number", "required": false, "default": 1, "description": "Espessura em px." },
2441
+ "margin": { "type": "number", "required": false, "default": 16, "description": "Margem vertical em px." },
2442
+ "label": { "type": "string", "required": false, "description": "Texto opcional no centro do divider." }
2443
+ }
2444
+ },
2445
+ "spacer": {
2446
+ "name": "Espaçador",
2447
+ "category": "decorative",
2448
+ "description": "Espaçamento vertical vazio para separar elementos no dashboard.",
2449
+ "icon": "↕️",
2450
+ "render": "none",
2451
+ "defaultSize": { "width": 980, "height": 32 },
2452
+ "noData": true,
2453
+ "serialized_only": true,
2454
+ "propertiesDetailed": {
2455
+ "height": { "type": "number", "required": true, "description": "Altura do espaçamento em px." }
2456
+ }
2457
+ },
2458
+ "widgetCaixas": {
2459
+ "name": "WidgetCaixas",
2460
+ "category": "data",
2461
+ "description": "Seletor de caixas financeiros standalone",
2462
+ "render": "WidgetCaixas",
2463
+ "properties": [
2464
+ "emCodigo",
2465
+ "value",
2466
+ "onChange",
2467
+ "placeholder",
2468
+ "showIcon",
2469
+ "className",
2470
+ "disabled",
2471
+ "autoSelectFirst",
2472
+ "onSelect"
2473
+ ],
2474
+ "noData": true
2475
+ }
2476
+ }
2477
+ }