@aurea-uds/react 0.22.0 → 0.24.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.
@@ -1,7 +1,17 @@
1
1
  import React, { type HTMLAttributes, type RefAttributes, type ReactNode } from "react";
2
- export declare function Table({ caption, children, className, ...props }: HTMLAttributes<HTMLTableElement> & RefAttributes<HTMLTableElement> & {
2
+ export interface TableProps extends HTMLAttributes<HTMLTableElement>, RefAttributes<HTMLTableElement> {
3
+ /** Um `<caption>` de verdade; se for texto, vira também o nome da região que rola. */
3
4
  caption?: ReactNode;
4
- }): React.JSX.Element;
5
+ /** GAR-13: o cabeçalho fica preso no topo da caixa da tabela, que ganha teto (`--table-max-h`, 60vh) e rola por dentro. */
6
+ stickyHeader?: boolean;
7
+ /** GAR-12: a primeira coluna fica parada ao rolar de lado. */
8
+ stickyFirstColumn?: boolean;
9
+ /** GAR-12: a tabela cabe na largura da caixa, sem o mínimo de 720 — a comparação de dois itens no celular. */
10
+ fit?: boolean;
11
+ /** GAR-12: esconde as linhas marcadas como iguais (`<tr data-same>`) — o "Só diferenças". */
12
+ differencesOnly?: boolean;
13
+ }
14
+ export declare function Table({ caption, stickyHeader, stickyFirstColumn, fit, differencesOnly, children, className, ...props }: TableProps): React.JSX.Element;
5
15
  export interface SortableItem {
6
16
  id: string;
7
17
  label: ReactNode;
@@ -6,7 +6,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
6
6
  import React from "react";
7
7
  import { cx, useAureaStrings, useReorder } from "./internal.js";
8
8
  import { Icon } from "./system.js";
9
- export function Table({ caption, children, className, ...props }) { const s = useAureaStrings(); return _jsx("div", { className: "table-region", role: "region", "aria-label": typeof caption === "string" ? caption : s.tableLabel, tabIndex: 0, children: _jsxs("table", { className: cx("table", className), ...props, children: [caption && _jsx("caption", { children: caption }), children] }) }); }
9
+ export function Table({ caption, stickyHeader, stickyFirstColumn, fit, differencesOnly, children, className, ...props }) { const s = useAureaStrings(); return _jsx("div", { className: cx("table-region", stickyHeader && "table-sticky-header", stickyFirstColumn && "table-sticky-first"), role: "region", "aria-label": typeof caption === "string" ? caption : s.tableLabel, tabIndex: 0, children: _jsxs("table", { className: cx("table", fit && "table-fit", differencesOnly && "table-differences-only", className), ...props, children: [caption && _jsx("caption", { children: caption }), children] }) }); }
10
10
  // O protocolo de teclado e de ponteiro saiu daqui para o `useReorder` do `internal` no item N1,
11
11
  // quando o `BlockEditor` virou o segundo dono dele. A DOM abaixo não mudou uma vírgula na
12
12
  // extração — é o que o gate de pixel e o `skin.spec` continuam medindo.
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, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount, type BadgeVariant, type BadgeEmphasis, type BadgeSize, type BadgePlacement, type BadgeProps, type ProgressProps, type ProgressTone, type AvatarSize, type TopbarVariant, 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, AvatarGroup, LogStream, MediaPlayerShell, Header, Topbar, Kbd, Textarea, Checkbox, Radio, Switch, Range, formatBadgeCount, type BadgeVariant, type BadgeEmphasis, type BadgeSize, type BadgePlacement, type BadgeProps, type ProgressProps, type ProgressTone, type AvatarSize, type HeaderVariant, type HeaderProps, type TopbarVariant, type SectionVariant, type SectionFooterGroup, type TextProps, type HeadingProps, type ParagraphProps, type CodeProps, type TypographyType, type TypographyColor, type TypographyWeight, type TypographyAlign, type HeadingLevel, type ParagraphSize } 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, 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, 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";
@@ -1,6 +1,6 @@
1
1
  import { type HTMLAttributes, type RefAttributes, type ReactNode } from "react";
2
2
  import { type Orientation, type Responsive } from "./pure.js";
3
- import { type TopbarVariant, type SidebarVariant, type SidebarItem } from "./navigation.js";
3
+ import { type HeaderVariant, type SidebarVariant, type SidebarItem } from "./navigation.js";
4
4
  export declare function AppShell({ brand, navigation, navItems, currentNavId, navLabel, topbar, topbarVariant, topbarDivider, sidebarVariant, sidebarCollapsed, sidebarCollapsible, defaultSidebarCollapsed, onSidebarCollapsedChange, contentVariant, children, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
5
5
  brand: ReactNode;
6
6
  navigation?: ReactNode;
@@ -8,7 +8,7 @@ export declare function AppShell({ brand, navigation, navItems, currentNavId, na
8
8
  currentNavId?: string;
9
9
  navLabel?: string;
10
10
  topbar?: ReactNode;
11
- topbarVariant?: Exclude<TopbarVariant, "pill">;
11
+ topbarVariant?: Exclude<HeaderVariant, "pill">;
12
12
  topbarDivider?: boolean;
13
13
  sidebarVariant?: SidebarVariant;
14
14
  /** A lateral em trilha de ícones. Controlado: quem passa decide (e o `onSidebarCollapsedChange` avisa). */
@@ -11,7 +11,7 @@ import { useValorResponsivo } from "./responsivo-runtime.js";
11
11
  import { ESCALA } from "./escala.js";
12
12
  import { IconButton } from "./actions.js";
13
13
  import { Tooltip } from "./overlays.js";
14
- import { Sidebar, Topbar } from "./navigation.js";
14
+ import { Sidebar, Header } from "./navigation.js";
15
15
  // ── Auxiliar de topo: mora ANTES do primeiro export, e a posição é obrigatória ───────────────
16
16
  // O check 22 mede o corpo de um componente do `export` dele até o PRÓXIMO export — fatia longa
17
17
  // de propósito, porque a implementação de vários componentes daqui continua num auxiliar não
@@ -180,7 +180,7 @@ export function AppShell({ brand, navigation, navItems, currentNavId, navLabel,
180
180
  // A condição vai escrita no `icon=` do botão, e não numa variável: é ali que o check 46 lê os
181
181
  // ícones que o shell desenha.
182
182
  const paraOComeco = !efetiva, direita = useDirection() === "rtl";
183
- return _jsxs("div", { className: cx("app-shell", topbarVariant === "flush" && "app-shell-flush", sidebarCollapsible && "app-shell-collapsible", className), ...props, children: [_jsx("a", { className: "skip-link", href: `#${SHELL_MAIN_ID}`, children: s.skipToContent }), _jsx(Topbar, { variant: topbarVariant, divider: topbarDivider, brand: _jsxs(_Fragment, { children: [_jsx(IconButton, { className: "nav-toggle", icon: "list", label: s.navigationToggle, popoverTarget: SHELL_NAV_ID }), brand] }), children: topbar }), sidebarCollapsible && _jsx("div", { className: "sidebar-toggle-slot", children: _jsx(Tooltip, { content: rotulo, side: "right", children: _jsx(IconButton, { className: "sidebar-toggle", size: "xs", icon: paraOComeco === direita ? "caret-right" : "caret-left", label: rotulo, "aria-expanded": !efetiva, "aria-controls": SHELL_NAV_ID, onClick: alternar }) }) }), _jsx(Sidebar, { id: SHELL_NAV_ID, popover: "auto", variant: sidebarVariant, collapsed: efetiva, items: navItems, current: currentNavId, label: navLabel, onToggle: focoDaGaveta, children: navigation }), _jsx("main", { id: SHELL_MAIN_ID, tabIndex: -1, className: cx("content", contentVariant === "plain" && "content-plain"), children: children })] });
183
+ return _jsxs("div", { className: cx("app-shell", topbarVariant === "flush" && "app-shell-flush", sidebarCollapsible && "app-shell-collapsible", className), ...props, children: [_jsx("a", { className: "skip-link", href: `#${SHELL_MAIN_ID}`, children: s.skipToContent }), _jsx(Header, { variant: topbarVariant, divider: topbarDivider, brand: _jsxs(_Fragment, { children: [_jsx(IconButton, { className: "nav-toggle", icon: "list", label: s.navigationToggle, popoverTarget: SHELL_NAV_ID }), brand] }), children: topbar }), sidebarCollapsible && _jsx("div", { className: "sidebar-toggle-slot", children: _jsx(Tooltip, { content: rotulo, side: "right", children: _jsx(IconButton, { className: "sidebar-toggle", size: "xs", icon: paraOComeco === direita ? "caret-right" : "caret-left", label: rotulo, "aria-expanded": !efetiva, "aria-controls": SHELL_NAV_ID, onClick: alternar }) }) }), _jsx(Sidebar, { id: SHELL_NAV_ID, popover: "auto", variant: sidebarVariant, collapsed: efetiva, items: navItems, current: currentNavId, label: navLabel, onToggle: focoDaGaveta, children: navigation }), _jsx("main", { id: SHELL_MAIN_ID, tabIndex: -1, className: cx("content", contentVariant === "plain" && "content-plain"), children: children })] });
184
184
  }
185
185
  export function Separator({ orientation, spacing = "none", className, ...props }) {
186
186
  const ancora = useRef(null);
package/dist/layout.d.ts CHANGED
@@ -2,4 +2,4 @@ export * from "./layout-client.js";
2
2
  export { Card, Stack, Cluster, Grid } from "./markup.js";
3
3
  export { AspectRatio } from "./markup.js";
4
4
  export { Container, Section } from "./markup.js";
5
- export type { GridSpan, GridItemProps, ContainerSize, ContainerProps, SectionSurface, SectionSpacing, SectionProps } from "./markup.js";
5
+ export type { GridSpan, GridItemProps, ContainerSize, ContainerProps, SectionSurface, SectionSpacing, SectionProps, SectionVariant, SectionFooterGroup } from "./markup.js";
package/dist/markup.d.ts CHANGED
@@ -1,9 +1,12 @@
1
1
  import React, { type HTMLAttributes, type InputHTMLAttributes, type ReactElement, type ReactNode, type RefAttributes, type TextareaHTMLAttributes } from "react";
2
2
  import { type Responsive } from "./pure.js";
3
3
  import type { ComponentSize } from "./actions.js";
4
+ import type { SidebarItem } from "./navigation-client.js";
4
5
  export type BadgeVariant = "neutral" | "primary" | "info" | "success" | "warning" | "danger" | "running" | "paused" | "offline" | "review";
5
6
  export type AvatarSize = "sm" | "md" | "lg";
6
- export type TopbarVariant = "floating" | "flush" | "pill";
7
+ export type HeaderVariant = "floating" | "flush" | "pill";
8
+ /** @deprecated `Topbar` é o nome antigo do `Header` (07/10/2026). O tipo continua valendo; use `HeaderVariant`. */
9
+ export type TopbarVariant = HeaderVariant;
7
10
  type CardBase = HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
8
11
  padding?: "normal" | "none";
9
12
  orientation?: "vertical" | "horizontal";
@@ -98,6 +101,13 @@ export interface ContainerProps extends HTMLAttributes<HTMLDivElement>, RefAttri
98
101
  export declare function Container({ size, className, ...props }: ContainerProps): React.JSX.Element;
99
102
  /** O fundo da faixa: o da página (padrão), o de cartão ou o rebaixado. */
100
103
  export type SectionSurface = "background" | "card" | "inset";
104
+ /** `base` é a faixa comum; `footer` é o rodapé do site (GAR-06, 07/10/2026). */
105
+ export type SectionVariant = "base" | "footer";
106
+ /** Uma coluna de links do rodapé: o título e os itens. */
107
+ export interface SectionFooterGroup {
108
+ title: ReactNode;
109
+ items: SidebarItem[];
110
+ }
101
111
  /** O respiro de cima e de baixo: `md` (padrão, 64 e 96 a partir do `md`) ou `sm` (32 e 48). */
102
112
  export type SectionSpacing = "sm" | "md";
103
113
  export interface SectionProps extends HTMLAttributes<HTMLElement>, RefAttributes<HTMLElement> {
@@ -109,13 +119,28 @@ export interface SectionProps extends HTMLAttributes<HTMLElement>, RefAttributes
109
119
  * página não vazam para dentro dela.
110
120
  */
111
121
  theme?: "light" | "dark";
122
+ /**
123
+ * `footer` faz da faixa o RODAPÉ do site (GAR-06): `<footer>` com a marca, as colunas de links e a
124
+ * linha legal, e o miolo já num `Container`. No celular, tudo empilha.
125
+ */
126
+ variant?: SectionVariant;
127
+ /** Só no `footer`: a marca e uma frase curta, no alto à esquerda. */
128
+ brand?: ReactNode;
129
+ /** Só no `footer`: as colunas de links, cada uma com título. Os itens são `SidebarItem` (`id`, `label`, `href`, `render`). */
130
+ links?: SectionFooterGroup[];
131
+ /** Só no `footer`: a linha de baixo — direitos, termos, privacidade. */
132
+ legal?: ReactNode;
133
+ /** Só no `footer`: até onde o miolo cresce, pela escala do `Container`. Padrão: `xl`. */
134
+ maxWidth?: ContainerSize;
135
+ /** Só no `footer`: o nome da navegação do rodapé para o leitor de tela. Padrão: `"Footer"`. */
136
+ navLabel?: string;
112
137
  }
113
138
  /**
114
139
  * A faixa de ponta a ponta de uma página de site (GAR-04): `<section>` com fundo e respiro de site.
115
140
  * O conteúdo vai dentro de um `Container`. Dê um nome à faixa (`aria-labelledby` no título dela)
116
141
  * quando ela for uma região que o leitor de tela deva listar.
117
142
  */
118
- export declare function Section({ surface, spacing, theme, className, ...props }: SectionProps): React.JSX.Element;
143
+ export declare function Section({ surface, spacing, theme, variant, brand, links, legal, maxWidth, navLabel, children, className, ...props }: SectionProps): React.JSX.Element;
119
144
  export declare function KPI({ label, value, trend, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement> & {
120
145
  label: ReactNode;
121
146
  value: ReactNode;
@@ -228,11 +253,34 @@ export declare function LogStream({ lines }: {
228
253
  }>;
229
254
  }): React.JSX.Element;
230
255
  export declare function MediaPlayerShell({ children, className, ...props }: HTMLAttributes<HTMLDivElement> & RefAttributes<HTMLDivElement>): React.JSX.Element;
231
- export declare function Topbar({ variant, divider, brand, children, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement> & {
232
- variant?: TopbarVariant;
256
+ export interface HeaderProps extends HTMLAttributes<HTMLElement>, RefAttributes<HTMLElement> {
257
+ /** A pele: `floating` (caixa solta), `flush` (encostada, o fundo da página) ou `pill` (cápsula). */
258
+ variant?: HeaderVariant;
259
+ /** A marca. No `AppShell`, é aqui que entra também o botão que abre a lateral. */
233
260
  brand?: ReactNode;
261
+ /** Só na `flush` (B-07): a linha embaixo da barra. */
234
262
  divider?: boolean;
235
- }): React.JSX.Element;
263
+ /**
264
+ * Os links do site (GAR-01) — a mesma lista do `Sidebar` e do `BottomNav`. No celular (abaixo
265
+ * de 768) eles saem da barra e entram no painel do botão de menu.
266
+ */
267
+ items?: SidebarItem[];
268
+ /** O `id` do item da página atual: ganha `aria-current="page"` e a cor de destaque. */
269
+ current?: string;
270
+ /** O que fica do lado direito: busca, botão de ação, conta. Fica na barra também no celular. */
271
+ actions?: ReactNode;
272
+ /** Até onde o miolo da barra cresce, pela escala do `Container` (`sm` 640 … `2xl` 1536, `full`). */
273
+ maxWidth?: ContainerSize;
274
+ /** O nome da navegação para o leitor de tela. Padrão: `"Main"`. */
275
+ navLabel?: string;
276
+ /** O nome do botão de menu do celular. Padrão: `"Menu"`. */
277
+ menuLabel?: string;
278
+ /** O `id` do painel do celular. Padrão: `"aurea-header-menu"`. Troque só se a página tiver dois cabeçalhos de site. */
279
+ menuId?: string;
280
+ }
281
+ export declare function Header({ variant, divider, brand, items, current, actions, maxWidth, navLabel, menuLabel, menuId, children, className, ...props }: HeaderProps): React.JSX.Element;
282
+ /** @deprecated `Topbar` é o nome antigo do `Header` (07/10/2026). Continua funcionando, igual; use `Header`. */
283
+ export declare function Topbar(props: HeaderProps): React.JSX.Element;
236
284
  export declare function Kbd({ children, className, ...props }: HTMLAttributes<HTMLElement> & RefAttributes<HTMLElement>): React.JSX.Element;
237
285
  export interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement>, RefAttributes<HTMLTextAreaElement> {
238
286
  size?: Responsive<FieldSize>;
package/dist/markup.js CHANGED
@@ -75,8 +75,18 @@ export function Container({ size = "xl", className, ...props }) {
75
75
  * O conteúdo vai dentro de um `Container`. Dê um nome à faixa (`aria-labelledby` no título dela)
76
76
  * quando ela for uma região que o leitor de tela deva listar.
77
77
  */
78
- export function Section({ surface = "background", spacing = "md", theme, className, ...props }) {
79
- return _jsx("section", { "data-theme": theme, className: cx("section", surface !== "background" && `section-${surface}`, spacing !== "md" && `section-spacing-${spacing}`, className), ...props });
78
+ // GAR-06 (07/10/2026): o rodapé de site é uma VARIAÇÃO da Section (regra do Victor: peça nova entra
79
+ // como variação), porque o rodapé é a última faixa da página: herda o fundo (`surface`), o respiro
80
+ // (`spacing`) e o tema próprio (`theme` — rodapé escuro numa página clara). Nenhuma referência da
81
+ // fila tem um rodapé aberto; o desenho é da Aurea, com tokens que já existem. Os links de cada
82
+ // coluna são `SidebarItem`, a mesma forma dos menus, e o `render` leva o link do roteador.
83
+ export function Section({ surface = "background", spacing = "md", theme, variant = "base", brand, links, legal, maxWidth = "xl", navLabel = "Footer", children, className, ...props }) {
84
+ const pele = cx("section", surface !== "background" && `section-${surface}`, spacing !== "md" && `section-spacing-${spacing}`);
85
+ if (variant !== "footer")
86
+ return _jsx("section", { "data-theme": theme, className: cx(pele, className), ...props, children: children });
87
+ return _jsx("footer", { "data-theme": theme, className: cx(pele, "section-footer", className), ...props, children: _jsxs("div", { className: cx("container", maxWidth !== "xl" && `container-${maxWidth}`), children: [_jsxs("div", { className: "section-footer-top", children: [brand != null && _jsx("div", { className: "section-footer-brand", children: brand }), links && links.length > 0 && _jsx("nav", { className: "section-footer-nav", "aria-label": navLabel, children: links.map((g, n) => _jsxs("div", { className: "section-footer-group", children: [_jsx("h2", { className: "section-footer-title", children: g.title }), _jsx("ul", { className: "section-footer-links", children: g.items.map(it => _jsx("li", { children: it.render
88
+ ? fundirRender(it.render, { className: "section-footer-link", children: it.label }, "a")
89
+ : _jsx("a", { className: "section-footer-link", href: it.href, children: it.label }) }, it.id)) })] }, n)) }), children] }), legal != null && _jsx("div", { className: "section-footer-legal", children: legal })] }) });
80
90
  }
81
91
  // ── Data Display ─────────────────────────────────────────────────────────────────────────────
82
92
  export function KPI({ label, value, trend, className, ...props }) { return _jsxs(Card, { className: cx("kpi", className), ...props, children: [_jsx("span", { className: "muted", children: label }), _jsx("strong", { children: value }), trend && _jsx("small", { children: trend })] }); }
@@ -146,11 +156,20 @@ export function AvatarGroup({ children, max, total, label, size, className }) {
146
156
  export function LogStream({ lines }) { return _jsx("div", { className: "log-stream", role: "log", "aria-live": "polite", children: lines.map((l, n) => _jsxs("div", { className: "log-line", children: [_jsx("time", { className: "log-time", children: l.time }), _jsx("span", { className: cx("log-level", l.level && l.level.toLowerCase()), children: l.level }), _jsx("span", { children: l.text })] }, n)) }); }
147
157
  // ── Media ────────────────────────────────────────────────────────────────────────────────────
148
158
  export function MediaPlayerShell({ children, className, ...props }) { return _jsx("div", { className: cx("media-player", className), ...props, children: children }); }
149
- // ── Navigation ───────────────────────────────────────────────────────────────────────────────
150
- // B-07 (24/09/2026): `divider` põe a linha de baixo na `flush`. Ela é fundo igual ao da página e
151
- // gruda no topo; sem linha, o conteúdo passa por baixo dela e nada diz onde a barra acaba. Só na
152
- // `flush`: a `floating` e a `pill` são caixas com borda própria.
153
- export function Topbar({ variant = "floating", divider, brand, children, className, ...props }) { return _jsxs("header", { className: cx("topbar", `topbar-${variant}`, divider && variant === "flush" && "topbar-divider", className), ...props, children: [brand != null && _jsx("div", { className: "brand", children: brand }), children] }); }
159
+ // O item da barra e o do painel são o MESMO elemento com a mesma pele: o atual é o atual nos dois.
160
+ function linksDoHeader(items, current) {
161
+ return _jsx("ul", { className: "topbar-links", children: items.map(it => {
162
+ const p = { className: "topbar-link", "aria-current": it.id === current ? "page" : undefined, children: it.label };
163
+ return _jsx("li", { children: it.render ? fundirRender(it.render, p, "a") : _jsx("a", { href: it.href, ...p }) }, it.id);
164
+ }) });
165
+ }
166
+ export function Header({ variant = "floating", divider, brand, items, current, actions, maxWidth, navLabel = "Main", menuLabel = "Menu", menuId = "aurea-header-menu", children, className, ...props }) {
167
+ const site = !!items && items.length > 0;
168
+ const miolo = _jsxs(_Fragment, { children: [brand != null && _jsx("div", { className: "brand", children: brand }), site && _jsx("nav", { className: "topbar-nav", "aria-label": navLabel, children: linksDoHeader(items, current) }), children, actions != null && _jsx("div", { className: "topbar-actions", children: actions }), site && _jsxs(_Fragment, { children: [_jsx("button", { type: "button", className: "btn btn-ghost btn-icon topbar-menu-toggle", popoverTarget: menuId, "aria-label": menuLabel, children: _jsx("span", { className: "topbar-menu-icon", "aria-hidden": "true" }) }), _jsx("nav", { id: menuId, popover: "auto", className: "topbar-menu-panel", "aria-label": navLabel, children: linksDoHeader(items, current) })] })] });
169
+ return _jsx("header", { className: cx("topbar", `topbar-${variant}`, divider && variant === "flush" && "topbar-divider", site && "topbar-site", maxWidth && "topbar-contained", className), ...props, children: maxWidth ? _jsx("div", { className: cx("container", maxWidth !== "xl" && `container-${maxWidth}`, "topbar-inner"), children: miolo }) : miolo });
170
+ }
171
+ /** @deprecated `Topbar` é o nome antigo do `Header` (07/10/2026). Continua funcionando, igual; use `Header`. */
172
+ export function Topbar(props) { return _jsx(Header, { ...props }); }
154
173
  // ── System / interno ─────────────────────────────────────────────────────────────────────────
155
174
  // Kbd — representação de tecla/atalho. <kbd> é o elemento HTML certo; a pele é nossa. Ele já
156
175
  // morava fora da casa dele (no `internal.tsx`, por causa do `Button`); agora mora aqui, pelo
@@ -1,2 +1,2 @@
1
1
  export * from "./navigation-client.js";
2
- export { Topbar, type TopbarVariant } from "./markup.js";
2
+ export { Header, Topbar, type HeaderVariant, type HeaderProps, type TopbarVariant } from "./markup.js";
@@ -2,4 +2,5 @@
2
2
  // `"use client"` de propósito: a diretiva contamina o módulo inteiro e faria a marcação pura
3
3
  // chegar como cliente por vizinhança (ADR-0026; o check 26b reprova quem a puser de volta aqui).
4
4
  export * from "./navigation-client.js";
5
- export { Topbar } from "./markup.js";
5
+ // `Header` é o nome de mercado do antigo `Topbar` (07/10/2026); os dois são o mesmo componente.
6
+ export { Header, Topbar } from "./markup.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aurea-uds/react",
3
- "version": "0.22.0",
3
+ "version": "0.24.0",
4
4
  "description": "Os componentes React da Aurea UDS. Importe @aurea-uds/fonts/css e @aurea-uds/core/css junto.",
5
5
  "keywords": [
6
6
  "aurea",