@aurea-uds/react 0.1.0 → 0.3.0

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 (64) hide show
  1. package/README.md +34 -2
  2. package/dist/actions.d.ts +20 -0
  3. package/dist/actions.js +59 -5
  4. package/dist/agents.d.ts +209 -0
  5. package/dist/agents.js +302 -0
  6. package/dist/calendar.d.ts +6 -0
  7. package/dist/calendar.js +27 -0
  8. package/dist/chart.d.ts +10 -0
  9. package/dist/chart.js +53 -0
  10. package/dist/code-client.d.ts +6 -0
  11. package/dist/code-client.js +24 -0
  12. package/dist/code-editor.js +1 -0
  13. package/dist/code.d.ts +2 -13
  14. package/dist/code.js +5 -18
  15. package/dist/communication.js +1 -0
  16. package/dist/data-display-client.d.ts +14 -0
  17. package/dist/data-display-client.js +22 -0
  18. package/dist/data-display.d.ts +2 -23
  19. package/dist/data-display.js +5 -13
  20. package/dist/data-grid.d.ts +52 -3
  21. package/dist/data-grid.js +205 -25
  22. package/dist/feedback-client.d.ts +64 -0
  23. package/dist/feedback-client.js +110 -0
  24. package/dist/feedback.d.ts +2 -53
  25. package/dist/feedback.js +5 -71
  26. package/dist/file-input.d.ts +21 -2
  27. package/dist/file-input.js +202 -21
  28. package/dist/graph.d.ts +33 -0
  29. package/dist/graph.js +178 -0
  30. package/dist/identity-client.d.ts +9 -0
  31. package/dist/identity-client.js +12 -0
  32. package/dist/identity.d.ts +2 -8
  33. package/dist/identity.js +5 -3
  34. package/dist/index.d.ts +4 -1
  35. package/dist/index.js +33 -3
  36. package/dist/inputs-client.d.ts +105 -0
  37. package/dist/inputs-client.js +264 -0
  38. package/dist/inputs.d.ts +2 -65
  39. package/dist/inputs.js +9 -61
  40. package/dist/internal.d.ts +23 -70
  41. package/dist/internal.js +115 -23
  42. package/dist/layout-client.d.ts +9 -0
  43. package/dist/layout-client.js +72 -0
  44. package/dist/layout.d.ts +2 -14
  45. package/dist/layout.js +5 -22
  46. package/dist/markup.d.ts +72 -0
  47. package/dist/markup.js +87 -0
  48. package/dist/media-client.d.ts +36 -0
  49. package/dist/media-client.js +239 -0
  50. package/dist/media.d.ts +2 -9
  51. package/dist/media.js +5 -98
  52. package/dist/navigation-client.d.ts +94 -0
  53. package/dist/navigation-client.js +154 -0
  54. package/dist/navigation.d.ts +2 -59
  55. package/dist/navigation.js +5 -113
  56. package/dist/overlays.d.ts +28 -0
  57. package/dist/overlays.js +66 -10
  58. package/dist/pure.d.ts +196 -0
  59. package/dist/pure.js +111 -0
  60. package/dist/qrcode.d.ts +2 -1
  61. package/dist/qrcode.js +3 -2
  62. package/dist/system.d.ts +11 -1
  63. package/dist/system.js +59 -4
  64. package/package.json +40 -4
package/dist/pure.js ADDED
@@ -0,0 +1,111 @@
1
+ // A METADE SEM ESTADO do internal.tsx — Parte A do PLANO-1.0 (06/08/2026).
2
+ //
3
+ // Existe por uma razão só, e ela é a mesma da Parte A vista uma camada abaixo: o `internal.tsx`
4
+ // precisa de `"use client"` (ele chama `createContext`), e num empacotador de RSC TODO export de
5
+ // um módulo com a diretiva vira REFERÊNCIA de cliente. O `cx` continuaria importável de um
6
+ // componente de servidor e quebraria ao ser CHAMADO — no consumidor, não aqui.
7
+ //
8
+ // Então o que não tem estado mora neste arquivo, SEM diretiva. O `internal.tsx` reexporta para os
9
+ // módulos de cliente não precisarem saber da diferença; o barril (`index.tsx`, que também é de
10
+ // servidor) importa DAQUI.
11
+ //
12
+ // Mesmo desenho da referência: no shadcn/ui o `cn` mora em `lib/utils.ts` sem diretiva, enquanto
13
+ // 43 dos 57 componentes de `registry/bases/aria/ui` a declaram — medido em 06/08/2026.
14
+ //
15
+ // `.tsx` sem JSX de propósito: os checks 11, 19 e 26 varrem `packages/react/src/*.tsx`, e um
16
+ // `.ts` aqui seria um arquivo que gate nenhum enxerga.
17
+ export const cx = (...v) => v.filter(Boolean).join(" ");
18
+ export const universalStates = ["waiting_user", "waiting_approval", "waiting_dependency", "offline", "stale", "partial", "degraded"];
19
+ // Nenhum dos sete é FALHA: nos sete a tela AINDA SERVE, e é isso que os separa de `error`. Por
20
+ // isso o teto de gravidade é `warning` e `danger` não aparece — quem espera é informado, quem
21
+ // perdeu qualidade é avisado. Um `role="alert"` aqui interromperia o leitor de tela por uma
22
+ // condição que não pede ação imediata, que é o oposto do que o papel serve.
23
+ export const stateSeverity = (state) => state.startsWith("waiting_") ? "info" : "warning";
24
+ export const defaultStrings = { close: "Close", confirmCancel: "Cancel", dataError: "This could not be loaded.", dataEmpty: "Nothing here yet", confirmProceed: "Continue", paginationLabel: "Pagination", previous: "Previous", next: "Next", breadcrumbLabel: "Breadcrumb", tabsLabel: "Tabs", optionsLabel: "Options", tableLabel: "Table", commandLabel: "Command palette", commandPlaceholder: "Type a command…", dismissNotification: "Dismiss notification", toolbarLabel: "Toolbar", loading: "Loading", otpDigit: "Digit", stepperLabel: "Steps", increment: "Increase", decrement: "Decrease", comboboxEmpty: "No results", comboboxClear: "Clear selection", comboboxOpen: "Open list", comboboxRemove: "Remove", comboboxLoading: "Loading…", fileDropPrompt: "Drag files here or click to select", fileAdded: "File added", fileRemoved: "File removed", fileRemove: "Remove", fileTooLarge: "File exceeds the size limit", fileWrongType: "File type not allowed", treeLabel: "Tree", notificationsLabel: "Notifications", notificationMarkAll: "Mark all as read", notificationEmpty: "No notifications", notificationUnread: "Unread", notificationNew: "new notifications", dataGridFilter: "Filter", dataGridEmpty: "No results", dataGridSelectAll: "Select all rows", dataGridSelectRow: "Select row", dataGridSelected: "selected", dataGridClearSelection: "Clear selection", dataGridBulkLabel: "Bulk actions", dataGridColumns: "Columns", dataGridResize: "Resize column", dataGridStale: "Showing data that may be out of date.", dataGridPartial: "Some rows could not be loaded. What you see is incomplete.", dataGridError: "The rows could not be loaded.", dataGridDetails: "Details", dataGridDetailPanel: "Row detail", dataGridExport: "Export", dataGridExportRows: "rows", dataGridExportFiltered: "filtered rows", dataGridExportSelected: "selected rows", mediaPlayer: "Media player", mediaPlay: "Play", mediaPause: "Pause", mediaMute: "Mute", mediaUnmute: "Unmute", mediaSeek: "Seek", mediaVolume: "Volume", mediaCaptionsShow: "Show captions", mediaCaptionsHide: "Hide captions", mediaSkipBack: "Skip back 10 seconds", mediaSkipForward: "Skip forward 10 seconds", mediaFullscreenEnter: "Enter full screen", mediaFullscreenExit: "Exit full screen", carouselLabel: "Carousel", carouselSlide: "Slide", positionOf: "of", carouselPrev: "Previous slide", carouselNext: "Next slide", galleryLabel: "Gallery", sortableLabel: "Sortable list", sortableHandle: "Reorder", sortableHelp: "Press Space to pick this up, then Arrow Up and Arrow Down to move it. Space drops it, Escape puts it back.", sortableGrabbed: "Picked up", sortableDropped: "Dropped", sortableMoved: "Moved", sortableCanceled: "Put back", blockEditorLabel: "Content blocks", blockLabel: "Block", blockRemove: "Remove block", uploadSending: "Uploading", uploadCancel: "Cancel upload", uploadRetry: "Retry upload", uploadError: "Upload failed", uploadCanceled: "Upload canceled", uploadComplete: "Upload complete", uploadPause: "Pause upload", uploadResume: "Resume upload", uploadPaused: "Paused", uploadPending: "Waiting", uploadChecksum: "Checksum", uploadChecksumBad: "The server received different bytes than the ones sent.", fileConflict: "A file with this name is already in the queue", fileReplace: "Replace", fileKeepBoth: "Keep both", fileSkip: "Skip", uploadReceipt: "Receipt", uploadReceiptCopy: "Copy receipt", agentInspector: "Agent inspector", invocationLabel: "Invocation", invocationInput: "Input", invocationOutput: "Output", taskQueueLabel: "Task queue", taskState: { queued: "Queued", running: "Running", completed: "Completed", failed: "Failed", blocked: "Blocked", paused: "Paused" }, taskPriority: { low: "Low", medium: "Medium", high: "High" }, approvalLabel: "Approval", approvalApprove: "Approve", approvalDeny: "Deny", approvalApproved: "Approved", approvalDenied: "Denied", approvalDeadline: "Decide by", approvalRisk: { low: "Low risk", medium: "Medium risk", high: "High risk" }, permissionLabel: "Tool permissions", permissionAsk: "Ask", permissionAlways: "Always", permissionNever: "Never", eventStreamLabel: "Events", traceLabel: "Trace", healthLabel: "Health", healthState: { operational: "Operational", degraded: "Degraded", down: "Down", maintenance: "Maintenance", unknown: "Unknown" }, modelUsageLabel: "Model usage", usageMetric: { tokens: "Tokens", cost: "Cost", requests: "Requests" }, costMeterLabel: "Cost", costMeterSpent: "Spent", costMeterRemaining: "left", costMeterExceeded: "Over the limit", costMeterNear: "Spending is past the soft limit.", costMeterOver: "The limit has been reached. Further calls are blocked.", memoryLabel: "Memory ledger", memoryProvenance: "Where this came from", memoryOperation: { added: "Added", updated: "Updated", recalled: "Recalled", forgotten: "Forgotten" }, memoryScope: { episodic: "Episodic", semantic: "Semantic", procedural: "Procedural" }, agentMessageLabel: "Agent messages", agentMessageTo: "to", agentMessageBroadcast: "all agents", agentMessageReason: "Why it went this way", agentMessageKind: { request: "Request", response: "Response", handoff: "Handoff", broadcast: "Broadcast", error: "Error" }, automationWhen: "When", automationThen: "Then", automationEnabled: "Enabled", automationLastRun: "Last run", automationResult: { success: "Succeeded", failure: "Failed" }, graphLabel: "Dependency graph", agentState: { idle: "Idle", thinking: "Thinking", running: "Running", paused: "Paused", error: "Error", completed: "Completed" }, codeEditor: "Code editor", chatLabel: "Conversation", chatMessage: "Message", chatSend: "Send", qrCode: "QR code", chartLabel: "Chart", copyCode: "Copy code", tocLabel: "On this page", navigationToggle: "Navigation", sidebarLabel: "Sidebar", universalState: { waiting_user: "Waiting for someone to act.", waiting_approval: "Waiting for approval.", waiting_dependency: "Waiting for something else to finish.", offline: "No connection. This was loaded earlier.", stale: "This may be out of date.", partial: "Some of this could not be loaded.", degraded: "Working with reduced capability." } };
25
+ // pt-BR preservado como locale (mesmos valores que já eram o default): passe
26
+ // <AureaProvider strings={ptBR}> para restaurar português.
27
+ export const ptBR = { close: "Fechar", confirmCancel: "Cancelar", dataError: "Não foi possível carregar.", dataEmpty: "Ainda não há nada aqui", confirmProceed: "Continuar", paginationLabel: "Paginação", previous: "Anterior", next: "Próxima", breadcrumbLabel: "Breadcrumb", tabsLabel: "Abas", optionsLabel: "Opções", tableLabel: "Tabela", commandLabel: "Paleta de comandos", commandPlaceholder: "Digite um comando…", dismissNotification: "Dispensar notificação", toolbarLabel: "Barra de ferramentas", loading: "Carregando", otpDigit: "Dígito", stepperLabel: "Etapas", increment: "Aumentar", decrement: "Diminuir", comboboxEmpty: "Nenhum resultado", comboboxClear: "Limpar seleção", comboboxOpen: "Abrir lista", comboboxRemove: "Remover", comboboxLoading: "Carregando…", fileDropPrompt: "Arraste arquivos aqui ou clique para selecionar", fileAdded: "Arquivo adicionado", fileRemoved: "Arquivo removido", fileRemove: "Remover", fileTooLarge: "Arquivo maior que o limite", fileWrongType: "Tipo de arquivo não aceito", treeLabel: "Árvore", notificationsLabel: "Notificações", notificationMarkAll: "Marcar todas como lidas", notificationEmpty: "Nenhuma notificação", notificationUnread: "Não lida", notificationNew: "novas notificações", dataGridFilter: "Filtrar", dataGridEmpty: "Nenhum resultado", dataGridSelectAll: "Selecionar todas as linhas", dataGridSelectRow: "Selecionar linha", dataGridSelected: "selecionadas", dataGridClearSelection: "Limpar seleção", dataGridBulkLabel: "Ações em lote", dataGridColumns: "Colunas", dataGridResize: "Redimensionar coluna", dataGridStale: "Mostrando dados que podem estar desatualizados.", dataGridPartial: "Algumas linhas não puderam ser carregadas. O que aparece está incompleto.", dataGridError: "Não foi possível carregar as linhas.", dataGridDetails: "Detalhes", dataGridDetailPanel: "Detalhe da linha", dataGridExport: "Exportar", dataGridExportRows: "linhas", dataGridExportFiltered: "linhas filtradas", dataGridExportSelected: "linhas selecionadas", mediaPlayer: "Reprodutor de mídia", mediaPlay: "Reproduzir", mediaPause: "Pausar", mediaMute: "Silenciar", mediaUnmute: "Ativar som", mediaSeek: "Posição da reprodução", mediaVolume: "Volume", mediaCaptionsShow: "Ativar legendas", mediaCaptionsHide: "Desativar legendas", mediaSkipBack: "Voltar 10 segundos", mediaSkipForward: "Avançar 10 segundos", mediaFullscreenEnter: "Tela cheia", mediaFullscreenExit: "Sair da tela cheia", carouselLabel: "Carrossel", carouselSlide: "Slide", positionOf: "de", carouselPrev: "Slide anterior", carouselNext: "Próximo slide", galleryLabel: "Galeria", sortableLabel: "Lista ordenável", sortableHandle: "Reordenar", sortableHelp: "Aperte Espaço para pegar, e as setas para cima e para baixo para mover. Espaço solta, Esc devolve ao lugar.", sortableGrabbed: "Pego", sortableDropped: "Solto", sortableMoved: "Movido", sortableCanceled: "Devolvido", blockEditorLabel: "Blocos de conteúdo", blockLabel: "Bloco", blockRemove: "Remover bloco", uploadSending: "Enviando", uploadCancel: "Cancelar envio", uploadRetry: "Tentar envio novamente", uploadError: "Falha no envio", uploadCanceled: "Envio cancelado", uploadComplete: "Envio concluído", uploadPause: "Pausar envio", uploadResume: "Retomar envio", uploadPaused: "Pausado", uploadPending: "Aguardando", uploadChecksum: "Soma de verificação", uploadChecksumBad: "O servidor recebeu bytes diferentes dos enviados.", fileConflict: "Já existe um arquivo com este nome na fila", fileReplace: "Substituir", fileKeepBoth: "Manter os dois", fileSkip: "Pular", uploadReceipt: "Recibo", uploadReceiptCopy: "Copiar recibo", agentInspector: "Inspetor do agente", invocationLabel: "Invocação", invocationInput: "Entrada", invocationOutput: "Saída", taskQueueLabel: "Fila de tarefas", taskState: { queued: "Na fila", running: "Executando", completed: "Concluída", failed: "Falhou", blocked: "Bloqueada", paused: "Pausada" }, taskPriority: { low: "Baixa", medium: "Média", high: "Alta" }, approvalLabel: "Aprovação", approvalApprove: "Aprovar", approvalDeny: "Negar", approvalApproved: "Aprovado", approvalDenied: "Negado", approvalDeadline: "Decidir até", approvalRisk: { low: "Risco baixo", medium: "Risco médio", high: "Risco alto" }, permissionLabel: "Permissões de ferramenta", permissionAsk: "Perguntar", permissionAlways: "Sempre", permissionNever: "Nunca", eventStreamLabel: "Eventos", traceLabel: "Rastro", healthLabel: "Saúde", healthState: { operational: "Operando", degraded: "Degradado", down: "Fora do ar", maintenance: "Em manutenção", unknown: "Desconhecido" }, modelUsageLabel: "Consumo por modelo", usageMetric: { tokens: "Tokens", cost: "Custo", requests: "Chamadas" }, costMeterLabel: "Custo", costMeterSpent: "Gasto", costMeterRemaining: "restantes", costMeterExceeded: "Acima do limite", costMeterNear: "O gasto passou do limite brando.", costMeterOver: "O limite foi atingido. As próximas chamadas estão bloqueadas.", memoryLabel: "Livro-razão de memória", memoryProvenance: "De onde isto veio", memoryOperation: { added: "Guardada", updated: "Atualizada", recalled: "Lembrada", forgotten: "Esquecida" }, memoryScope: { episodic: "Episódica", semantic: "Semântica", procedural: "Procedural" }, agentMessageLabel: "Recados entre agentes", agentMessageTo: "para", agentMessageBroadcast: "todos os agentes", agentMessageReason: "Por que foi por aqui", agentMessageKind: { request: "Pedido", response: "Resposta", handoff: "Passagem", broadcast: "Difusão", error: "Erro" }, automationWhen: "Quando", automationThen: "Então", automationEnabled: "Ativa", automationLastRun: "Última execução", automationResult: { success: "Concluiu", failure: "Falhou" }, graphLabel: "Grafo de dependências", agentState: { idle: "Ocioso", thinking: "Pensando", running: "Executando", paused: "Pausado", error: "Erro", completed: "Concluído" }, codeEditor: "Editor de código", chatLabel: "Conversa", chatMessage: "Mensagem", chatSend: "Enviar", qrCode: "Código QR", chartLabel: "Gráfico", copyCode: "Copiar código", tocLabel: "Nesta página", navigationToggle: "Navegação", sidebarLabel: "Lateral", universalState: { waiting_user: "Esperando alguém agir.", waiting_approval: "Esperando aprovação.", waiting_dependency: "Esperando outra coisa terminar.", offline: "Sem conexão. Isto foi carregado antes.", stale: "Isto pode estar desatualizado.", partial: "Parte disto não pôde ser carregada.", degraded: "Funcionando com capacidade reduzida." } };
28
+ // Sprite de ícones: CONFIGURAÇÃO DE APLICAÇÃO, então entra pelo provider, uma vez.
29
+ // Antes o default absoluto "/aurea-icons.svg" vivia no Icon e 15 componentes declaravam
30
+ // e repassavam `spriteUrl` à mão — 52 sítios de código. Consequência: aplicação servida
31
+ // em subcaminho perdia TODOS os ícones, e para consertar tinha de passar a prop em cada
32
+ // componente (auditoria 26/07/2026, achado A4 — causa raiz do A3 daquela auditoria, que
33
+ // foi corrigido nos fallbacks do catálogo e não aqui). O default segue o mesmo para quem
34
+ // não configura nada; `Icon` aceita a prop como override local.
35
+ export const defaultSpriteUrl = "/aurea-icons.svg";
36
+ // Formato: `sort=-nome,execucoes` (o `-` é descendente) · `q=texto` · `page=2` ·
37
+ // `f.<coluna>=valor`, repetido quando a coluna é faceta. Só entra o que está
38
+ // ativo, então grade sem filtro nenhum deixa a URL limpa.
39
+ //
40
+ // `into` preserva o que já estava na busca: uma aplicação real tem `tab=`, `ref=`
41
+ // e companhia na mesma URL, e serializar a grade não pode apagá-los.
42
+ export function gridStateToParams(state, into) {
43
+ const p = new URLSearchParams(into);
44
+ for (const k of [...p.keys()])
45
+ if (k === "sort" || k === "q" || k === "page" || k.startsWith("f."))
46
+ p.delete(k);
47
+ if (state.sorting?.length)
48
+ p.set("sort", state.sorting.map(s => (s.desc ? "-" : "") + s.id).join(","));
49
+ if (state.globalFilter)
50
+ p.set("q", state.globalFilter);
51
+ // página 1 não vai para a URL: é o default, e escrevê-lo só suja o link.
52
+ if (state.page && state.page > 1)
53
+ p.set("page", String(state.page));
54
+ for (const f of state.columnFilters ?? []) {
55
+ if (Array.isArray(f.value)) {
56
+ for (const v of f.value)
57
+ p.append("f." + f.id, String(v));
58
+ }
59
+ else if (f.value != null && f.value !== "")
60
+ p.set("f." + f.id, String(f.value));
61
+ }
62
+ return p;
63
+ }
64
+ // `filters` é o MESMO array que a grade recebe, e serve para uma coisa só: saber
65
+ // se `f.estado=feito` volta como `"feito"` ou como `["feito"]`. Sem ele a decisão
66
+ // cai num palpite — repetido é lista, sozinho é texto —, e uma faceta com UM valor
67
+ // escolhido volta como texto e para de filtrar. Passe-o sempre que houver faceta.
68
+ export function gridStateFromParams(params, filters) {
69
+ const state = {};
70
+ const sort = params.get("sort");
71
+ if (sort)
72
+ state.sorting = sort.split(",").filter(Boolean).map(t => t.startsWith("-") ? { id: t.slice(1), desc: true } : { id: t, desc: false });
73
+ const q = params.get("q");
74
+ if (q)
75
+ state.globalFilter = q;
76
+ const page = Number(params.get("page"));
77
+ if (Number.isFinite(page) && page > 1)
78
+ state.page = Math.floor(page);
79
+ const colunas = [];
80
+ for (const k of new Set([...params.keys()].filter(k => k.startsWith("f.")))) {
81
+ const id = k.slice(2), vals = params.getAll(k);
82
+ colunas.push({ id, value: (filters ? filters.some(f => f.column === id && f.facet) : vals.length > 1) ? vals : vals[0] });
83
+ }
84
+ if (colunas.length)
85
+ state.columnFilters = colunas;
86
+ return state;
87
+ }
88
+ const CHAVES_TELA = ["tab", "view", "detail"];
89
+ // `into` preserva o que já estava, pelo mesmo motivo do `gridStateToParams`: uma aplicação real
90
+ // tem `ref=`, `utm_*` e companhia na mesma URL, e serializar a tela não pode apagá-los. O que se
91
+ // apaga é só o que ESTE formato escreve — senão um estado que saiu continuaria na URL.
92
+ export function screenStateToParams(state, into) {
93
+ const p = gridStateToParams(state, into);
94
+ for (const k of CHAVES_TELA)
95
+ p.delete(k);
96
+ for (const k of CHAVES_TELA) {
97
+ const v = state[k];
98
+ if (v)
99
+ p.set(k, v);
100
+ }
101
+ return p;
102
+ }
103
+ export function screenStateFromParams(params, filters) {
104
+ const state = gridStateFromParams(params, filters);
105
+ for (const k of CHAVES_TELA) {
106
+ const v = params.get(k);
107
+ if (v)
108
+ state[k] = v;
109
+ }
110
+ return state;
111
+ }
package/dist/qrcode.d.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import React from "react";
2
2
  import { type ErrorCorrection } from "qr";
3
+ export type QRCodeSize = "sm" | "md" | "lg";
3
4
  export interface QRCodeProps extends Omit<React.SVGAttributes<SVGSVGElement>, "children"> {
4
5
  value: string;
5
- size?: number;
6
+ size?: QRCodeSize;
6
7
  ecc?: ErrorCorrection;
7
8
  quietZone?: number;
8
9
  label?: string;
package/dist/qrcode.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  // Fase 9 (achado A5): este arquivo saiu do index.tsx de 970 linhas. Um módulo por categoria
3
4
  // do registry — a taxonomia já existia e é gateada. A ordem de import entre eles é um DAG:
@@ -14,7 +15,7 @@ import { cx, useAureaStrings } from "./internal.js";
14
15
  // --qr-quiet no CSS. Matriz da lib `qr` (0-dep, Apache-2.0, Paul Miller); o desenho é
15
16
  // nosso. ecc default "quartile": dots cobrem menos área que quadrados, então mais
16
17
  // correção de erro preserva a escaneabilidade. ponytail: um estilo (dots) só.
17
- export function QRCode({ value, size = 160, ecc = "quartile", quietZone = 4, label, className, ...props }) {
18
+ export function QRCode({ value, size = "md", ecc = "quartile", quietZone = 4, label, className, ...props }) {
18
19
  const s = useAureaStrings();
19
20
  const name = label ?? `${s.qrCode}: ${value}`;
20
21
  const m = encodeQR(value, "raw", { ecc, border: quietZone });
@@ -30,5 +31,5 @@ export function QRCode({ value, size = 160, ecc = "quartile", quietZone = 4, lab
30
31
  // olho redondo: anel externo (raio 3.5) → furo (2.5, cor do fundo) → centro (1.5).
31
32
  // os raios preservam a proporção 7:5:3 do finder, então o leitor ainda o reconhece.
32
33
  const eyeShapes = eyes.map(([ex, ey], i) => { const cx = ex + 3.5, cy = ey + 3.5; return _jsxs(React.Fragment, { children: [_jsx("circle", { className: "qr-mod", cx: cx, cy: cy, r: 3.5 }), _jsx("circle", { className: "qr-eye-gap", cx: cx, cy: cy, r: 2.5 }), _jsx("circle", { className: "qr-mod", cx: cx, cy: cy, r: 1.5 })] }, `eye${i}`); });
33
- return _jsxs("svg", { className: cx("qrcode", className), role: "img", "aria-label": name, viewBox: `0 0 ${n} ${n}`, width: size, height: size, ...props, children: [_jsx("title", { children: name }), eyeShapes, dots] });
34
+ return _jsxs("svg", { className: cx("qrcode", size !== "md" && `qrcode-${size}`, className), role: "img", "aria-label": name, viewBox: `0 0 ${n} ${n}`, ...props, children: [_jsx("title", { children: name }), eyeShapes, dots] });
34
35
  }
package/dist/system.d.ts CHANGED
@@ -1,13 +1,23 @@
1
1
  import React, { type ReactNode } from "react";
2
2
  import { type AureaStrings } from "./internal.js";
3
- export declare function AureaProvider({ children, strings, direction, spriteUrl }: {
3
+ export declare function AureaProvider({ children, strings, direction, spriteUrl, portalContainer }: {
4
4
  children: ReactNode;
5
5
  strings?: Partial<AureaStrings>;
6
6
  direction?: "ltr" | "rtl";
7
7
  spriteUrl?: string;
8
+ portalContainer?: HTMLElement | null;
8
9
  }): React.JSX.Element;
9
10
  export type AureaToastType = "info" | "success" | "warning" | "danger";
10
11
  export declare const useToast: () => import("@base-ui/react").UseToastManagerReturnValue<any>;
12
+ export type AureaThemeName = "dark" | "light";
13
+ export type AureaDensity = "compact" | "comfortable" | "spacious";
14
+ export declare function useAureaTheme(): {
15
+ theme: AureaThemeName | null;
16
+ density: AureaDensity | null;
17
+ setTheme: (t: AureaThemeName) => void;
18
+ setDensity: (d: AureaDensity) => void;
19
+ toggleTheme: () => void;
20
+ };
11
21
  export type IconName = string;
12
22
  export interface IconProps extends React.SVGAttributes<SVGSVGElement> {
13
23
  name: IconName;
package/dist/system.js CHANGED
@@ -1,3 +1,4 @@
1
+ "use client";
1
2
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
3
  // Fase 9 (achado A5): este arquivo saiu do index.tsx de 970 linhas. Um módulo por categoria
3
4
  // do registry — a taxonomia já existia e é gateada. A ordem de import entre eles é um DAG:
@@ -6,19 +7,73 @@ import React from "react";
6
7
  import { Toast as BaseToast } from "@base-ui/react/toast";
7
8
  import { Tooltip as BaseTooltip } from "@base-ui/react/tooltip";
8
9
  import { DirectionProvider } from "@base-ui/react/direction-provider";
9
- import { cx, StringsContext, SpriteContext, defaultStrings, defaultSpriteUrl, useSpriteUrl, useAureaStrings } from "./internal.js";
10
- export function AureaProvider({ children, strings, direction = "ltr", spriteUrl = defaultSpriteUrl }) {
10
+ import { cx, StringsContext, SpriteContext, PortalContext, defaultStrings, defaultSpriteUrl, useSpriteUrl, useAureaStrings, usePortalContainer } from "./internal.js";
11
+ // `portalContainer` (achado B7, Parte C do PLANO-1.0): onde TODO popup da biblioteca é montado.
12
+ // Configuração de aplicação, então entra aqui uma vez — o mesmo raciocínio do `spriteUrl`, e
13
+ // pela mesma razão medida: com prop por componente seriam nove sítios repassando a mesma coisa
14
+ // à mão, que é o achado A4 de novo.
15
+ // Sem ela nada muda: o Base UI monta no `document.body`, que é o que permite empilhar e
16
+ // posicionar sem herdar `overflow` nem `transform`. Com ela, o consumidor aponta para um nó
17
+ // dentro do landmark dele e o conteúdo do popup deixa de ficar fora de qualquer marco.
18
+ export function AureaProvider({ children, strings, direction = "ltr", spriteUrl = defaultSpriteUrl, portalContainer }) {
11
19
  const value = React.useMemo(() => strings ? { ...defaultStrings, ...strings } : defaultStrings, [strings]);
12
- return _jsx(StringsContext.Provider, { value: value, children: _jsx(SpriteContext.Provider, { value: spriteUrl, children: _jsx(DirectionProvider, { direction: direction, children: _jsx(BaseToast.Provider, { children: _jsxs(BaseTooltip.Provider, { children: [children, _jsx(AureaToastViewport, {})] }) }) }) }) });
20
+ return _jsx(StringsContext.Provider, { value: value, children: _jsx(SpriteContext.Provider, { value: spriteUrl, children: _jsx(PortalContext.Provider, { value: portalContainer, children: _jsx(DirectionProvider, { direction: direction, children: _jsx(BaseToast.Provider, { children: _jsxs(BaseTooltip.Provider, { children: [children, _jsx(AureaToastViewport, {})] }) }) }) }) }) });
13
21
  }
14
22
  export const useToast = () => BaseToast.useToastManager();
23
+ // useAureaTheme (M7): ler e trocar os DOIS eixos que a Aurea põe no <html> — `data-theme` e
24
+ // `data-density`. Até aqui só existia `window.Aurea.setTheme` no `aurea.js`, que é vanilla: em
25
+ // React não havia como saber o tema atual sem enfiar a mão no DOM, e um botão de tema não sabia
26
+ // que ícone desenhar.
27
+ //
28
+ // O QUE ESTE HOOK NÃO FAZ, e é a parte mais importante dele — pesquisado em 13/08/2026, não
29
+ // suposto. O `next-themes` já resolve persistência, preferência do sistema, sincronia entre abas
30
+ // e o script embutido que evita o flash, e ele escreve **`data-theme` no <html>**, que é
31
+ // exatamente o atributo que a Aurea lê. Ou seja: os dois já se encaixam sem código nosso.
32
+ // Reescrever isso aqui seria trocar uma biblioteca mantida por uma cópia pior — e guardar
33
+ // preferência de usuário é decisão da APLICAÇÃO, não da biblioteca de interface (é o mesmo
34
+ // motivo pelo qual a persistência de tema do catálogo mora no catálogo).
35
+ // O que ele faz é o que biblioteca nenhuma faz: **densidade**, que é eixo da Aurea e não existe
36
+ // no `next-themes` nem em ninguém.
37
+ //
38
+ // `useSyncExternalStore` e não `useState`: o valor mora no DOM, e quem o troca pode ser outro —
39
+ // o `next-themes`, um script no <head>, ou o `window.Aurea` de sempre. Assinar a mutação do
40
+ // atributo é o que mantém o React em dia com quem manda de verdade.
41
+ //
42
+ // E `getServerSnapshot` devolve `null` de propósito. A armadilha está documentada no próprio
43
+ // `next-themes`: no servidor o tema é **desconhecido**, e fingir um valor produz erro de
44
+ // hidratação. Por isso o retorno é `theme: string|null` — enquanto for `null`, não desenhe UI que
45
+ // dependa do tema. É a mesma regra do "delay rendering until mounted", só que sem um `mounted`
46
+ // solto para o consumidor esquecer de checar.
47
+ const assinaHtml = (cb) => {
48
+ if (typeof MutationObserver === "undefined")
49
+ return () => { };
50
+ const obs = new MutationObserver(cb);
51
+ obs.observe(document.documentElement, { attributes: true, attributeFilter: ["data-theme", "data-density"] });
52
+ return () => obs.disconnect();
53
+ };
54
+ const leAtributo = (nome) => () => typeof document === "undefined" ? null : document.documentElement.getAttribute(nome);
55
+ const semServidor = () => null;
56
+ export function useAureaTheme() {
57
+ const theme = React.useSyncExternalStore(assinaHtml, leAtributo("data-theme"), semServidor);
58
+ const density = React.useSyncExternalStore(assinaHtml, leAtributo("data-density"), semServidor);
59
+ return React.useMemo(() => ({
60
+ theme, density,
61
+ setTheme: (t) => { document.documentElement.dataset.theme = t; },
62
+ setDensity: (d) => { document.documentElement.dataset.density = d; },
63
+ // Alternar é sobre o que está NA TELA, então `null` (servidor, ou ninguém escolheu ainda)
64
+ // resolve para claro e vira escuro — e não o contrário, que deixaria o primeiro clique sem
65
+ // efeito visível em quem estava no claro do sistema.
66
+ toggleTheme: () => { document.documentElement.dataset.theme = theme === "dark" ? "light" : "dark"; },
67
+ }), [theme, density]);
68
+ }
15
69
  function AureaToastList() {
16
70
  const { toasts } = BaseToast.useToastManager();
17
71
  const s = useAureaStrings();
18
72
  return _jsx(_Fragment, { children: toasts.map(t => (_jsxs(BaseToast.Root, { toast: t, className: cx("toast", t.type && `toast-${t.type}`), children: [_jsxs("div", { className: "toast-text", children: [_jsx(BaseToast.Title, { render: _jsx("strong", {}) }), t.description ? _jsx(BaseToast.Description, { className: "muted" }) : null] }), _jsx(BaseToast.Close, { className: "btn btn-ghost btn-icon btn-sm", "aria-label": s.dismissNotification, children: "\u00D7" })] }, t.id))) });
19
73
  }
20
74
  function AureaToastViewport() {
21
- return _jsx(BaseToast.Portal, { children: _jsx(BaseToast.Viewport, { className: "toast-stack", children: _jsx(AureaToastList, {}) }) });
75
+ const portal = usePortalContainer();
76
+ return _jsx(BaseToast.Portal, { container: portal, children: _jsx(BaseToast.Viewport, { className: "toast-stack", children: _jsx(AureaToastList, {}) }) });
22
77
  }
23
78
  // spriteUrl aqui é OVERRIDE local (dois sprites na mesma página, por exemplo). O normal é
24
79
  // não passar nada e deixar o AureaProvider dizer de onde vêm os glifos.
package/package.json CHANGED
@@ -1,8 +1,14 @@
1
1
  {
2
2
  "name": "@aurea-uds/react",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "React components for Aurea UDS. Import @aurea-uds/fonts/css and @aurea-uds/core/css alongside.",
5
- "keywords": ["aurea", "design-system", "react", "components", "ui"],
5
+ "keywords": [
6
+ "aurea",
7
+ "design-system",
8
+ "react",
9
+ "components",
10
+ "ui"
11
+ ],
6
12
  "license": "Apache-2.0",
7
13
  "repository": {
8
14
  "type": "git",
@@ -85,6 +91,22 @@
85
91
  "./qrcode": {
86
92
  "types": "./dist/qrcode.d.ts",
87
93
  "import": "./dist/qrcode.js"
94
+ },
95
+ "./chart": {
96
+ "types": "./dist/chart.d.ts",
97
+ "import": "./dist/chart.js"
98
+ },
99
+ "./calendar": {
100
+ "types": "./dist/calendar.d.ts",
101
+ "import": "./dist/calendar.js"
102
+ },
103
+ "./graph": {
104
+ "types": "./dist/graph.d.ts",
105
+ "import": "./dist/graph.js"
106
+ },
107
+ "./agents": {
108
+ "types": "./dist/agents.d.ts",
109
+ "import": "./dist/agents.js"
88
110
  }
89
111
  },
90
112
  "files": [
@@ -102,10 +124,13 @@
102
124
  "@codemirror/view": "^6.43.6",
103
125
  "@lezer/highlight": "^1.2.3",
104
126
  "@tanstack/react-table": "^8.21.3",
127
+ "@xyflow/react": "^12.11.2",
105
128
  "codemirror": "^6.0.2",
106
129
  "qr": "^0.6.0",
107
130
  "react": ">=19",
108
- "react-dom": ">=19"
131
+ "react-day-picker": "^10.0.1",
132
+ "react-dom": ">=19",
133
+ "recharts": "^3.10.1"
109
134
  },
110
135
  "peerDependenciesMeta": {
111
136
  "@codemirror/language": {
@@ -123,11 +148,20 @@
123
148
  "@tanstack/react-table": {
124
149
  "optional": true
125
150
  },
151
+ "react-day-picker": {
152
+ "optional": true
153
+ },
154
+ "recharts": {
155
+ "optional": true
156
+ },
126
157
  "codemirror": {
127
158
  "optional": true
128
159
  },
129
160
  "qr": {
130
161
  "optional": true
162
+ },
163
+ "@xyflow/react": {
164
+ "optional": true
131
165
  }
132
166
  },
133
167
  "devDependencies": {
@@ -139,6 +173,8 @@
139
173
  "codemirror": "^6.0.2",
140
174
  "qr": "^0.6.0",
141
175
  "react": "^19.2.0",
142
- "react-dom": "^19.2.0"
176
+ "react-day-picker": "^10.0.1",
177
+ "react-dom": "^19.2.0",
178
+ "recharts": "^3.10.1"
143
179
  }
144
180
  }