@aurea-uds/react 0.31.0 → 0.32.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.
package/dist/graph.js CHANGED
@@ -39,7 +39,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
39
39
  // Quem importa a folha é o CONSUMIDOR, uma vez, como já importa o `@aurea-uds/core/css`: um
40
40
  // `import "…css"` dentro deste módulo quebraria em Node puro e o build daqui é `tsc` só.
41
41
  import React from "react";
42
- import { ReactFlow, ReactFlowProvider, Background, BaseEdge, EdgeLabelRenderer, EdgeText, Handle, MiniMap, Panel, Position, SelectionMode, applyNodeChanges, getBezierPath, getSmoothStepPath, useOnViewportChange, useReactFlow, useStore } from "@xyflow/react";
42
+ import { ReactFlow, ReactFlowProvider, Background, BaseEdge, EdgeLabelRenderer, EdgeText, Handle, MiniMap, Panel, Position, SelectionMode, applyNodeChanges, getBezierPath, getSmoothStepPath, useNodesInitialized, useOnViewportChange, useReactFlow, useStore } from "@xyflow/react";
43
43
  import { cx, useAureaStrings } from "./internal.js";
44
44
  import { Icon } from "./system.js";
45
45
  import { Badge } from "./markup.js";
@@ -73,6 +73,8 @@ const FOLGA_DO_DESVIO = 8, MALHA_DO_DESVIO = 8;
73
73
  const ESCALA_DOS_ROTULOS = 0.6;
74
74
  // O mapa grande (MNT-19.1) precisa caber na tela: o motor para em 50% por padrão, e um site de 100
75
75
  // equipamentos com andares não cabe nisso. Afasta até 10%.
76
+ // A margem que o motor põe em volta do mapa ao caber na tela (o padrão do `fitView` dele, 10%).
77
+ const MARGEM_DO_MOTOR = 0.1;
76
78
  const ESCALA_MINIMA = 0.1;
77
79
  // O VÃO ENTRE COLUNAS CRESCE COM O RÓTULO (A-09, 23/09/2026). Com o rótulo legível, a primeira
78
80
  // imagem mostrou o que o preto escondia: "Te1/1/1 ↔ Te1/0/1" é mais largo que 90px e entrava por
@@ -405,13 +407,21 @@ const ArestaAurea = React.memo(function ArestaAurea({ id, sourceX, sourceY, targ
405
407
  // rótulo vai para a pastilha de HTML do meio, junto deles — dois desenhos no mesmo ponto se cobririam.
406
408
  // O traço DUPLO desenha o miolo por cima da linha — e por cima do rótulo SVG, que sairia riscado
407
409
  // (medido na bancada). Com rótulo, ele também vai para a pastilha.
408
- const pastilha = !!(d.marca || d.contagem || d.grupo || (d.padrao === "double" && label != null));
409
- const cls = cx("graph-edge", d.padrao && d.padrao !== "solid" && `graph-edge-${d.padrao}`, d.peso && d.peso !== "regular" && `graph-edge-${d.peso}`, d.apagada && "is-dimmed");
410
+ const pastilha = !!(d.marca || d.marcaDoEstado || d.contagem || d.grupo || (d.padrao === "double" && label != null));
411
+ const cls = cx("graph-edge", d.padrao && d.padrao !== "solid" && `graph-edge-${d.padrao}`, d.peso && d.peso !== "regular" && `graph-edge-${d.peso}`, d.tom && d.tom !== "neutral" && `graph-edge-tone-${d.tom}`, d.apagada && "is-dimmed");
410
412
  // MNT-12.5: cada rótulo leva quem é, a prioridade e a ordem — o mapa esconde o que encosta.
411
413
  const marca = (parte) => ({ "data-edge-label": `${id}${parte}`, "data-priority": d.prioridade ?? 0, "data-order": d.ordem ?? 0 });
412
- return _jsxs(_Fragment, { children: [_jsx(BaseEdge, { id: id, path: caminho, className: cls, markerEnd: markerEnd, style: style }), d.padrao === "double" && _jsx("path", { d: caminho, fill: "none", className: cx("graph-edge-double-core", d.peso && d.peso !== "regular" && `graph-edge-${d.peso}`, d.apagada && "is-dimmed") }), !pastilha && label != null && _jsx(EdgeText, { x: lx, y: ly, label: label, labelStyle: ROTULO, labelShowBg: true, labelBgStyle: FUNDO_DO_ROTULO, className: cx("graph-edge-text", d.apagada && "is-dimmed"), ...marca("") }), (pastilha || d.origem || d.destino) && _jsxs(EdgeLabelRenderer, { children: [pastilha && _jsxs("div", { className: cx("graph-edge-chip nodrag nopan", d.apagada && "is-dimmed"), style: { transform: `translate(-50%,-50%) translate(${lx}px,${ly}px)` }, ...marca(""), children: [d.marca && _jsx("span", { className: `graph-edge-mark graph-edge-mark-${d.marca}`, "aria-hidden": "true", children: d.marca === "lock" && _jsx(Icon, { name: "lock-key", size: "sm" }) }), label != null && _jsx("span", { className: "graph-edge-chip-text", children: label }), d.contagem != null && _jsxs("span", { className: "graph-edge-count", children: ["\u00D7", d.contagem] }), d.grupo && _jsxs("button", { type: "button", className: "graph-edge-group", "aria-expanded": d.grupo.aberto, "aria-label": `${d.grupo.aberto ? d.grupo.juntar : d.grupo.mostrar} ${d.grupo.n} ${d.grupo.conexoes}`, onClick: d.grupo.alternar, children: ["\u00D7", d.grupo.n] })] }), d.origem && _jsx("div", { className: cx("graph-edge-end", d.apagada && "is-dimmed"), style: { transform: pontaDoRotulo(ini.x, ini.y, ladoIni) }, ...marca(":origem"), children: d.origem }), d.destino && _jsx("div", { className: cx("graph-edge-end", d.apagada && "is-dimmed"), style: { transform: pontaDoRotulo(fim.x, fim.y, ladoFim) }, ...marca(":destino"), children: d.destino })] })] });
414
+ return _jsxs(_Fragment, { children: [_jsx(BaseEdge, { id: id, path: caminho, className: cls, markerEnd: markerEnd, style: style }), d.padrao === "double" && _jsx("path", { d: caminho, fill: "none", className: cx("graph-edge-double-core", d.peso && d.peso !== "regular" && `graph-edge-${d.peso}`, d.tom && d.tom !== "neutral" && `graph-edge-tone-${d.tom}`, d.apagada && "is-dimmed") }), !pastilha && label != null && _jsx(EdgeText, { x: lx, y: ly, label: label, labelStyle: ROTULO, labelShowBg: true, labelBgStyle: FUNDO_DO_ROTULO, className: cx("graph-edge-text", d.apagada && "is-dimmed"), ...marca("") }), (pastilha || d.origem || d.destino) && _jsxs(EdgeLabelRenderer, { children: [pastilha && _jsxs("div", { className: cx("graph-edge-chip nodrag nopan", d.apagada && "is-dimmed"), style: { transform: `translate(-50%,-50%) translate(${lx}px,${ly}px)` }, ...marca(""), children: [d.marca && _jsx(MarcaDaLinha, { marca: d.marca }), d.marcaDoEstado && d.marcaDoEstado !== d.marca && _jsx(MarcaDaLinha, { marca: d.marcaDoEstado }), label != null && _jsx("span", { className: "graph-edge-chip-text", children: label }), d.contagem != null && _jsxs("span", { className: "graph-edge-count", children: ["\u00D7", d.contagem] }), d.grupo && _jsxs("button", { type: "button", className: "graph-edge-group", "data-edge-group": id, "aria-expanded": d.grupo.aberto, "aria-label": `${d.grupo.aberto ? d.grupo.juntar : d.grupo.mostrar} ${d.grupo.n} ${d.grupo.conexoes}`, onClick: d.grupo.alternar, children: ["\u00D7", d.grupo.n] })] }), d.origem && _jsx("div", { className: cx("graph-edge-end", d.apagada && "is-dimmed"), style: { transform: pontaDoRotulo(ini.x, ini.y, ladoIni) }, ...marca(":origem"), children: d.origem }), d.destino && _jsx("div", { className: cx("graph-edge-end", d.apagada && "is-dimmed"), style: { transform: pontaDoRotulo(fim.x, fim.y, ladoFim) }, ...marca(":destino"), children: d.destino })] })] });
413
415
  });
414
416
  const TIPOS_DE_ARESTA = { aurea: ArestaAurea };
417
+ /** A marca do meio da linha: o × e o ponto são desenho do CSS; o cadeado, o ícone. */
418
+ function MarcaDaLinha({ marca }) {
419
+ return _jsx("span", { className: `graph-edge-mark graph-edge-mark-${marca}`, "aria-hidden": "true", children: marca === "lock" && _jsx(Icon, { name: "lock-key", size: "sm" }) });
420
+ }
421
+ /** A amostra de uma linha na legenda: o traço, o miolo do duplo e a marca — o mesmo desenho do mapa. */
422
+ function AmostraDaLinha({ padrao, peso, tom, marca }) {
423
+ return _jsxs(_Fragment, { children: [_jsxs("svg", { className: "graph-legend-sample", "aria-hidden": "true", viewBox: "0 0 32 8", children: [_jsx("path", { d: "M0 4H32", className: cx("graph-edge", padrao && padrao !== "solid" && `graph-edge-${padrao}`, peso && peso !== "regular" && `graph-edge-${peso}`, tom && tom !== "neutral" && `graph-edge-tone-${tom}`) }), padrao === "double" && _jsx("path", { d: "M0 4H32", className: cx("graph-edge-double-core", peso && peso !== "regular" && `graph-edge-${peso}`) })] }), marca && _jsx(MarcaDaLinha, { marca: marca })] });
424
+ }
415
425
  /** A chave de um PAR sem sentido: o cabo entre A e B é o mesmo que entre B e A. */
416
426
  const parSemSentido = (e) => e.from < e.to ? `${e.from}|${e.to}` : `${e.to}|${e.from}`;
417
427
  /**
@@ -1085,20 +1095,35 @@ export function DependencyGraph({ nodes, edges, label, selectedId, onSelect, con
1085
1095
  onEdgeSelect(id);
1086
1096
  } } } } : {}),
1087
1097
  hidden: ocultos.has(e.from) || ocultos.has(e.to),
1088
- data: { deslocamento: rota ? 0 : ident[i].deslocamento, vertical, forma: edgeShape, padrao: e.pattern, peso: e.weight, marca: e.mark, contagem: e.count,
1098
+ data: { deslocamento: rota ? 0 : ident[i].deslocamento, vertical, forma: edgeShape, padrao: e.pattern, peso: e.weight, tom: e.status?.tone, marca: e.mark, marcaDoEstado: e.status?.mark, contagem: e.count,
1089
1099
  origem: e.sourceLabel, destino: e.targetLabel, apagada: aceso?.arestas ? !aceso.arestas.has(e.id ?? id) : aceso?.nos ? !(aceso.nos.has(e.from) && aceso.nos.has(e.to)) : false,
1090
1100
  grupo: grupo ? { n: grupo.n, aberto: grupo.aberto, alternar: () => alternarGrupo(grupo.chave), mostrar: s.graphShow, juntar: s.graphJoin, conexoes: s.graphConnections } : undefined,
1091
1101
  rota, saltos: sl ? [...sl] : undefined, prioridade: e.priority, ordem: i },
1092
1102
  };
1093
1103
  }), [desenhadas, ident, tracados, saltos, vertical, edgeShape, onEdgeSelect, ocultos, aceso, alternarGrupo, s, nomeDe]);
1094
- // A LEGENDA se monta com o que está na tela: uma linha por nome de `legend`, com o desenho dela.
1104
+ // A LEGENDA se monta com as linhas, em DUAS PARTES (decisão do Victor, 12/10/2026, depois da pesquisa
1105
+ // nas referências de mapa dele): o TIPO da ligação (`legend`, pelo desenho, SEM cor) e o ESTADO
1106
+ // (`status`, pela cor). Nenhuma das referências de mapa junta as duas coisas numa lista: uma legenda só
1107
+ // o tipo, pelo desenho; as outras pintam o estado. Cada amostra mostra o que TODAS as linhas do grupo têm em comum
1108
+ // — a espessura da velocidade varia dentro da "Fibra" e não é dela. A marca de cada parte é a SUA: o
1109
+ // `mark` da linha na do tipo (o cadeado da VPN), o `status.mark` na do estado (o × do "Caído"). Com uma
1110
+ // linha só não dá para adivinhar de quem é a marca — por isso o app diz.
1095
1111
  const legenda = React.useMemo(() => {
1096
- const vistas = new Map();
1097
- for (const e of edges)
1098
- if (e.legend && !vistas.has(e.legend))
1099
- vistas.set(e.legend, e);
1100
- return [...vistas.entries()];
1112
+ const comum = (xs) => xs.every(x => x === xs[0]) ? xs[0] : undefined;
1113
+ const agrupar = (nome) => {
1114
+ const m = new Map();
1115
+ for (const e of edges) {
1116
+ const k = nome(e);
1117
+ if (k)
1118
+ m.set(k, [...(m.get(k) ?? []), e]);
1119
+ }
1120
+ return [...m.entries()];
1121
+ };
1122
+ const estados = agrupar(e => e.status?.label).map(([nome, es]) => ({ nome, tom: comum(es.map(e => e.status?.tone)), marca: comum(es.map(e => e.status?.mark)) }));
1123
+ const tipos = agrupar(e => e.legend).map(([nome, es]) => ({ nome, padrao: comum(es.map(e => e.pattern)), peso: comum(es.map(e => e.weight)), marca: comum(es.map(e => e.mark)) }));
1124
+ return { tipos, estados };
1101
1125
  }, [edges]);
1126
+ const idDaLegenda = React.useId();
1102
1127
  // O texto que o MOTOR põe na tela (descrição do nó para o leitor de tela, aviso de "movido", nome das
1103
1128
  // alças e do minimapa) sai na língua da Aurea — o padrão dele é inglês.
1104
1129
  const rotulosDoMotor = React.useMemo(() => ({
@@ -1110,13 +1135,134 @@ export function DependencyGraph({ nodes, edges, label, selectedId, onSelect, con
1110
1135
  }), [s]);
1111
1136
  const linhas = React.useMemo(() => desenhadas.map(({ item }, i) => ({ item, rota: tracados.mapa.get(ident[i].id) })), [desenhadas, tracados, ident]);
1112
1137
  const raiz = React.useRef(null);
1138
+ // MNT-21 (opção "A" do Victor, 12/10/2026): O MAPA DE LEITURA É UMA PARADA DE TAB. O app mediu 87
1139
+ // paradas, as 59 linhas antes de qualquer nó (o motor desenha as linhas antes dos nós). Agora só o nó
1140
+ // atual (o último visitado; no começo, o primeiro) fica na ordem do Tab; as setas andam de nó em nó;
1141
+ // com o nó em foco, o Tab passa pelo botão de fechar dele e pelas linhas dele, e depois sai do mapa.
1142
+ // Numa linha em foco, as setas levam às pontas dela. O link de crédito do motor sai do Tab (continua à
1143
+ // vista). No modo de arrumar quem manda é o motor, e nada disto liga.
1144
+ const linhasDoNo = React.useMemo(() => {
1145
+ const porNo = new Map(), pontas = new Map();
1146
+ desenhadas.forEach(({ item }, i) => {
1147
+ const id = ident[i].id;
1148
+ pontas.set(id, { de: item.from, para: item.to });
1149
+ for (const n of [item.from, item.to]) {
1150
+ const l = porNo.get(n) ?? [];
1151
+ if (!l.includes(id))
1152
+ l.push(id);
1153
+ porNo.set(n, l);
1154
+ }
1155
+ });
1156
+ const pai = new Map(nodes.filter(n => n.parentId).map(n => [n.id, n.parentId]));
1157
+ return { porNo, pontas, pai };
1158
+ }, [desenhadas, ident, nodes]);
1159
+ const linhasRef = React.useRef(linhasDoNo);
1160
+ linhasRef.current = linhasDoNo;
1161
+ React.useEffect(() => {
1162
+ const el = raiz.current;
1163
+ if (!el || editavel)
1164
+ return;
1165
+ let atual = null, quadro = 0;
1166
+ const sequencia = (id) => {
1167
+ const no = el.querySelector(`.react-flow__node[data-id="${escapar(id)}"]`);
1168
+ if (!no)
1169
+ return [];
1170
+ const ancora = ancoraDoNo(el, id);
1171
+ const seq = ancora ? [ancora, ...[...no.querySelectorAll("button.graph-node-toggle, button.graph-group-toggle")].filter(b => b !== ancora)] : [];
1172
+ // O nó dentro de um contêiner aberto leva também o "Fechar" dele: o contêiner aberto não é alvo das
1173
+ // setas (o centro dele é o meio da caixa grande), e o botão dele não pode ficar fora de alcance.
1174
+ const pai = linhasRef.current.pai.get(id);
1175
+ const fecharPai = pai ? el.querySelector(`.react-flow__node[data-id="${escapar(pai)}"] button.graph-group-toggle`) : null;
1176
+ if (fecharPai && !seq.includes(fecharPai))
1177
+ seq.push(fecharPai);
1178
+ for (const l of linhasRef.current.porNo.get(id) ?? []) {
1179
+ const linha = el.querySelector(`.react-flow__edge[data-id="${escapar(l)}"]`);
1180
+ if (linha && linha.hasAttribute("tabindex"))
1181
+ seq.push(linha);
1182
+ const grupo = el.querySelector(`[data-edge-group="${escapar(l)}"]`);
1183
+ if (grupo)
1184
+ seq.push(grupo);
1185
+ }
1186
+ return seq;
1187
+ };
1188
+ const aplicar = () => {
1189
+ const todos = [...el.querySelectorAll(".react-flow__node button, .react-flow__edge[tabindex], .graph-edge-group, .react-flow__attribution a")];
1190
+ if (!atual || !ancoraDoNo(el, atual)) {
1191
+ const ids = [...el.querySelectorAll(".react-flow__node")].map(n => n.dataset.id);
1192
+ atual = ids.find(id => el.querySelector(`.react-flow__node[data-id="${escapar(id)}"] button.graph-node-body`))
1193
+ ?? ids.find(id => ancoraDoNo(el, id)) ?? null;
1194
+ }
1195
+ const ancora = atual ? ancoraDoNo(el, atual) : null;
1196
+ for (const t of todos)
1197
+ t.tabIndex = t === ancora ? 0 : -1;
1198
+ };
1199
+ const depois = () => { cancelAnimationFrame(quadro); quadro = requestAnimationFrame(aplicar); };
1200
+ const aoFocar = (e) => {
1201
+ const no = e.target.closest(".react-flow__node");
1202
+ if (no?.dataset.id && no.dataset.id !== atual) {
1203
+ atual = no.dataset.id;
1204
+ aplicar();
1205
+ }
1206
+ };
1207
+ const aoTeclar = (e) => {
1208
+ const alvo = e.target;
1209
+ if (!atual)
1210
+ return;
1211
+ const seq = sequencia(atual), i = seq.indexOf(alvo);
1212
+ if (i < 0)
1213
+ return;
1214
+ if (e.key === "Tab") {
1215
+ if (e.shiftKey ? i > 0 : i < seq.length - 1) {
1216
+ e.preventDefault();
1217
+ seq[e.shiftKey ? i - 1 : i + 1].focus({ preventScroll: true });
1218
+ return;
1219
+ }
1220
+ // A última da sequência: o Tab do navegador segue para depois do mapa. A âncora sai da ordem por
1221
+ // um instante — ela vem DEPOIS das linhas no documento, e o Tab voltaria a ela.
1222
+ if (!e.shiftKey) {
1223
+ const a = seq[0];
1224
+ a.tabIndex = -1;
1225
+ setTimeout(aplicar, 0);
1226
+ }
1227
+ return;
1228
+ }
1229
+ if (!SETAS.has(e.key))
1230
+ return;
1231
+ const linha = alvo.closest(".react-flow__edge")?.dataset.id ?? alvo.dataset.edgeGroup;
1232
+ if (linha) {
1233
+ // Numa linha, as setas levam às pontas: para cima ou para a esquerda, a de onde ela sai.
1234
+ const pt = linhasRef.current.pontas.get(linha);
1235
+ if (!pt)
1236
+ return;
1237
+ e.preventDefault();
1238
+ ancoraDoNo(el, e.key === "ArrowUp" || e.key === "ArrowLeft" ? pt.de : pt.para)?.focus({ preventScroll: true });
1239
+ return;
1240
+ }
1241
+ // O botão do nó já anda pelas setas; o de fechar anda igual.
1242
+ if (!alvo.matches("button.graph-node-body")) {
1243
+ e.preventDefault();
1244
+ teclado.current?.(atual, e.key);
1245
+ }
1246
+ };
1247
+ aplicar();
1248
+ const obs = new MutationObserver(depois);
1249
+ obs.observe(el, { childList: true, subtree: true });
1250
+ el.addEventListener("focusin", aoFocar);
1251
+ el.addEventListener("keydown", aoTeclar);
1252
+ return () => { obs.disconnect(); cancelAnimationFrame(quadro); el.removeEventListener("focusin", aoFocar); el.removeEventListener("keydown", aoTeclar); };
1253
+ }, [editavel]);
1113
1254
  // `initialWidth`/`initialHeight` no provider é o par do de cima, um nível acima: é o viewport
1114
1255
  // que o `fitView` usa ENQUANTO ninguém mediu. Com o prefixo `initial`, o navegador sobrescreve
1115
1256
  // na primeira medição — passar `width`/`height` direto no ReactFlow fixaria o tamanho e mataria
1116
1257
  // a fluidez. O valor é a extensão do próprio layout, então no servidor o grafo cabe exato.
1117
1258
  const estilo = { ...style, ...(height ? { blockSize: height } : null), "--graph-node-w": `${m.larg}px` };
1118
1259
  return _jsx("div", { ref: raiz, className: cx("dependency-graph", className), style: estilo, "data-text": textSize === "md" ? undefined : textSize, "data-contrast": highContrast ? "high" : undefined, "data-editable": editavel || undefined, role: "group", "aria-label": label ?? s.graphLabel, ...props, children: _jsx(ReactFlowProvider, { initialNodes: nosDoMotor, initialEdges: arestasDoMotor, fitView: true, initialWidth: automatico.extensao.larg, initialHeight: automatico.extensao.alt, children: _jsxs(ReactFlow, { nodes: nosVivos, onNodesChange: aoMudarNos, edges: arestasDoMotor, nodeTypes: TIPOS, edgeTypes: TIPOS_DE_ARESTA, fitView: true, proOptions: { hideAttribution: false }, minZoom: ESCALA_MINIMA, nodesDraggable: editavel || !!onNodeMove, nodesConnectable: !!connectable, elementsSelectable: editavel, nodesFocusable: editavel, edgesFocusable: !!onEdgeSelect, disableKeyboardA11y: !editavel, selectionOnDrag: editavel, panOnDrag: editavel ? BOTOES_DE_ARRASTAR : true, selectionMode: SelectionMode.Partial, multiSelectionKeyCode: TECLAS_DE_SOMAR, deleteKeyCode: null, snapToGrid: editavel && grid, snapGrid: [GRADE, GRADE], onlyRenderVisibleElements: !!visibleOnly, ariaLabelConfig: rotulosDoMotor, onSelectionChange: editavel ? aoMudarEscolha : undefined, onNodeMouseEnter: onNodeHover ? (_, no) => onNodeHover(no.id) : undefined, onNodeMouseLeave: onNodeHover ? () => onNodeHover(null) : undefined, onNodeContextMenu: onNodeContextMenu ? (ev, no) => { ev.preventDefault(); onNodeContextMenu(no.id, { x: ev.clientX, y: ev.clientY }); } : undefined, onEdgeClick: onEdgeSelect ? (_, a) => onEdgeSelect(a.id) : undefined, onConnect: onConnect ? c => { if (c.source && c.target)
1119
- onConnect({ from: c.source, to: c.target, fromPort: c.sourceHandle ?? undefined, toPort: c.targetHandle ?? undefined }); } : undefined, children: [_jsx(Background, { gap: editavel && grid ? GRADE : undefined }), _jsx(Comandos, { raiz: raiz, teclado: teclado, focusId: focusId, pedidoDeCaber: pedidoDeCaber, controls: !!controls, apiRef: apiRef, linhas: linhas, forma: edgeShape, titulo: label ?? s.graphLabel, desenho: tracados, editavel: editavel, barra: barra, acoes: acoes }), minimap && _jsx(MiniMap, { pannable: true, zoomable: true, ariaLabel: s.graphOverview, className: "graph-minimap" }), legend && legenda.length > 0 && _jsx(Panel, { position: "bottom-left", children: _jsx("ul", { className: "graph-legend", "aria-label": s.graphLegend, children: legenda.map(([nome, e]) => _jsxs("li", { children: [_jsxs("svg", { className: "graph-legend-sample", "aria-hidden": "true", viewBox: "0 0 32 8", children: [_jsx("path", { d: "M0 4H32", className: cx("graph-edge", e.pattern && e.pattern !== "solid" && `graph-edge-${e.pattern}`, e.weight && e.weight !== "regular" && `graph-edge-${e.weight}`) }), e.pattern === "double" && _jsx("path", { d: "M0 4H32", className: cx("graph-edge-double-core", e.weight && e.weight !== "regular" && `graph-edge-${e.weight}`) })] }), e.mark && _jsx("span", { className: `graph-edge-mark graph-edge-mark-${e.mark}`, "aria-hidden": "true", children: e.mark === "lock" && _jsx(Icon, { name: "lock-key", size: "sm" }) }), _jsx("span", { children: nome })] }, nome)) }) })] }) }) });
1260
+ onConnect({ from: c.source, to: c.target, fromPort: c.sourceHandle ?? undefined, toPort: c.targetHandle ?? undefined }); } : undefined, children: [_jsx(Background, { gap: editavel && grid ? GRADE : undefined }), _jsx(Comandos, { raiz: raiz, teclado: teclado, focusId: focusId, pedidoDeCaber: pedidoDeCaber, controls: !!controls, apiRef: apiRef, linhas: linhas, forma: edgeShape, titulo: label ?? s.graphLabel, desenho: tracados, editavel: editavel, barra: barra, acoes: acoes }), minimap && _jsx(MiniMap, { pannable: true, zoomable: true, ariaLabel: s.graphOverview, className: "graph-minimap" }), legend && (legenda.tipos.length > 0 || legenda.estados.length > 0) && _jsx(Panel, { position: "bottom-left", children: _jsxs("div", { className: "graph-legend", role: "group", "aria-label": s.graphLegend, children: [legenda.tipos.length > 0 && _jsxs(_Fragment, { children: [legenda.estados.length > 0 && _jsx("p", { className: "graph-legend-title", id: `${idDaLegenda}-tipo`, children: s.graphLegendKind }), _jsx("ul", { "aria-labelledby": legenda.estados.length > 0 ? `${idDaLegenda}-tipo` : undefined, children: legenda.tipos.map(t => _jsxs("li", { children: [_jsx(AmostraDaLinha, { padrao: t.padrao, peso: t.peso, marca: t.marca }), _jsx("span", { children: t.nome })] }, t.nome)) })] }), legenda.estados.length > 0 && _jsxs(_Fragment, { children: [legenda.tipos.length > 0 && _jsx("p", { className: "graph-legend-title", id: `${idDaLegenda}-estado`, children: s.graphLegendStatus }), _jsx("ul", { "aria-labelledby": legenda.tipos.length > 0 ? `${idDaLegenda}-estado` : undefined, children: legenda.estados.map(e => _jsxs("li", { children: [_jsx(AmostraDaLinha, { tom: e.tom, marca: e.marca }), _jsx("span", { children: e.nome })] }, e.nome)) })] })] }) })] }) }) });
1261
+ }
1262
+ /** O primeiro alvo de Tab de um nó no mapa de leitura: o botão dele; sem ele, o de fechar. */
1263
+ function ancoraDoNo(raiz, id) {
1264
+ const no = raiz?.querySelector(`.react-flow__node[data-id="${escapar(id)}"]`);
1265
+ return no?.querySelector("button.graph-node-body") ?? no?.querySelector("button.graph-node-toggle, button.graph-group-toggle") ?? null;
1120
1266
  }
1121
1267
  // `CSS.escape` existe no navegador; fora dele (o teste em jsdom), as aspas bastam.
1122
1268
  const escapar = (id) => typeof CSS !== "undefined" && typeof CSS.escape === "function" ? CSS.escape(id) : id.replace(/[\x22\\]/g, "\\$&");
@@ -1162,9 +1308,53 @@ function Comandos({ raiz, teclado, focusId, pedidoDeCaber, controls, apiRef, lin
1162
1308
  if (c)
1163
1309
  rf.setCenter(c.x, c.y, { zoom: Math.max(rf.getZoom(), 1), duration: duracao() });
1164
1310
  }, [rf, centro]);
1311
+ // MNT-24 (12/10/2026): A BARRA DO MODO DE ARRUMAR COBRIA O TOPO DO MAPA — o nó de cima ficava atrás
1312
+ // dela até a pessoa rolar (medido pelo app). Os botões de zoom, no outro canto de cima, fazem o mesmo.
1313
+ // O "caber na tela" passa a reservar em cima a altura do mais alto dos dois, com a margem que o motor
1314
+ // dá a eles (`offsetTop`) dos dois lados; os outros lados ficam com a margem do motor (0,1, o padrão
1315
+ // dele). A reserva é MEDIDA: a barra quebra em mais linhas na tela estreita.
1316
+ const barraRef = React.useRef(null);
1317
+ const zoomRef = React.useRef(null);
1318
+ const [reserva, setReserva] = React.useState(0);
1319
+ React.useLayoutEffect(() => {
1320
+ const medir = () => {
1321
+ const alturas = [barraRef.current, zoomRef.current].filter((e) => !!e).map(e => e.offsetTop * 2 + e.offsetHeight);
1322
+ setReserva(alturas.length ? Math.max(...alturas) : 0);
1323
+ };
1324
+ medir();
1325
+ if (typeof ResizeObserver === "undefined")
1326
+ return;
1327
+ const ro = new ResizeObserver(medir);
1328
+ for (const e of [barraRef.current, zoomRef.current])
1329
+ if (e)
1330
+ ro.observe(e);
1331
+ return () => ro.disconnect();
1332
+ }, [editavel, controls]);
1333
+ const margem = React.useMemo(() => reserva ? { top: `${reserva}px`, right: MARGEM_DO_MOTOR, bottom: MARGEM_DO_MOTOR, left: MARGEM_DO_MOTOR } : MARGEM_DO_MOTOR, [reserva]);
1334
+ const caber = React.useCallback((duration = duracao()) => void rf.fitView({ padding: margem, duration }), [rf, margem]);
1335
+ // O primeiro "caber" é o do motor, antes de a reserva existir: quando os nós estão medidos e a reserva
1336
+ // chega, ele cabe de novo, uma vez. Depois disso, a barra que aparece ou some (ligar o modo de arrumar)
1337
+ // DESCE o mapa o tanto dela, sem mexer no zoom que a pessoa escolheu.
1338
+ const medidos = useNodesInitialized();
1339
+ const reservaAnterior = React.useRef(null);
1340
+ React.useEffect(() => {
1341
+ if (!medidos)
1342
+ return;
1343
+ const antes = reservaAnterior.current;
1344
+ reservaAnterior.current = reserva;
1345
+ if (antes === null) {
1346
+ if (reserva)
1347
+ requestAnimationFrame(() => caber(0));
1348
+ return;
1349
+ }
1350
+ if (reserva !== antes) {
1351
+ const v = rf.getViewport();
1352
+ void rf.setViewport({ ...v, y: v.y + reserva - antes });
1353
+ }
1354
+ }, [medidos, reserva, caber, rf]);
1165
1355
  // A arrumação chegou (ou a pessoa pediu "Reorganizar"): o mapa cabe de novo na tela.
1166
1356
  React.useEffect(() => { if (pedidoDeCaber)
1167
- requestAnimationFrame(() => rf.fitView({ duration: duracao() })); }, [pedidoDeCaber, rf]);
1357
+ requestAnimationFrame(() => caber()); }, [pedidoDeCaber, caber]);
1168
1358
  React.useEffect(() => { if (focusId)
1169
1359
  centralizar(focusId); }, [focusId, centralizar]);
1170
1360
  // AS SETAS (MNT-19.4): o nó mais perto na direção da seta, dentro de um cone de 45°. O foco vai
@@ -1176,8 +1366,13 @@ function Comandos({ raiz, teclado, focusId, pedidoDeCaber, controls, apiRef, lin
1176
1366
  if (!a)
1177
1367
  return;
1178
1368
  let melhor = null;
1179
- for (const n of rf.getNodes()) {
1180
- if (n.id === id || n.hidden || n.type !== "aurea")
1369
+ const nos = rf.getNodes();
1370
+ for (const n of nos) {
1371
+ if (n.id === id || n.hidden)
1372
+ continue;
1373
+ // O contêiner FECHADO é alvo das setas — fechado, ele é uma caixa só, e o botão dele abre. O aberto
1374
+ // não: o centro dele é o meio da caixa grande, e a seta pularia os nós de dentro.
1375
+ if (n.type === "aureaGrupo" ? nos.some(f => f.parentId === n.id && !f.hidden) : n.type !== "aurea")
1181
1376
  continue;
1182
1377
  const b = centro(n.id);
1183
1378
  if (!b)
@@ -1193,7 +1388,7 @@ function Comandos({ raiz, teclado, focusId, pedidoDeCaber, controls, apiRef, lin
1193
1388
  }
1194
1389
  if (!melhor)
1195
1390
  return;
1196
- const alvo = () => raiz.current?.querySelector(`.react-flow__node[data-id="${escapar(melhor.id)}"] button.graph-node-body`);
1391
+ const alvo = () => ancoraDoNo(raiz.current, melhor.id);
1197
1392
  const botao = alvo();
1198
1393
  if (!botao) {
1199
1394
  centralizar(melhor.id);
@@ -1248,7 +1443,7 @@ function Comandos({ raiz, teclado, focusId, pedidoDeCaber, controls, apiRef, lin
1248
1443
  return () => el.removeEventListener("keydown", atalho);
1249
1444
  }, [editavel, raiz, acoes]);
1250
1445
  React.useImperativeHandle(apiRef, () => ({
1251
- fitView: () => { void rf.fitView({ duration: duracao() }); },
1446
+ fitView: () => caber(),
1252
1447
  zoomIn: () => { void rf.zoomIn({ duration: duracao() }); },
1253
1448
  zoomOut: () => { void rf.zoomOut({ duration: duracao() }); },
1254
1449
  focus: centralizar,
@@ -1258,9 +1453,9 @@ function Comandos({ raiz, teclado, focusId, pedidoDeCaber, controls, apiRef, lin
1258
1453
  undo: () => acoes.current.desfazer(), redo: () => acoes.current.refazer(),
1259
1454
  align: b => acoes.current.alinhar(b), distribute: e => acoes.current.distribuir(e),
1260
1455
  relayout: () => acoes.current.reorganizar(), getLayout: () => acoes.current.arrumacao(),
1261
- }), [rf, centralizar, linhas, forma, titulo, raiz, acoes]);
1456
+ }), [rf, centralizar, linhas, forma, titulo, raiz, acoes, caber]);
1262
1457
  const a = acoes.current;
1263
- return _jsxs(_Fragment, { children: [editavel && _jsx(Panel, { position: "top-left", className: "graph-toolbar", children: _jsxs(Toolbar, { label: s.graphArrange, children: [_jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphUndo, disabled: !barra.podeDesfazer, onClick: () => a.desfazer(), children: _jsx(Icon, { name: "arrow-u-up-left" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphRedo, disabled: !barra.podeRefazer, onClick: () => a.refazer(), children: _jsx(Icon, { name: "arrow-u-up-right" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignLeft, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("left"), children: _jsx(Icon, { name: "align-left" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignCenter, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("center"), children: _jsx(Icon, { name: "align-center-horizontal" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignRight, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("right"), children: _jsx(Icon, { name: "align-right" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignTop, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("top"), children: _jsx(Icon, { name: "align-top" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignMiddle, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("middle"), children: _jsx(Icon, { name: "align-center-vertical" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignBottom, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("bottom"), children: _jsx(Icon, { name: "align-bottom" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphDistributeH, disabled: barra.alinhaveis < 3, onClick: () => a.distribuir("horizontal"), children: _jsx(Icon, { name: "arrows-out-line-horizontal" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphDistributeV, disabled: barra.alinhaveis < 3, onClick: () => a.distribuir("vertical"), children: _jsx(Icon, { name: "arrows-out-line-vertical" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphPin, disabled: !barra.escolhidos, onClick: () => a.fixar(), "aria-pressed": barra.todosFixos, children: _jsx(Icon, { name: "push-pin" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphRelayout, disabled: false, onClick: () => a.reorganizar(), children: _jsx(Icon, { name: "tree-structure" }) })] }) }), controls && _jsxs(Panel, { position: "top-right", className: "graph-controls", children: [_jsx(IconButton, { icon: "magnifying-glass-plus", label: s.graphZoomIn, onClick: () => void rf.zoomIn({ duration: duracao() }) }), _jsx(IconButton, { icon: "magnifying-glass-minus", label: s.graphZoomOut, onClick: () => void rf.zoomOut({ duration: duracao() }) }), _jsx(IconButton, { icon: "corners-out", label: s.graphFit, onClick: () => void rf.fitView({ duration: duracao() }) })] })] });
1458
+ return _jsxs(_Fragment, { children: [editavel && _jsx(Panel, { ref: barraRef, position: "top-left", className: "graph-toolbar", children: _jsxs(Toolbar, { label: s.graphArrange, children: [_jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphUndo, disabled: !barra.podeDesfazer, onClick: () => a.desfazer(), children: _jsx(Icon, { name: "arrow-u-up-left" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphRedo, disabled: !barra.podeRefazer, onClick: () => a.refazer(), children: _jsx(Icon, { name: "arrow-u-up-right" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignLeft, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("left"), children: _jsx(Icon, { name: "align-left" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignCenter, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("center"), children: _jsx(Icon, { name: "align-center-horizontal" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignRight, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("right"), children: _jsx(Icon, { name: "align-right" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignTop, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("top"), children: _jsx(Icon, { name: "align-top" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignMiddle, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("middle"), children: _jsx(Icon, { name: "align-center-vertical" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphAlignBottom, disabled: barra.alinhaveis < 2, onClick: () => a.alinhar("bottom"), children: _jsx(Icon, { name: "align-bottom" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphDistributeH, disabled: barra.alinhaveis < 3, onClick: () => a.distribuir("horizontal"), children: _jsx(Icon, { name: "arrows-out-line-horizontal" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphDistributeV, disabled: barra.alinhaveis < 3, onClick: () => a.distribuir("vertical"), children: _jsx(Icon, { name: "arrows-out-line-vertical" }) }), _jsx(ToolbarSeparator, {}), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphPin, disabled: !barra.escolhidos, onClick: () => a.fixar(), "aria-pressed": barra.todosFixos, children: _jsx(Icon, { name: "push-pin" }) }), _jsx(ToolbarButton, { className: "btn-icon", "aria-label": s.graphRelayout, disabled: false, onClick: () => a.reorganizar(), children: _jsx(Icon, { name: "tree-structure" }) })] }) }), controls && _jsxs(Panel, { ref: zoomRef, position: "top-right", className: "graph-controls", children: [_jsx(IconButton, { icon: "magnifying-glass-plus", label: s.graphZoomIn, onClick: () => void rf.zoomIn({ duration: duracao() }) }), _jsx(IconButton, { icon: "magnifying-glass-minus", label: s.graphZoomOut, onClick: () => void rf.zoomOut({ duration: duracao() }) }), _jsx(IconButton, { icon: "corners-out", label: s.graphFit, onClick: () => caber() })] })] });
1264
1459
  }
1265
1460
  /**
1266
1461
  * A FOTO do mapa (MNT-19.2), pelo `modern-screenshot` (peer OPCIONAL, MIT), carregado só aqui. Sai
@@ -15,7 +15,13 @@ export type IconName = PhosphorIconName | Extract<keyof AureaIconNames, string>;
15
15
  /**
16
16
  * O peso do ícone. `regular` é o de sempre; `fill` é o cheio, o do item escolhido (aba ativa,
17
17
  * item atual do menu) — ADR-0053. Nome próprio do app não tem forma cheia e fica no `regular`.
18
+ * `bold` (0.32.0) é o traço grosso, e só existe para os nomes de `NOMES_BOLD` (hoje, o `x` do
19
+ * `CloseButton`); para os outros, ele desenha o `regular`.
18
20
  */
19
- export type IconWeight = "regular" | "fill";
21
+ export type IconWeight = "regular" | "fill" | "bold";
20
22
  /** Os nomes do Phosphor em tempo de execução: só eles têm a forma cheia (`<nome>-fill`). */
21
23
  export declare const NOMES_PHOSPHOR: ReadonlySet<string>;
24
+ /** Os nomes que também têm o peso Bold (`<nome>-bold`), um a um, por decisão. */
25
+ export type BoldIconName = "x";
26
+ /** Os mesmos, em tempo de execução. */
27
+ export declare const NOMES_BOLD: ReadonlySet<string>;
@@ -2,3 +2,5 @@
2
2
  // Achado A-04: o nome do ícone é checado pelo TypeScript. ADR-0053: os nomes são os do Phosphor.
3
3
  /** Os nomes do Phosphor em tempo de execução: só eles têm a forma cheia (`<nome>-fill`). */
4
4
  export const NOMES_PHOSPHOR = new Set(["acorn", "address-book", "address-book-tabs", "air-traffic-control", "airplane", "airplane-in-flight", "airplane-landing", "airplane-takeoff", "airplane-taxiing", "airplane-tilt", "airplay", "alarm", "alien", "align-bottom", "align-bottom-simple", "align-center-horizontal", "align-center-horizontal-simple", "align-center-vertical", "align-center-vertical-simple", "align-left", "align-left-simple", "align-right", "align-right-simple", "align-top", "align-top-simple", "ambulance", "anchor", "anchor-simple", "angle", "aperture", "app-window", "approximate-equals", "archive", "armchair", "arrow-arc-left", "arrow-arc-right", "arrow-bend-double-up-left", "arrow-bend-double-up-right", "arrow-bend-down-left", "arrow-bend-down-right", "arrow-bend-left-down", "arrow-bend-left-up", "arrow-bend-right-down", "arrow-bend-right-up", "arrow-bend-up-left", "arrow-bend-up-right", "arrow-circle-down", "arrow-circle-down-left", "arrow-circle-down-right", "arrow-circle-left", "arrow-circle-right", "arrow-circle-up", "arrow-circle-up-left", "arrow-circle-up-right", "arrow-clockwise", "arrow-counter-clockwise", "arrow-down", "arrow-down-left", "arrow-down-right", "arrow-elbow-down-left", "arrow-elbow-down-right", "arrow-elbow-left", "arrow-elbow-left-down", "arrow-elbow-left-up", "arrow-elbow-right", "arrow-elbow-right-down", "arrow-elbow-right-up", "arrow-elbow-up-left", "arrow-elbow-up-right", "arrow-fat-down", "arrow-fat-left", "arrow-fat-line-down", "arrow-fat-line-left", "arrow-fat-line-right", "arrow-fat-line-up", "arrow-fat-lines-down", "arrow-fat-lines-left", "arrow-fat-lines-right", "arrow-fat-lines-up", "arrow-fat-right", "arrow-fat-up", "arrow-left", "arrow-line-down", "arrow-line-down-left", "arrow-line-down-right", "arrow-line-left", "arrow-line-right", "arrow-line-up", "arrow-line-up-left", "arrow-line-up-right", "arrow-right", "arrow-square-down", "arrow-square-down-left", "arrow-square-down-right", "arrow-square-in", "arrow-square-left", "arrow-square-out", "arrow-square-right", "arrow-square-up", "arrow-square-up-left", "arrow-square-up-right", "arrow-u-down-left", "arrow-u-down-right", "arrow-u-left-down", "arrow-u-left-up", "arrow-u-right-down", "arrow-u-right-up", "arrow-u-up-left", "arrow-u-up-right", "arrow-up", "arrow-up-left", "arrow-up-right", "arrows-clockwise", "arrows-counter-clockwise", "arrows-down-up", "arrows-horizontal", "arrows-in", "arrows-in-cardinal", "arrows-in-line-horizontal", "arrows-in-line-vertical", "arrows-in-simple", "arrows-left-right", "arrows-merge", "arrows-out", "arrows-out-cardinal", "arrows-out-line-horizontal", "arrows-out-line-vertical", "arrows-out-simple", "arrows-split", "arrows-vertical", "article", "article-medium", "article-ny-times", "asclepius", "asterisk", "asterisk-simple", "at", "atom", "avocado", "axe", "baby", "baby-carriage", "backpack", "backspace", "bag", "bag-simple", "balloon", "bandaids", "bank", "barbell", "barcode", "barn", "barricade", "baseball", "baseball-cap", "baseball-helmet", "basket", "basketball", "bathtub", "battery-charging", "battery-charging-vertical", "battery-empty", "battery-full", "battery-high", "battery-low", "battery-medium", "battery-plus", "battery-plus-vertical", "battery-vertical-empty", "battery-vertical-full", "battery-vertical-high", "battery-vertical-low", "battery-vertical-medium", "battery-warning", "battery-warning-vertical", "beach-ball", "beanie", "bed", "beer-bottle", "beer-stein", "bell", "bell-ringing", "bell-simple", "bell-simple-ringing", "bell-simple-slash", "bell-simple-z", "bell-slash", "bell-z", "belt", "bezier-curve", "bicycle", "binary", "binoculars", "biohazard", "bird", "blueprint", "bluetooth", "bluetooth-connected", "bluetooth-slash", "bluetooth-x", "boat", "bomb", "bone", "book", "book-bookmark", "book-open", "book-open-text", "book-open-user", "bookmark", "bookmark-simple", "bookmarks", "bookmarks-simple", "books", "boot", "boules", "bounding-box", "bowl-food", "bowl-steam", "bowling-ball", "box-arrow-down", "box-arrow-up", "boxing-glove", "brackets-angle", "brackets-curly", "brackets-round", "brackets-square", "brain", "brandy", "bread", "bridge", "briefcase", "briefcase-metal", "broadcast", "broom", "browser", "browsers", "bug", "bug-beetle", "bug-droid", "building", "building-apartment", "building-office", "buildings", "bulldozer", "bus", "butterfly", "cable-car", "cactus", "cake", "calculator", "calendar", "calendar-blank", "calendar-check", "calendar-dot", "calendar-dots", "calendar-heart", "calendar-minus", "calendar-plus", "calendar-slash", "calendar-star", "calendar-x", "call-bell", "camera", "camera-plus", "camera-rotate", "camera-slash", "campfire", "car", "car-battery", "car-profile", "car-simple", "cardholder", "cards", "cards-three", "caret-circle-double-down", "caret-circle-double-left", "caret-circle-double-right", "caret-circle-double-up", "caret-circle-down", "caret-circle-left", "caret-circle-right", "caret-circle-up", "caret-circle-up-down", "caret-double-down", "caret-double-left", "caret-double-right", "caret-double-up", "caret-down", "caret-left", "caret-line-down", "caret-line-left", "caret-line-right", "caret-line-up", "caret-right", "caret-up", "caret-up-down", "carrot", "cash-register", "cassette-tape", "castle-turret", "cat", "cell-signal-full", "cell-signal-high", "cell-signal-low", "cell-signal-medium", "cell-signal-none", "cell-signal-slash", "cell-signal-x", "cell-tower", "certificate", "chair", "chalkboard", "chalkboard-simple", "chalkboard-teacher", "champagne", "charging-station", "chart-bar", "chart-bar-horizontal", "chart-donut", "chart-line", "chart-line-down", "chart-line-up", "chart-pie", "chart-pie-slice", "chart-polar", "chart-scatter", "chat", "chat-centered", "chat-centered-dots", "chat-centered-slash", "chat-centered-text", "chat-circle", "chat-circle-dots", "chat-circle-slash", "chat-circle-text", "chat-dots", "chat-slash", "chat-teardrop", "chat-teardrop-dots", "chat-teardrop-slash", "chat-teardrop-text", "chat-text", "chats", "chats-circle", "chats-teardrop", "check", "check-circle", "check-fat", "check-square", "check-square-offset", "checkerboard", "checks", "cheers", "cheese", "chef-hat", "cherries", "church", "cigarette", "cigarette-slash", "circle", "circle-dashed", "circle-half", "circle-half-tilt", "circle-notch", "circles-four", "circles-three", "circles-three-plus", "circuitry", "city", "clipboard", "clipboard-text", "clock", "clock-afternoon", "clock-clockwise", "clock-countdown", "clock-counter-clockwise", "clock-user", "closed-captioning", "cloud", "cloud-arrow-down", "cloud-arrow-up", "cloud-check", "cloud-fog", "cloud-lightning", "cloud-moon", "cloud-rain", "cloud-slash", "cloud-snow", "cloud-sun", "cloud-warning", "cloud-x", "clover", "club", "coat-hanger", "code", "code-block", "code-simple", "coffee", "coffee-bean", "coin", "coin-vertical", "coins", "columns", "columns-plus-left", "columns-plus-right", "command", "compass", "compass-rose", "compass-tool", "computer-tower", "confetti", "contactless-payment", "control", "cookie", "cooking-pot", "copy", "copy-simple", "copyleft", "copyright", "corners-in", "corners-out", "couch", "court-basketball", "cow", "cowboy-hat", "cpu", "crane", "crane-tower", "credit-card", "cricket", "crop", "cross", "crosshair", "crosshair-simple", "crown", "crown-cross", "crown-simple", "cube", "cube-focus", "cube-transparent", "currency-btc", "currency-circle-dollar", "currency-cny", "currency-dollar", "currency-dollar-simple", "currency-eth", "currency-eur", "currency-gbp", "currency-inr", "currency-jpy", "currency-krw", "currency-kzt", "currency-ngn", "currency-rub", "cursor", "cursor-click", "cursor-text", "cylinder", "database", "desk", "desktop", "desktop-tower", "detective", "device-mobile", "device-mobile-camera", "device-mobile-slash", "device-mobile-speaker", "device-rotate", "device-tablet", "device-tablet-camera", "device-tablet-speaker", "devices", "diamond", "diamonds-four", "dice-five", "dice-four", "dice-one", "dice-six", "dice-three", "dice-two", "disc", "disco-ball", "divide", "dna", "dog", "door", "door-open", "dot", "dot-outline", "dots-nine", "dots-six", "dots-six-vertical", "dots-three", "dots-three-circle", "dots-three-circle-vertical", "dots-three-outline", "dots-three-outline-vertical", "dots-three-vertical", "download", "download-simple", "dress", "dresser", "drone", "drop", "drop-half", "drop-half-bottom", "drop-simple", "drop-slash", "ear", "ear-slash", "egg", "egg-crack", "eject", "eject-simple", "elevator", "empty", "engine", "envelope", "envelope-open", "envelope-simple", "envelope-simple-open", "equalizer", "equals", "eraser", "escalator-down", "escalator-up", "exam", "exclamation-mark", "exclude", "exclude-square", "export", "eye", "eye-closed", "eye-slash", "eyedropper", "eyedropper-sample", "eyeglasses", "eyes", "face-mask", "factory", "faders", "faders-horizontal", "fallout-shelter", "fan", "farm", "fast-forward", "fast-forward-circle", "feather", "file", "file-archive", "file-arrow-down", "file-arrow-up", "file-audio", "file-c", "file-c-sharp", "file-cloud", "file-code", "file-cpp", "file-css", "file-csv", "file-dashed", "file-doc", "file-html", "file-image", "file-ini", "file-jpg", "file-js", "file-jsx", "file-lock", "file-magnifying-glass", "file-md", "file-minus", "file-pdf", "file-plus", "file-png", "file-ppt", "file-py", "file-rs", "file-sql", "file-svg", "file-text", "file-ts", "file-tsx", "file-txt", "file-video", "file-vue", "file-x", "file-xls", "file-zip", "files", "film-reel", "film-script", "film-slate", "film-strip", "fingerprint", "fingerprint-simple", "finn-the-human", "fire", "fire-extinguisher", "fire-simple", "fire-truck", "first-aid", "first-aid-kit", "fish", "fish-simple", "flag", "flag-banner", "flag-banner-fold", "flag-checkered", "flag-pennant", "flame", "flashlight", "flask", "flip-horizontal", "flip-vertical", "floppy-disk", "floppy-disk-back", "flow-arrow", "flower", "flower-lotus", "flower-tulip", "flying-saucer", "folder", "folder-dashed", "folder-lock", "folder-minus", "folder-open", "folder-plus", "folder-simple", "folder-simple-dashed", "folder-simple-lock", "folder-simple-minus", "folder-simple-plus", "folder-simple-star", "folder-simple-user", "folder-star", "folder-user", "folders", "football", "football-helmet", "footprints", "fork-knife", "four-k", "frame-corners", "function", "funnel", "funnel-simple", "funnel-simple-x", "funnel-x", "game-controller", "garage", "gas-can", "gas-pump", "gauge", "gavel", "gear", "gear-fine", "gear-six", "gender-female", "gender-intersex", "gender-male", "gender-neuter", "gender-nonbinary", "gender-transgender", "ghost", "gif", "gift", "git-branch", "git-commit", "git-diff", "git-fork", "git-merge", "git-pull-request", "globe", "globe-hemisphere-east", "globe-hemisphere-west", "globe-simple", "globe-simple-x", "globe-stand", "globe-x", "goggles", "golf", "gps", "gps-fix", "gps-slash", "gradient", "graduation-cap", "grains", "grains-slash", "graph", "graphics-card", "greater-than", "greater-than-or-equal", "grid-four", "grid-nine", "guitar", "hair-dryer", "hamburger", "hammer", "hand", "hand-arrow-down", "hand-arrow-up", "hand-coins", "hand-deposit", "hand-eye", "hand-fist", "hand-grabbing", "hand-heart", "hand-palm", "hand-peace", "hand-pointing", "hand-soap", "hand-swipe-left", "hand-swipe-right", "hand-tap", "hand-waving", "hand-withdraw", "handbag", "handbag-simple", "hands-clapping", "hands-praying", "handshake", "hard-drive", "hard-drives", "hard-hat", "hash", "hash-straight", "head-circuit", "headlights", "headphones", "headset", "heart", "heart-break", "heart-half", "heart-straight", "heart-straight-break", "heartbeat", "hexagon", "high-definition", "high-heel", "highlighter", "highlighter-circle", "hockey", "hoodie", "horse", "hospital", "hourglass", "hourglass-high", "hourglass-low", "hourglass-medium", "hourglass-simple", "hourglass-simple-high", "hourglass-simple-low", "hourglass-simple-medium", "house", "house-line", "house-simple", "hurricane", "ice-cream", "identification-badge", "identification-card", "image", "image-broken", "image-square", "images", "images-square", "infinity", "info", "intersect", "intersect-square", "intersect-three", "intersection", "invoice", "island", "jar", "jar-label", "jeep", "joystick", "kanban", "key", "key-return", "keyboard", "keyhole", "knife", "ladder", "ladder-simple", "lamp", "lamp-pendant", "laptop", "lasso", "layout", "leaf", "lectern", "lego", "lego-smiley", "less-than", "less-than-or-equal", "letter-circle-h", "letter-circle-p", "letter-circle-v", "lifebuoy", "lightbulb", "lightbulb-filament", "lighthouse", "lightning", "lightning-a", "lightning-slash", "line-segment", "line-segments", "line-vertical", "link", "link-break", "link-simple", "link-simple-break", "link-simple-horizontal", "link-simple-horizontal-break", "list", "list-bullets", "list-checks", "list-dashes", "list-heart", "list-magnifying-glass", "list-numbers", "list-plus", "list-star", "lock", "lock-key", "lock-key-open", "lock-laminated", "lock-laminated-open", "lock-open", "lock-simple", "lock-simple-open", "lockers", "log", "magic-wand", "magnet", "magnet-straight", "magnifying-glass", "magnifying-glass-minus", "magnifying-glass-plus", "mailbox", "map-pin", "map-pin-area", "map-pin-line", "map-pin-plus", "map-pin-simple", "map-pin-simple-area", "map-pin-simple-line", "map-trifold", "marker-circle", "martini", "mask-happy", "mask-sad", "math-operations", "medal", "medal-military", "megaphone", "megaphone-simple", "member-of", "memory", "meteor", "metronome", "microphone", "microphone-slash", "microphone-stage", "microscope", "minus", "minus-circle", "minus-square", "money", "money-wavy", "monitor", "monitor-arrow-up", "monitor-play", "moon", "moon-stars", "moped", "moped-front", "mosque", "motorcycle", "mountains", "mouse", "mouse-left-click", "mouse-middle-click", "mouse-right-click", "mouse-scroll", "mouse-simple", "music-note", "music-note-simple", "music-notes", "music-notes-minus", "music-notes-plus", "music-notes-simple", "navigation-arrow", "needle", "network", "network-slash", "network-x", "newspaper", "newspaper-clipping", "not-equals", "not-member-of", "not-subset-of", "not-superset-of", "notches", "note", "note-blank", "note-pencil", "notebook", "notepad", "notification", "nuclear-plant", "number-circle-eight", "number-circle-five", "number-circle-four", "number-circle-nine", "number-circle-one", "number-circle-seven", "number-circle-six", "number-circle-three", "number-circle-two", "number-circle-zero", "number-eight", "number-five", "number-four", "number-nine", "number-one", "number-seven", "number-six", "number-square-eight", "number-square-five", "number-square-four", "number-square-nine", "number-square-one", "number-square-seven", "number-square-six", "number-square-three", "number-square-two", "number-square-zero", "number-three", "number-two", "number-zero", "numpad", "nut", "octagon", "office-chair", "onigiri", "option", "orange", "orange-slice", "oven", "package", "paint-brush", "paint-brush-broad", "paint-brush-household", "paint-bucket", "paint-roller", "palette", "panorama", "pants", "paper-plane", "paper-plane-right", "paper-plane-tilt", "paperclip", "paperclip-horizontal", "parachute", "paragraph", "parallelogram", "park", "password", "path", "pause", "pause-circle", "paw-print", "peace", "pen", "pen-nib", "pen-nib-straight", "pencil", "pencil-circle", "pencil-line", "pencil-ruler", "pencil-simple", "pencil-simple-line", "pencil-simple-slash", "pencil-slash", "pentagon", "pentagram", "pepper", "percent", "person", "person-arms-spread", "person-simple", "person-simple-bike", "person-simple-circle", "person-simple-hike", "person-simple-run", "person-simple-ski", "person-simple-snowboard", "person-simple-swim", "person-simple-tai-chi", "person-simple-throw", "person-simple-walk", "perspective", "phone", "phone-call", "phone-disconnect", "phone-incoming", "phone-list", "phone-outgoing", "phone-pause", "phone-plus", "phone-slash", "phone-transfer", "phone-x", "pi", "piano-keys", "picnic-table", "picture-in-picture", "piggy-bank", "pill", "ping-pong", "pint-glass", "pinwheel", "pipe", "pipe-wrench", "pizza", "placeholder", "planet", "plant", "play", "play-circle", "play-pause", "playlist", "plug", "plug-charging", "plugs", "plugs-connected", "plus", "plus-circle", "plus-minus", "plus-square", "poker-chip", "police-car", "polygon", "popcorn", "popsicle", "potted-plant", "power", "prescription", "presentation", "presentation-chart", "printer", "prohibit", "prohibit-inset", "projector-screen", "projector-screen-chart", "pulse", "push-pin", "push-pin-simple", "push-pin-simple-slash", "push-pin-slash", "puzzle-piece", "qr-code", "question", "question-mark", "queue", "quotes", "rabbit", "racquet", "radical", "radio", "radio-button", "radioactive", "rainbow", "rainbow-cloud", "ranking", "receipt", "receipt-x", "record", "rectangle", "rectangle-dashed", "recycle", "repeat", "repeat-once", "resize", "rewind", "rewind-circle", "road-horizon", "robot", "rocket", "rocket-launch", "rows", "rows-plus-bottom", "rows-plus-top", "rss", "rss-simple", "rug", "ruler", "sailboat", "scales", "scan", "scan-smiley", "scissors", "scooter", "screencast", "screwdriver", "scribble", "scribble-loop", "scroll", "seal", "seal-check", "seal-percent", "seal-question", "seal-warning", "seat", "seatbelt", "security-camera", "selection", "selection-all", "selection-background", "selection-foreground", "selection-inverse", "selection-plus", "selection-slash", "shapes", "share", "share-fat", "share-network", "shield", "shield-check", "shield-checkered", "shield-chevron", "shield-plus", "shield-slash", "shield-star", "shield-warning", "shipping-container", "shirt-folded", "shooting-star", "shopping-bag", "shopping-bag-open", "shopping-cart", "shopping-cart-simple", "shovel", "shower", "shrimp", "shuffle", "shuffle-angular", "shuffle-simple", "sidebar", "sidebar-simple", "sigma", "sign-in", "sign-out", "signature", "signpost", "sim-card", "siren", "skip-back", "skip-back-circle", "skip-forward", "skip-forward-circle", "skull", "sliders", "sliders-horizontal", "slideshow", "smiley", "smiley-angry", "smiley-blank", "smiley-meh", "smiley-melting", "smiley-nervous", "smiley-sad", "smiley-sticker", "smiley-wink", "smiley-x-eyes", "sneaker", "sneaker-move", "snowflake", "soccer-ball", "sock", "solar-panel", "solar-roof", "sort-ascending", "sort-descending", "spade", "sparkle", "speaker-hifi", "speaker-high", "speaker-low", "speaker-none", "speaker-simple-high", "speaker-simple-low", "speaker-simple-none", "speaker-simple-slash", "speaker-simple-x", "speaker-slash", "speaker-x", "speedometer", "sphere", "spinner", "spinner-ball", "spinner-gap", "spiral", "split-horizontal", "split-vertical", "spray-bottle", "square", "square-half", "square-half-bottom", "square-split-horizontal", "square-split-vertical", "squares-four", "stack", "stack-minus", "stack-plus", "stack-simple", "stairs", "stamp", "standard-definition", "star", "star-and-crescent", "star-four", "star-half", "star-of-david", "steering-wheel", "steps", "stethoscope", "sticker", "stool", "stop", "stop-circle", "storefront", "strategy", "student", "subset-of", "subset-proper-of", "subtitles", "subtitles-slash", "subtract", "subtract-square", "subway", "suitcase", "suitcase-rolling", "suitcase-simple", "sun", "sun-dim", "sun-horizon", "sunglasses", "superset-of", "superset-proper-of", "swap", "swatches", "swimming-pool", "sword", "synagogue", "syringe", "t-shirt", "table", "tabs", "tag", "tag-chevron", "tag-simple", "target", "taxi", "tea-bag", "television", "television-simple", "tennis-ball", "tent", "terminal", "terminal-window", "test-tube", "text-a-underline", "text-aa", "text-align-center", "text-align-justify", "text-align-left", "text-align-right", "text-b", "text-columns", "text-h", "text-h-five", "text-h-four", "text-h-one", "text-h-six", "text-h-three", "text-h-two", "text-indent", "text-italic", "text-outdent", "text-strikethrough", "text-subscript", "text-superscript", "text-t", "text-t-slash", "text-underline", "textbox", "thermometer", "thermometer-cold", "thermometer-hot", "thermometer-simple", "three-d", "thumbs-down", "thumbs-up", "ticket", "tilde", "timer", "tip-jar", "tipi", "tire", "toggle-left", "toggle-right", "toilet", "toilet-paper", "toolbox", "tooth", "tornado", "tote", "tote-simple", "towel", "tractor", "trademark", "trademark-registered", "traffic-cone", "traffic-sign", "traffic-signal", "train", "train-regional", "train-simple", "tram", "translate", "trash", "trash-simple", "tray", "tray-arrow-down", "tray-arrow-up", "treasure-chest", "tree", "tree-evergreen", "tree-palm", "tree-structure", "tree-view", "trend-down", "trend-up", "triangle", "triangle-dashed", "trolley", "trolley-suitcase", "trophy", "truck", "truck-trailer", "umbrella", "umbrella-simple", "union", "unite", "unite-square", "upload", "upload-simple", "usb", "user", "user-check", "user-circle", "user-circle-check", "user-circle-dashed", "user-circle-gear", "user-circle-minus", "user-circle-plus", "user-focus", "user-gear", "user-list", "user-minus", "user-plus", "user-rectangle", "user-sound", "user-square", "user-switch", "users", "users-four", "users-three", "van", "vault", "vector-three", "vector-two", "vibrate", "video", "video-camera", "video-camera-slash", "video-conference", "vignette", "vinyl-record", "virtual-reality", "virus", "visor", "voicemail", "volleyball", "wall", "wallet", "warehouse", "warning", "warning-circle", "warning-diamond", "warning-octagon", "washing-machine", "watch", "wave-sawtooth", "wave-sine", "wave-square", "wave-triangle", "waveform", "waveform-slash", "waves", "webcam", "webcam-slash", "wheelchair", "wheelchair-motion", "wifi-high", "wifi-low", "wifi-medium", "wifi-none", "wifi-slash", "wifi-x", "wind", "windmill", "wine", "wrench", "x", "x-circle", "x-square", "yarn", "yin-yang"]);
5
+ /** Os mesmos, em tempo de execução. */
6
+ export const NOMES_BOLD = new Set(["x"]);
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { cx, defaultStrings, ptBR, defaultSpriteUrl, gridStateToParams, gridStat
2
2
  export { useAureaStrings, useSpriteUrl, useTheme, useDensity } from "./internal.js";
3
3
  export { type Responsive, type Breakpoint, type ContainerBreakpoint, type Orientation, ESCALA, ESCALA_CONTAINER } from "./pure.js";
4
4
  export { ContainerScope, useValorResponsivo } from "./responsivo-runtime.js";
5
- export { AspectRatio, InputGroup, InputGroupAddon, Label, Card, Stack, Cluster, Grid, Container, Section, KPI, DataList, Timeline, Prose, Text, Heading, Paragraph, Code, Badge, Progress, Skeleton, AvatarGroup, LogStream, MediaPlayerShell, Header, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount, type BadgeVariant, type BadgeCategory, type BadgeEmphasis, type BadgeSize, type BadgePlacement, type BadgeProps, type KPIProps, type KPIDirection, type KPITone, type KPIVariant, type ProgressProps, type ProgressTone, type AvatarSize, type HeaderVariant, type HeaderProps, type TopbarVariant, type SectionVariant, type SectionFooterGroup, type CardProps, type CardAccent, type TextProps, type HeadingProps, type ParagraphProps, type CodeProps, type TypographyType, type TypographyColor, type TypographyWeight, type TypographyAlign, type HeadingLevel, type ParagraphSize } from "./markup.js";
5
+ export { AspectRatio, InputGroup, InputGroupAddon, Label, Card, Stack, Cluster, Grid, Container, Section, KPI, DataList, Timeline, Prose, Text, Heading, Paragraph, Code, Badge, Progress, Skeleton, Link, ColorSwatch, ProgressCircle, AvatarGroup, LogStream, MediaPlayerShell, Header, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount, type BadgeVariant, type BadgeCategory, type BadgeEmphasis, type BadgeSize, type BadgePlacement, type BadgeProps, type KPIProps, type KPIDirection, type KPITone, type KPIVariant, type ProgressProps, type ProgressTone, type AvatarSize, type HeaderVariant, type HeaderProps, type TopbarVariant, type SectionVariant, type SectionFooterGroup, type CardProps, type CardAccent, type TextProps, type HeadingProps, type ParagraphProps, type CodeProps, type TypographyType, type TypographyColor, type TypographyWeight, type TypographyAlign, type HeadingLevel, type ParagraphSize, type LinkProps, type ColorSwatchProps, type ColorSwatchSize, type ProgressCircleProps, type ProgressCircleSize, type ProgressSize, type SkeletonAnimation, type TypographyTone } from "./markup.js";
6
6
  export * from "./system.js";
7
7
  export * from "./actions.js";
8
8
  export * from "./feedback.js";
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ export { ContainerScope, useValorResponsivo } from "./responsivo-runtime.js";
51
51
  // inteiro). O que muda é de ONDE ele vem — do módulo com a diretiva —, e aí ele volta a chegar
52
52
  // como referência de CLIENTE e os 118,5 KB voltam com ele. Não é um erro: é o ganho do item O1
53
53
  // se desfazendo em silêncio. É isso, exatamente isso, que o check 35 pega.
54
- export { AspectRatio, InputGroup, InputGroupAddon, Label, Card, Stack, Cluster, Grid, Container, Section, KPI, DataList, Timeline, Prose, Text, Heading, Paragraph, Code, Badge, Progress, Skeleton, AvatarGroup, LogStream, MediaPlayerShell, Header, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount } from "./markup.js";
54
+ export { AspectRatio, InputGroup, InputGroupAddon, Label, Card, Stack, Cluster, Grid, Container, Section, KPI, DataList, Timeline, Prose, Text, Heading, Paragraph, Code, Badge, Progress, Skeleton, Link, ColorSwatch, ProgressCircle, AvatarGroup, LogStream, MediaPlayerShell, Header, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount } from "./markup.js";
55
55
  export * from "./system.js";
56
56
  export * from "./actions.js";
57
57
  export * from "./feedback.js";